同一服务器上的Apache和Node.js

Mat*_*att 341 apache node.js

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

  1. 说服他使用Node(他放弃了一点点)

  2. 弄清楚如何在节点或文件中上传,下载,重命名,保存等文件

  3. 我必须在同一台服务器上安装apache和node.

哪个是最有利的情况,我该如何实现呢?

Ste*_*las 687

好问题!

PHP中运行的许多网站和免费网络应用程序都在Apache上运行,许多人使用它,因此您可以轻松地混搭一些东西,此外,它是一种提供静态内容的简单方法.Node是快速,强大,优雅,性感的工具,具有V8的原始功能和没有内置依赖关系的扁平堆栈.

我也想要Apache的轻松/灵活性以及Node.JS的咕噜和优雅,为什么我不能同时拥有它们

幸运的是,使用Apache中的ProxyPass指令,将httpd.conf特定URL上的所有请求传递给Node.JS应用程序并不困难.

ProxyPass /node http://localhost:8000
Run Code Online (Sandbox Code Playgroud)

此外,请确保未注释掉以下行,以便您获得正确的代理和子模块以重新路由http请求:

LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
Run Code Online (Sandbox Code Playgroud)

然后在端口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');
Run Code Online (Sandbox Code Playgroud)

然后,您可以使用/node/网址上的路径访问所有Node.JS逻辑,网站的其余部分可以留给Apache来托管您现有的PHP页面:

在此输入图像描述

现在唯一剩下的就是说服你的托管公司让你运行这个配置!

  • 我测试了将"ProxyPass/http://127.0.0.1:8000/"放在虚拟主机容器中,并且能够成功地将整个域组重定向到节点实例.我还测试了"time wget ..."来比较直接访问节点的速度以及通过Apache访问它的速度.在30对试验中,平均差异约为0.56ms.直接和通过Apache的最低加载时间为120毫秒.直接的最高加载时间为154ms,Apache的加载时间为164.没有显着差异.如果我有两个IP的奢侈,我不会通过Apache,但现在我将坚持使用Proxypass (11认同)
  • 这是一个很好的答案,只是想添加一个链接,其中包含我用于完成此工作的代理传递的更多信息.检查评论.http://boriskuzmanovic.wordpress.com/2006/10/20/apaches-proxypass-on-ubuntu/ (6认同)
  • 这不是从Apache到Node的代理请求,而是它带走了Node的非阻塞性质的好处吗? (5认同)
  • 我在哪里添加基于debian的发行版?没有httpd.conf文件. (4认同)
  • 嗨,@ Basj,我自己没有安装对websockets的支持的经验。话虽如此,Apache 2.4.6似乎支持使用`mod_proxy_wstunnel`代理代理websockets通信。我看到您现在已经找到答案了,对于其他有相同问题的人,请参考:http://serverfault.com/questions/616370/configuring-apache-2-4-mod-proxy-wstunnel-for-socket-io- 1-0 / 623027#623027 (2认同)

Iai*_*ins 60

这个问题更多地依赖于服务器故障但是FWIW我会说在Node.js之前运行Apache在大多数情况下并不是一个好方法.

Apache的ProxyPass很多东西都很棒(比如将基于Tomcat的服务暴露为网站的一部分),如果你的Node.js应用程序只是做一个特定的小角色,或者是一个内部工具,它只能拥有有限数量的用户然后它可能更容易使用它,所以你可以让它工作并继续前进,但这听起来不像这里的情况.

如果你想利用Node.js所带来的性能和规模 - 特别是如果你想使用一些涉及维护像web套接字这样的持久连接的东西 - 你最好同时运行Apache和你的Node. js在其他端口上(例如本地主机上的Apache:8080,localhost:3000上的Node.js),然后在前面运行nginx,Varnish或HA代理之类的东西 - 并以这种方式路由流量.

