Node.js“服务器”与Nginx或Apache服务器相比有何区别?

140

最近我一直在学习Node.js,看到了一些关于编写简单基于Node.js的服务器的资料。例如下面这个。

var express = require("express"),
http = require("http"), app;

// Create our Express-powered HTTP server
// and have it listen on port 3000
app = express();
http.createServer(app).listen(3000);

// set up our routes
app.get("/hello", function (req, res) {
    res.send("Hello World!");
});

app.get("/goodbye", function (req, res) {
    res.send("Goodbye World!");
});

现在,虽然我似乎理解了代码中正在进行的事情,但术语让我有些困惑。当我听到"server"这个词时,我会想到像Apache或Nginx这样的东西。我习惯于将它们看作是可以容纳我的Web应用程序的容器。Node.js服务器与Nginx / Apache服务器有何不同?难道不能将基于Node.js的服务器(即代码)放置在类似Nginx中以运行吗?那么为什么两者都被称为"服务器"?


2
不是的,那是错误的。 - Jaromanda X
1
从技术上讲,您可以运行应用程序并使用Node向客户端提供服务,有效地填充Web服务器的角色,但您可能会尝试做过多。我最近阅读了这篇关于此主题的好文章:https://www.nginx.com/blog/nginx-vs-apache-our-view/ - datafunk
1
让我澄清一下,当我询问两者之间的区别时,我并不是在谈论Apache与Nginx的区别。我是在谈论Node.js与Nginx的区别。 - Grateful
1
不要被标题所误导。如果你阅读了文章,你就会明白为什么我这样说,虽然你可以自己做,但你可能不想这样做... - datafunk
3个回答

218

是的,这是一个服务器。

Node.js Web应用程序与Nginx或Apache一样都是完整的Web服务器。

确实可以不使用其他Web服务器来提供Node.js应用程序。只需更改您的代码:

app = express();
http.createServer(app).listen(80); // serve HTTP directly

确实,一些项目使用node.js作为前端负载均衡器来负载其他服务器(包括Apache)。

请注意,node.js并不是唯一可以做到这一点的开发堆栈。Go、Java和Swift的Web开发框架也可以做到这一点。

为什么?

起初是CGI。CGI很好,运行得还可以。Apache收到请求后,找到URL需要执行CGI应用程序,执行该CGI应用程序并将数据作为环境变量传递,读取stdout并将数据返回给浏览器。

问题在于速度慢。当CGI应用程序是一个小的静态编译C程序时,还好,但是一组小的静态编译C程序变得难以维护。因此,人们开始使用脚本语言编写程序。后来,这也变得难以维护,人们开始开发面向对象的MVC框架。现在我们遇到了麻烦——即使没有任何动态内容需要提供(因为框架需要确定没有任何动态内容需要提供),每个请求都必须编译所有这些类并创建所有这些对象,以提供一些HTML。

如果我们不需要每个请求都创建所有这些对象呢?

人们就这样想。尝试解决这个问题产生了几种策略。最早的策略之一是直接在Web服务器中嵌入解释器,如Apache中的mod_php。编译的类和对象可以存储在全局变量中,因此可以缓存。另一种策略是进行预编译。还有一种策略是将应用程序作为常规服务器进程运行,并使用自定义协议(例如FastCGI)与Web服务器通信。

然后,一些开发人员开始简单地使用HTTP作为他们的应用程序->服务器协议。实际上,该应用程序也是一个HTTP服务器。这样做的优点是您无需实现任何新的、可能有错误、可能未经测试的协议,您可以直接使用Web浏览器(或常见的curl)调试您的应用程序。您不需要修改Web服务器以支持您的应用程序,只需要支持反向代理或重定向的任何Web服务器即可。

为什么要使用Apache/Nginx?

当您提供node.js应用程序时,请注意您是您自己的Web服务器的作者。您的应用程序中的任何潜在错误都是可以直接利用的互联网上的漏洞。有些人(理所当然地)对此感到不舒服。

在您的node.js应用程序前面添加Apache或Nginx层意味着您在互联网上使用经过实战检验的、安全加固的软件作为与您的应用程序接口的接口。这增加了一点点延迟(反向代理),但大多数人认为这是值得的。

在node.js早期,这曾经是标准建议。但现在,也有一些站点和Web服务直接将node.js暴露给互联网。 http.Server模块现在在互联网上已经相当经过实践检验,可以信任。


