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

时间:2012-03-22 22:37:41

标签: apache node.js

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

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

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

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

  4. 哪种情况最有利,我该如何实施呢?

10 个答案:

答案 0 :(得分:668)

很棒的问题!

在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');

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

enter image description here

现在唯一剩下的就是说服您的托管公司让您使用此配置运行!!!

答案 1 :(得分:54)

这个问题更多地放在Server Fault上,但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做同样的事情具有更大的可扩展性。

答案 2 :(得分:29)


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

为了将特定URL上的所有请求传递给Node.JS应用程序,在CUSTOM.conf目录中创建/etc/apache2/conf-available文件,并在创建的文件中添加以下行:

ProxyPass /node http://localhost:8000/

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

$> sudo a2enconf CUSTOM

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

$> sudo a2enmod proxy_http

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

$> sudo a2query -m MODULE_NAME

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

$> sudo service apache2 restart

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

答案 3 :(得分:14)

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

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

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

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

答案 4 :(得分:8)

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

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

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

答案 5 :(得分:5)

我将上面的答案与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的文档根目录位于Apache和Certbot的SSL下,而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>

然后我的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});

我强制使用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加载时,它将向套接字发出“命名事件”,将JSON中的数据发送到node.js / socket.io服务器。

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

答案 6 :(得分:0)

ProxyPass /node http://localhost:8000/     
  • 当我在httpd-vhosts.conf而不是httpd.conf
  • 上面输入时,这对我有用
  • 我在我的环境中安装了XAMPP&amp;希望在80端口上运行NodeJS应用程序,即http://localhost/[name_of_the_node_application]
  • ,以便在端口80上访问apache的所有流量

答案 7 :(得分:0)

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

我通过将端口(正在运行的节点应用)添加到Allow incoming TCP portsAllow outgoing TCP ports列表中来解决了此问题。

您可以在服务器的WHM面板的Firewall Configurations中找到这些配置。

答案 8 :(得分:-1)

我一直在寻找相同的信息。最后通过@Straseus上面的答案链接找到答案

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

这是在端口80上运行apache网站的最终解决方案,在端口8080上运行节点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

答案 9 :(得分:-2)

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

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

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

现在是时候停下来思考我刚刚说的话。

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

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

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

学习节点的框架比学习其他框架更容易,但它不是灵丹妙药。稍加努力(这可能是一项值得努力的事情),您也可以学习任何其他框架。我们都互相学习,如果你作为一个小团队工作,你会比你独自工作更有效率,你的后端技术技能也会更快地发展。因此,不要如此便宜地低估团队其他成员的技能。

这篇文章大约有一年的历史,很有可能你已经决定,但我希望我的咆哮会帮助下一个做出类似决定的人。

感谢阅读。