使用varnish或nginx之类的东西,您可以根据路径和/或主机路由流量.它们都使用更少的系统资源,并且使用Apache执行相同的操作更具可伸缩性.

  • 这个答案应该有更多的赞成.使用nginx代理比使用apache更好的方法. (12认同)
  • 我同意 Nginx 更快,但是这样你就需要配置和管理额外的服务。由于问题要求 Apache 和 Node 在同一台服务器上,看起来 Nginx 有点像第三轮。 (2认同)

krm*_*mld 33


说明运行node server沿apache2(v2.4.xx) server:

为了管在一个特定的URL的所有请求您的Node.js应用程序创建CUSTOM.conf的内部文件/etc/apache2/conf-available目录,并添加以下行创建的文件:

ProxyPass /node http://localhost:8000/
Run Code Online (Sandbox Code Playgroud)

将8000更改为首选端口号node server.
使用以下命令启用自定义配置:

$> sudo a2enconf CUSTOM
Run Code Online (Sandbox Code Playgroud)

CUSTOM是您新创建的没有扩展名的文件名,然后proxy_http使用以下命令启用:

$> sudo a2enmod proxy_http
Run Code Online (Sandbox Code Playgroud)

它应该启用两个proxyproxy_http模块.您可以使用以下命令检查模块是否已启用:

$> sudo a2query -m MODULE_NAME
Run Code Online (Sandbox Code Playgroud)

启用配置和模块后,您需要重启apache服务器:

$> sudo service apache2 restart
Run Code Online (Sandbox Code Playgroud)

现在您可以执行节点服务器.对URL/node节点的所有请求都将由节点服务器处理.


Yar*_*k T 15

在一台服务器上运行Node和Apache是​​微不足道的,因为它们不会发生冲突.NodeJS只是一种执行JavaScript服务器端的方法.真正的困境来自于从外部访问Node和Apache.我认为你有两个选择:

  1. 设置Apache以代理对NodeJS的所有匹配请求,NodeJS将执行文件上载以及节点中的任何其他内容.

  2. 让Apache和Node在不同的IP:端口组合上(如果你的服务器有两个IP,那么一个可以绑定到你的节点监听器,另一个绑定到Apache).

我也开始怀疑这可能不是你真正想要的.如果您的最终目标是在Nodejs中编写应用程序逻辑,并将一些"文件处理"部分卸载到承包商,那么它实际上是一种语言选择,而不是Web服务器.


wat*_*mal 9

您可以使用不同的方法,例如使用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");
Run Code Online (Sandbox Code Playgroud)

下面的文章描述了制作它的整个过程.

http://wathmal.xyz/run-apache-with-node-js-reverse-proxy/


Dr.*_*hno 7

我将上面的答案与 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
Run Code Online (Sandbox Code Playgroud)

Apache VirtualHost 设置(PHP 的文档根目录在 Apache 和 SSL 下,使用 Certbot,而 node.js/socket.io 站点在端口 3000 上运行 - 并使用来自 Apache 的 SSL 证书)还要注意 node.js 站点使用文件夹的代理/nodejs、socket.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>
Run Code Online (Sandbox Code Playgroud)

然后我的 node.js 应用程序(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});
Run Code Online (Sandbox Code Playgroud)

我强制使用 ip4 侦听器,但这是可选的 - 您可以替换:

http.listen(3000);
Run Code Online (Sandbox Code Playgroud)

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...
});
Run Code Online (Sandbox Code Playgroud)

最后,在客户端(创建为 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'
});
Run Code Online (Sandbox Code Playgroud)

在这个例子中,当 JS 加载时,它会向套接字发出一个“命名事件”,将 JSON 中的数据发送到 node.js/socket.io 服务器。

使用服务器上路径/nodejs(由客户端连接)下的io和socket,接收数据,然后将其作为广播重新发送。套接字中的任何其他用户都将通过其侦听器“命名事件广播”接收数据。请注意,发送方不会收到他们自己的广播。