我想使用Node,因为它是快速的,使用与我在客户端使用的相同的语言,并且根据定义它是非阻塞的。但是我雇来写文件处理程序(保存、编辑、重命名、下载、上传文件等)的那个人,他想用apache。所以,我必须:
说服他使用Node(他在这方面几乎没有让步) 弄清楚如何上传,下载,重命名,保存等文件在节点或 我必须在同一台服务器上安装apache和node。
哪种情况是最有利的,我如何实现它?
我想使用Node,因为它是快速的,使用与我在客户端使用的相同的语言,并且根据定义它是非阻塞的。但是我雇来写文件处理程序(保存、编辑、重命名、下载、上传文件等)的那个人,他想用apache。所以,我必须:
说服他使用Node(他在这方面几乎没有让步) 弄清楚如何上传,下载,重命名,保存等文件在节点或 我必须在同一台服务器上安装apache和node。
哪种情况是最有利的,我如何实现它?
当前回答
好问题!
有许多网站和免费的web应用程序是用PHP实现的,在Apache上运行,很多人使用它,所以你可以很容易地混合一些东西,此外,它是一种简单的静态内容服务方式。Node快速、强大、优雅,是一个性感的工具,拥有V8的原始功能和没有内置依赖的扁平堆栈。
我也想要Apache的简单/灵活,但Node.JS的粗粝和优雅,为什么我不能两者兼得呢?
幸运的是,使用Apache httpd.conf中的ProxyPass指令,将特定URL上的所有请求输送到Node.JS应用程序并不太难。
ProxyPass /node http://localhost:8000
另外,确保以下行没有被注释掉,这样你就可以得到正确的代理和子模块来重新路由http请求:
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
然后在端口8000上运行Node应用程序!
var http = require('http');
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello Apache!\n');
}).listen(8000, '127.0.0.1');
然后你可以使用url上的/node/路径访问所有node . js逻辑,网站的其余部分可以留给Apache来托管你现有的PHP页面:
现在剩下的唯一一件事就是说服你的托管公司让你运行这个配置!!
其他回答
我将上面的答案与certbot SSL cert和CORS access-control-allow-headers结合起来,并使其工作,因此我认为我将分享结果。
Apache httpd.conf添加到文件底部:
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
Apache VirtualHost设置(PHP的doc根目录在Apache和SSL的Certbot下,而node.js/socket。io站点运行在端口3000 -并使用SSL证书从Apache) 还要注意node.js站点使用了文件夹/nodejs,套接字的代理。Io和ws (websockets):
<IfModule mod_ssl.c>
<VirtualHost *:443>
ServerName www.example.com
ServerAlias www.example.com
DocumentRoot /var/html/www.example.com
ErrorLog /var/html/log/error.log
CustomLog /var/html/log/requests.log combined
SSLCertificateFile /etc/letsencrypt/live/www.example.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/www.example.com/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf
RewriteEngine On
RewriteCond %{REQUEST_URI} ^socket.io [NC]
RewriteCond %{QUERY_STRING} transport=websocket [NC]
RewriteRule /{.*} ws://localhost:3000/$1 [P,L]
RewriteCond %{HTTP:Connection} Upgrade [NC]
RewriteRule /(.*) ws://localhost:3000/$1 [P,L]
ProxyPass /nodejs http://localhost:3000/
ProxyPassReverse /nodejs http://localhost:3000/
ProxyPass /socket.io http://localhost:3000/socket.io
ProxyPassReverse /socket.io http://localhost:3000/socket.io
ProxyPass /socket.io ws://localhost:3000/socket.io
ProxyPassReverse /socket.io ws://localhost:3000/socket.io
</VirtualHost>
</IfModule>
然后我的node.js app (app.js):
var express = require('express');
var app = express();
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "X-Requested-With");
res.header("Access-Control-Allow-Headers", "Content-Type");
res.header("Access-Control-Allow-Methods", "PUT, GET, POST, DELETE, OPTIONS");
next();
});
var http = require('http').Server(app);
var io = require('socket.io')(http);
http.listen({host:'0.0.0.0',port:3000});
我强制一个ip4监听器,但这是可选的-你可以替换:
http.listen(3000);
Node.js应用程序(app.js)代码继续:
io.of('/nodejs').on('connection', function(socket) {
//optional settings:
io.set('heartbeat timeout', 3000);
io.set('heartbeat interval', 1000);
//listener for when a user is added
socket.on('add user', function(data) {
socket.join('AnyRoomName');
socket.broadcast.emit('user joined', data);
});
//listener for when a user leaves
socket.on('remove user', function(data) {
socket.leave('AnyRoomName');
socket.broadcast.emit('user left', data);
});
//sample listener for any other function
socket.on('named-event', function(data) {
//code....
socket.broadcast.emit('named-event-broadcast', data);
});
// add more listeners as needed... use different named-events...
});
最后,在客户端(创建为nodejs.js):
//notice the /nodejs path
var socket = io.connect('https://www.example.com/nodejs');
//listener for user joined
socket.on('user joined', function(data) {
// code... data shows who joined...
});
//listener for user left
socket.on('user left', function(data) {
// code... data shows who left...
});
// sample listener for any function:
socket.on('named-event-broadcast', function(data) {
// this receives the broadcast data (I use json then parse and execute code)
console.log('data1=' + data.data1);
console.log('data2=' + data.data2);
});
// sample send broadcast json data for user joined:
socket.emit('user joined', {
'userid': 'userid-value',
'username':'username-value'
});
// sample send broadcast json data for user left
//(I added the following with an event listener for 'beforeunload'):
// socket.emit('user joined', {
// 'userid': 'userid-value',
// 'username':'username-value'
// });
// sample send broadcast json data for any named-event:
socket.emit('named-event', {
'data1': 'value1',
'data2':'value2'
});
在这个例子中,当JS加载时,它会向套接字发出一个“named-event”,将JSON格式的数据发送到node.js/socket。io服务器。
使用服务器上路径/nodejs下的io和socket(通过客户端连接),接收数据,然后将其作为广播重新发送。套接字中的任何其他用户将通过他们的侦听器“named-event-broadcast”接收数据。注意,发送方不接收自己的广播。
这个问题更多地属于服务器故障,但我想说的是,在大多数情况下,在Node.js之前运行Apache并不是一个好方法。
Apache的ProxyPass对于很多事情来说都很棒(比如将基于Tomcat的服务作为站点的一部分公开),如果你的Node.js应用只是在做一个特定的、小的角色,或者是一个内部工具,只可能有有限数量的用户,那么使用它可能会更容易,这样你就可以让它工作并继续前进,但这里听起来不是这样的情况。
如果你想利用使用Node.js获得的性能和规模,特别是如果你想使用一些涉及维护持久连接的东西,比如web套接字,你最好在其他端口上运行Apache和Node.js(例如Apache在localhost上:8080,Node.js在localhost上:3000),然后在前面运行像nginx, Varnish或HA代理之类的东西,并以这种方式路由流量。
使用像varnish或nginx这样的东西,你可以基于路径和/或主机路由流量。它们都使用更少的系统资源,并且比使用Apache做同样的事情更具可伸缩性。
ProxyPass /node http://localhost:8000/
当我在httpd-vhosts.conf而不是httpd.conf中做上述条目时,这对我来说是有效的 我已经在我的环境中安装了XAMPP,并希望在apache的80端口上使用NodeJS应用程序运行在8080端口上,即http://localhost/[name_of_the_node_application]
在一台服务器上运行Node和Apache很简单,因为它们并不冲突。NodeJS只是一种执行JavaScript服务器端的方式。真正的困境来自于从外部同时访问Node和Apache。在我看来,你有两个选择:
设置Apache将所有匹配的请求代理给NodeJS,后者将在node中执行文件上传和其他任何操作。 让Apache和Node在不同的IP:端口组合上(如果您的服务器有两个IP,那么一个可以绑定到您的节点侦听器,另一个绑定到Apache)。
我也开始怀疑这可能不是你真正想要的。如果你的最终目标是用Nodejs编写应用程序逻辑,并将一些“文件处理”部分卸载给承包商,那么这实际上是语言的选择,而不是web服务器。
我最近遇到了这种问题,在一个基于PHP的codeigniter项目中,我需要在客户端和服务器之间使用websocket进行通信。
我通过将我的端口(运行的节点应用程序)添加到允许传入的TCP端口和允许传出的TCP端口列表中来解决这个问题。
您可以在服务器的WHM面板中的防火墙配置中找到这些配置。