我想使用Node,因为它是快速的,使用与我在客户端使用的相同的语言,并且根据定义它是非阻塞的。但是我雇来写文件处理程序(保存、编辑、重命名、下载、上传文件等)的那个人,他想用apache。所以,我必须:

说服他使用Node(他在这方面几乎没有让步) 弄清楚如何上传,下载,重命名,保存等文件在节点或 我必须在同一台服务器上安装apache和node。

哪种情况是最有利的,我如何实现它?


当前回答

我将上面的答案与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”接收数据。注意,发送方不接收自己的广播。

其他回答

你可以使用不同的方法,比如用nodejs编写一个反向代理服务器来代理apache和所有其他nodejs应用程序。

首先,你需要让apache在不同的端口上运行,而不是80端口。例如:端口8080

然后你可以用nodejs写一个反向代理脚本:

var proxy = require('redbird')({port: 80, xfwd: false);

proxy.register("mydomain.me/blog", "http://mydomain.me:8080/blog");
proxy.register("mydomain.me", "http://mydomain.me:3000");

下面这篇文章描述了整个制作过程。

运行apache与node js反向代理-使用redbird

我假设你正在制作一个web应用程序,因为你提到了Apache和Node。快速回答——有可能吗?推荐吗? -不推荐。Node捆绑了自己的web服务器,大多数网站都运行在80端口上。我还假设目前没有Apache插件是由Nodejs支持的,我不确定创建一个虚拟主机是否是实现这一点的最佳方式。这些问题应该由维护Nodejs的开发者来回答,就像Joyent的那些好人一样。

而不是端口,更好的方法是评估Node的技术堆栈,它与大多数其他技术栈完全不同,这也是我喜欢它的原因,但它也涉及到一些妥协,您应该事先知道。

您的示例看起来类似于CMS或共享web应用程序,并且有数百个可用的开箱即用应用程序可以在Apache上正常运行。即使你不喜欢任何现成的解决方案,你也可以用PHP / Java / Python编写一个web应用程序,或者将它与几个现成的应用程序混合,它们都被设计和支持在一个Apache实例后运行。

是时候停下来想想我刚才说的话了。

现在您已经准备好决定要使用哪个技术堆栈了。如果你的网站永远不会使用任何一个需要Apache的现成应用程序,那么就选择Node,否则你必须首先消除我前面所说的假设。

最后,您对技术堆栈的选择比任何单个组件都重要得多。

我完全同意@Straseus的观点,使用node.js文件系统api来处理上传和下载是相对简单的,但要多考虑一下从长远来看你想从你的网站得到什么,然后选择你的技术堆栈。

学习Node的框架比学习其他框架更容易,但它不是万能的。只要稍加努力(这本身可能是有价值的努力),您也可以学习任何其他框架。我们都可以互相学习,如果你在一个小团队中工作,你会比独自工作更有效率,你的后端技术技能也会发展得更快。因此,不要轻易低估团队其他成员的技能。

这篇文章大约发布了一年,你可能已经决定了,但我希望我的咆哮能帮助下一个正在经历类似决定的人。

感谢阅读。

我也在找同样的信息。终于从上面@Straseus的答案链接中找到了答案

http://arguments.callee.info/2010/04/20/running-apache-and-node-js-together/

下面是在80端口运行apache网站,在8080端口运行node js服务并使用.htaccess RewriteRule的最终解决方案

在apache网站的DocumentRoot目录下增加如下内容:

Options +FollowSymLinks -MultiViews

<IfModule mod_rewrite.c>

RewriteEngine on

# Simple URL redirect:
RewriteRule ^test.html$ http://arguments.callee.info:8000/test/ [P]

# More complicated (the user sees only "benchmark.html" in their address bar)
RewriteRule ^benchmark.html$ http://arguments.callee.info:8000/node?action=benchmark [P]

# Redirect a whole subdirectory:
RewriteRule ^node/(.*) http://arguments.callee.info:8000/$1 [P]

对于目录级重定向,上面的链接建议使用(.+)规则,该规则要求'node/'后面有一个或多个字符。我必须将它转换为(.*),这是零或更多,我的东西才能工作。

非常感谢@Straseus的链接

我最近遇到了这种问题,在一个基于PHP的codeigniter项目中,我需要在客户端和服务器之间使用websocket进行通信。

我通过将我的端口(运行的节点应用程序)添加到允许传入的TCP端口和允许传出的TCP端口列表中来解决这个问题。

您可以在服务器的WHM面板中的防火墙配置中找到这些配置。

我将上面的答案与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”接收数据。注意,发送方不接收自己的广播。