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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9831594/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 15:22:57  来源:igfitidea点击:

Apache and Node.js on the Same Server

apachenode.js

提问by Matt

I want to use Node because it's swift, uses the same language I am using on the client side, and it's non-blocking by definition. But the guy who I hired to write the program for file handling (saving, editing, renaming, downloading, uploading files, etc.), he wants to use apache. So, I must:

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

  1. Convince him to use Node (he's giving up little ground on that)

  2. Figure out how to upload, download, rename, save, etc. files in node or

  3. I must install apache and node on the same server.

  1. 说服他使用 Node(他对此几乎没有放弃)

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

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

Which is the most favorable situation, and how do I implement that?

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

回答by Steven de Salas

Great question!

好问题!

There are many websites and free web apps implemented in PHP that run on Apache, lots of people use it so you can mash up something pretty easy and besides, its a no-brainer way of serving static content. Node is fast, powerful, elegant, and a sexy tool with the raw power of V8 and a flat stack with no in-built dependencies.

有许多在 Apache 上运行的用 PHP 实现的网站和免费 Web 应用程序,很多人都使用它,因此您可以将一些非常简单的东西混搭在一起,此外,它是一种提供静态内容的简单方法。Node 是一种快速、强大、优雅且性感的工具,具有 V8 的原始功能和没有内置依赖项的扁平堆栈。

I also want the ease/flexibility of Apache and yet the grunt and elegance of Node.JS, why can't I have both?

我还想要 Apache 的易用性/灵活性以及 Node.JS 的笨拙和优雅,为什么我不能两者兼得

Fortunately with the ProxyPassdirective in the Apache httpd.confits not too hard to pipe all requests on a particular URL to your Node.JS application.

幸运的是,使用Apache 中的ProxyPass指令,将httpd.conf特定 URL 上的所有请求通过管道传输到您的 Node.JS 应用程序并不难。

ProxyPass /node http://localhost:8000

Also, make sure the following lines are NOT commented out so you get the right proxy and submodule to reroute http requests:

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

LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so

Then run your Node app on port 8000!

然后在端口 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');

Then you can access all Node.JS logic using the /node/path on your url, the rest of the website can be left to Apache to host your existing PHP pages:

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

enter image description here

在此处输入图片说明

Now the only thing left is convincing your hosting company let your run with this configuration!!!

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

回答by Iain Collins

This question belongs more on Server Faultbut FWIW I'd say running Apache in front of Node.js is not a good approach in most cases.

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

Apache's ProxyPass is awesome for lots of things (like exposing Tomcat based services as part of a site) and if your Node.js app is just doing a specific, small role or is an internal tool that's only likely to have a limited number of users then it might be easier just to use it so you can get it working and move on, but that doesn't sound like the case here.

Apache 的 ProxyPass 在很多方面都很棒(例如将基于 Tomcat 的服务作为站点的一部分公开),并且如果您的 Node.js 应用程序只是执行特定的小角色,或者是仅可能拥有有限数量用户的内部工具那么使用它可能会更容易,这样你就可以让它工作并继续前进,但这听起来不像这里的情况。

If you want to take advantage of the performance and scale you'll get from using Node.js - and especially if you want to use something that involves maintaining a persistent connection like web sockets - you are better off running both Apache and your Node.js on other ports (e.g. Apache on localhost:8080, Node.js on localhost:3000) and then running something like nginx, Varnish or HA proxy in front - and routing traffic that way.

如果您想利用 Node.js 带来的性能和规模优势——尤其是如果您想使用涉及维护网络套接字等持久连接的东西时——最好同时运行 Apache 和 Node.js。在其他端口上运行 Node.js(例如 localhost:8080 上的 Apache,localhost:3000 上的 Node.js),然后在前面运行诸如 nginx、Varnish 或 HA 代理之类的东西 - 并以这种方式路由流量。

With something like varnish or nginx you can route traffic based on path and/or host. They both use much less system resources and is much more scalable that using Apache to do the same thing.

使用 varnish 或 nginx 之类的东西,您可以根据路径和/或主机路由流量。它们都使用更少的系统资源,并且比使用 Apache 做同样的事情更具可扩展性。

回答by krmld


Instructions to run node serveralong apache2(v2.4.xx) server:

In order to pipe all requests on a particular URL to your Node.JS application create CUSTOM.conffile inside /etc/apache2/conf-availabledirectory, and add following line to the created file:


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

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

ProxyPass /node http://localhost:8000/

Change 8000 to the prefered port number for node server.
Enable custom configurations with following command:

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

$> sudo a2enconf CUSTOM

CUSTOM is your newly created filename without extension, then enable proxy_httpwith the command:

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

$> sudo a2enmod proxy_http

it should enable both proxyand proxy_httpmodules. You can check whether module is enabled or not with:

它应该同时启用proxyproxy_http模块。您可以通过以下方式检查模块是否已启用:

$> sudo a2query -m MODULE_NAME

After configuration and modules enabled, you will need to restart apache server:

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

$> sudo service apache2 restart

Now you can execute node server. All requests to the URL/nodewill be handled by node server.

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

回答by Yarek T

Running Node and Apache on one server is trivial as they don't conflict. NodeJS is just a way to execute JavaScript server side. The real dilemma comes from accessing both Node and Apache from outside. As I see it you have two choices:

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

  1. Set up Apache to proxy all matching requests to NodeJS, which will do the file uploading and whatever else in node.

  2. Have Apache and Node on different IP:port combinations (if your server has two IPs, then one can be bound to your node listener, the other to Apache).

  1. 设置 Apache 将所有匹配的请求代理到 NodeJS,NodeJS 将执行文件上传和 node.js 中的任何其他操作。

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

I'm also beginning to suspect that this might not be what you are actually looking for. If your end goal is for you to write your application logic in Nodejs and some "file handling" part that you off-load to a contractor, then its really a choice of language, not a web server.

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

回答by wathmal

You can use a different approach such as writing a reverse proxy server with nodejs to proxy both apache and all other nodejs apps.

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

First you need to make apache run on a different port other than port 80. ex: port 8080

首先,您需要让 apache 在端口 80 以外的其他端口上运行。例如:端口 8080

Then you can write a reverse proxy script with nodejs as:

然后你可以用 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");

Following article describes the whole process of making this.

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

RUN APACHE WITH NODE JS REVERSE PROXY – USING REDBIRD

使用 Node JS 反向代理运行 APACHE – 使用 REDBIRD

回答by rahul shukla

ProxyPass /node http://localhost:8000/     
  • this worked for me when I made above entry in httpd-vhosts.conf instead of httpd.conf
  • I have XAMPP installed over my environment & was looking to hit all the traffic at apache on port 80 with NodeJS applicatin running on 8080 port i.e. http://localhost/[name_of_the_node_application]
  • 当我在 httpd-vhosts.conf 而不是 httpd.conf 中进行上述条目时,这对我有用
  • 我在我的环境中安装了 XAMPP,并希望通过在 8080 端口上运行的 NodeJS 应用程序在端口 80 上访问 apache 上的所有流量,即http://localhost/[name_of_the_node_application]

回答by Dr. Aaron Dishno

I combined the answer above with certbot SSL cert and CORS access-control-allow-headers and got it working so I thought I would share the results.

我将上面的答案与 certbot SSL cert 和 CORS access-control-allow-headers 结合起来并让它工作,所以我想我会分享结果。

Apache httpd.conf added to the bottom of the file:

Apache httpd.conf 添加到文件底部:

LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so

Apache VirtualHost settings (doc root for PHP is under Apache and SSL with Certbot, while node.js/socket.io site runs on port 3000 - and uses SSL cert from Apache) Also notice the node.js site uses the proxy for the folder /nodejs, socket.io, and ws (websockets):

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/  [P,L]

    RewriteCond %{HTTP:Connection} Upgrade [NC]
    RewriteRule /(.*) ws://localhost:3000/ [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>

Then my node.js app (app.js):

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

I force a ip4 listener, but that is optional - you can substitute:

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

http.listen(3000);

node.js app (app.js) code continues with:

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...
});