2
我在类似的SO线程中读到,将Nginx或Apache层放在Node前面会“削弱其非阻塞特性”。对此有何想法? - MrfksIV
11
@MrfksIV,Nginx和Apache2都是非阻塞的。实际上,在Node.js出现之前,它们就已经实现了非阻塞。不要使用Apache1。 - slebetman
有关node-cgi使用的架构,您有什么想法吗?我印象中它是经典的基于线程的架构(因此每个请求都有自己的线程),而我需要一个具有基于事件的架构的托管提供商(每个请求在同一线程上处理)。如果我不想要云服务、docker等,只需要运行nodejs、支持websockets等的东西,我不知道哪个托管提供商支持这种类型的架构。 - inf3rno
@inf3rno 如果是CGI,那么它就是CGI,因此在扩展方面最糟糕的架构,因为它消耗大量RAM。然而,节点进程通常只需要在启动时占用约30MB的内存,因此不像Java这样糟糕。CGI甚至不是基于线程的。它是基于进程的。每个请求都会生成一个新进程(应用程序),并使用环境变量将数据发送到进程中(是的,按照现代标准来说有些尴尬,但如果您刚学习Unix上的C编程,那么您不需要学习任何关于tcp/ip或套接字的知识,这很容易)。 - slebetman
@inf3rno,如果你想托管一个支持Node的Web应用程序,Heroku是最受欢迎的方式之一。还有很多提供node.js托管的服务提供商。只需在谷歌上搜索“nodejs托管”即可。但是,即使您最终不使用它,我也鼓励您看看AWS。他们提供1年免费账户。他们提供从虚拟硬件(您可以安装任何想要的操作系统)到容器运行器(您可以上传Docker镜像以运行)再到应用程序运行器(您只需提供代码)甚至运行单个函数的所有内容,而无需提供完整的应用程序。 - slebetman
显示剩余5条评论

24

Node.js创建自己的服务器。正如您所看到的,术语非常清晰:

http.createServer(app).listen(3000);
创建一个服务器并在端口3000上监听HTTP请求。
我们在其中一个项目中使用了nginx,但更像是多个nodejs实例的负载均衡器。
假设您有两个运行在端口3000和3001上的nodejs实例, 现在您仍然可以使用nginx作为服务器来侦听实际的http调用,并且可能希望将您的请求重定向到nodejs服务器或其他一些服务器,更像一个loadbalancer。 因此,您仍然可以使用nginx提供的任何功能与nodejs一起使用。
已经在这里问了一个好问题。

3
我其实并不是太关注 nginx 本身,我在想 node.js 的 "服务器" 和其他 "服务器"(比如 apache 或者 nginx)之间的区别。我不明白如何将其中的内容(即 node 代码)与容器(即 apache)相等价……但我想我对此的理解是错误的。现在,我意识到 node.js 代码像 Apache 一样监听端口 3000……所以它们很相似。那么,他们都是有自己的优缺点的服务器,这种说法是否正确? - Grateful
4
createServer 只是创建一个监听端口,它并不提供任何服务。 - Roger F. Gay
1
如果nodejs在端口上使用createServer进行监听,但不会在请求该端口时提供任何服务,那么这样做的意义是什么呢?因此,从逻辑上讲,它无论如何都是一种“服务器”,不是吗? - GG2
@RogerF.Gay... 它在指定的端口上创建一个监听器,并在收到请求时执行回调函数。这就是我所说的它创建了一个服务器。 - Naeem Shaikh
1
@Naeem Shaikh 这没有任何作用。称呼一个没有任何作用的东西为服务器是没有意义的。 - Roger F. Gay

12
假设有一家酒店名为Apache Hotel,每位顾客都有一个服务员。当顾客点了沙拉后,服务员会去告诉厨师。在厨师准备菜品期间,服务员会等待。这里的情况是:

厨师 => 文件系统,

服务员 => 线程,

顾客 => 事件.

即使顾客只点了水,服务员也会等到沙拉端出来后才会送来。服务员会不断等待直到厨师准备好沙拉。这种状态称为阻塞状态。即使酒店扩大,每个顾客也应该有不同的服务员来服务以避免线程(服务员)的阻塞。
现在,我们来看Node Hotel,所有顾客只有一个服务员。如果第一个顾客点了汤,服务员会告诉厨师然后去接待第二个顾客。食物准备好后,服务员会把食物送给相应的顾客。这里,顾客不需要等待。这种状态称为非阻塞状态。单个服务员(线程)为所有顾客提供服务,并使他们满意。
因此,Node是一个单线程应用程序,速度非常快。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接