finally, on the client side (created as nodejs.js):

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

In this example when the JS loads, it will emit to the socket a "named-event" sending the data in JSON to the node.js/socket.io server.

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

Using the io and socket on the server under path /nodejs (connected by client), receives the data an then resends it as a broadcast. Any other users in the socket would receive the data with their listener "named-event-broadcast". Note that the sender does not receive their own broadcast.

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

回答by Paritosh Pandey

I recently ran into this kinda issue, where I need to communicate between client and server using websocket in a PHP based codeigniter project.

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

I resolved this issue by adding my port(node app running on) into Allow incoming TCP ports& Allow outgoing TCP portslists.

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

You can find these configurations in Firewall Configurationsin your server's WHM panel.

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

回答by pd1980

I was looking for the same information. Finally found the answer from the link on the answer above by @Straseus

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

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

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

Here is the final solution to run apache website on port 80, node js service on port 8080 and use .htaccess RewriteRule

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

In the DocumentRoot of the apache website, add the following:

在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/ [P]

For the directory level redirect, the link above suggested (.+) rule, which requires one or more character after the 'node/'. I had to convert it to (.*) which is zero or more for my stuff to work.

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

Thanks a lot for the link @Straseus

非常感谢@Straseus的链接

回答by RHT

I am assuming that you are making a web app because you refer to Apache and Node. Quick answer - Is it possible - YES. Is it recommended - NO. Node bundles it's own webserver and most websites run on port 80. I am also assuming that there is currently no Apache plugin which is supported by Nodejs and I am not sure if creating a virtual host is the best way to implement this. These are the questions that should be answered by developers who maintain Nodejs like the good folks at Joyent.

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

Instead of ports, it would be better to evaluate Node's tech stack which is completely different from most others and which is why I love it but it also involves a few compromises that you should be aware of in advance.

除了端口,最好评估 Node 的技术堆栈,它与大多数其他技术堆栈完全不同,这就是我喜欢它的原因,但它也涉及一些您应该提前了解的妥协。

Your example looks similar to a CMS or a sharing web app and there are hundreds of out of the box apps available that will run just fine on Apache. Even if you do not like any readymade solution, you could write a webapp in PHP / Java / Python or mix n match it with a couple of ready made apps and they are all designed and supported to run behind a single instance of Apache.

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

It's time to pause and think about what I just said.

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

Now you are ready to decide on which techstack you are going to use. If your website will never use any out of the thousands of ready made apps that require Apache, then go for Node otherwise you must first eliminate the assumptions that I have stated earlier.

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

In the end, your choice of techstack is way more important than any individual component.

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

I completely agree with @Straseus that it is relatively trivial to use node.js file system api for handling uploads and downloads but think more about what you want from your website in the long run and then choose your techstack.

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

Learning Node's framework is easier than learning other frameworks but it is not a panacea. With a slightly more effort (which may be a worthwhile endeavor in itself), you can learn any other framework too. We all learn from each other and you will be more productive if you are working as a small team than if you are working alone and your backend technical skills will also develop faster. Therefore, do not discount the skills of other members of your team so cheaply.

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

This post is about a year old and chances are that you have already decided but I hope that my rant will help the next person who is going through a similar decision.

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

Thanks for reading.

谢谢阅读。