我最近一直在研究 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!");
});
现在,虽然我似乎理解了代码中发生的事情,但我对术语感到有些困惑。当我听到服务器这个词时,我会想到 Apache 或 Nginx 之类的东西。我习惯于将它们视为可以容纳我的 Web 应用程序的容器。 Node.js 服务器与 Nginx/Apache 服务器有何不同?基于 Node.js 的服务器(即代码)是否仍然可以放置在 Nginx 之类的东西中运行?那么为什么两者都被称为“服务器”呢?
Isn't it true that a Node.js based server (i.e. code) will still be placed within something like Nginx to run?
不,这是不正确的
是的,是服务器。
node.js Web 应用程序是一个成熟的 Web 服务器,就像 Nginx 或 Apache。
您确实可以在不使用任何其他 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 应用程序并将数据作为环境变量传递,读取标准输出并将数据返回给浏览器。
问题是它很慢。当 CGI 应用程序是一个小型静态编译的 C 程序但一组小型静态编译的 C 程序变得难以维护时,这没关系。所以人们开始用脚本语言写作。然后这变得难以维护,人们开始开发面向对象的 MVC 框架。现在我们开始遇到麻烦了——每个请求都必须编译所有这些类并创建所有这些对象,以提供一些 HTML,即使没有动态服务(因为框架需要确定没有动态服务)。
如果我们不需要在每个请求中创建所有这些对象怎么办?
那是人们的想法。试图解决这个问题产生了几种策略。最早的方法之一是将解释器直接嵌入到 Web 服务器中,例如 Apache 中的 mod_php
。编译的类和对象可以存储在全局变量中,因此可以缓存。另一种策略是进行预编译。另一种策略是将应用程序作为常规服务器进程运行,并使用自定义协议(如 FastCGI)与 Web 服务器通信。
然后一些开发人员开始简单地使用 HTTP 作为他们的应用程序->服务器协议。实际上,该应用程序也是一个 HTTP 服务器。这样做的好处是您不需要实现任何新的、可能有错误的、可能未经测试的协议,并且您可以直接使用网络浏览器(或者通常,curl
)调试您的应用程序。而且您不需要修改过的 Web 服务器来支持您的应用程序,只需任何可以进行反向代理或重定向的 Web 服务器即可。
为什么使用 Apache/Nginx?
当您提供 node.js 应用程序时,请注意您是您自己的 Web 服务器的作者。您的应用程序中的任何潜在错误都是互联网上可直接利用的错误。有些人(有理由)对此感到不舒服。
在您的 node.js 应用程序前面添加一层 Apache 或 Nginx 意味着您在实时互联网上拥有一个经过实战考验、安全加固的软件,作为您应用程序的接口。它增加了一点延迟(反向代理),但大多数人认为这是值得的。
这曾经是 node.js 早期的标准建议。但是现在也有一些网站和 Web 服务将 node.js 直接暴露在互联网上。 http.Server
模块现已在 Internet 上经过充分的实战测试,值得信赖。
NodeJs 创建自己的服务器。如您所见,术语非常清楚:
http.createServer(app).listen(3000);
创建一个服务器并在 3000 端口监听 http 请求。
我们在我们的一个项目中使用了 nginx,但它更像是多个 nodejs 实例的负载均衡器。
假设您有两个 nodejs 实例在端口 3000 和 3001 上运行,现在您仍然可以使用 nginx
作为服务器来侦听 port 80
上的实际 http
调用,并且可能希望将您的请求重定向到 nodejs
服务器或者可能是其他一些服务器,更像是 loadbalancer
。因此,您仍然可以使用 nginx
为 nodejs
提供的任何内容。
一个很好的问题已经问过 here。
假设有一家名为 Apache Hotel 的酒店,每个客户都有一名服务员。
顾客一点沙拉,服务员就去找厨师告诉他。当厨师准备食物时,服务员在等待。这里,
Chef => File System,
Waiter => Thread,
Customer => Event.
即使顾客点了水,服务员也只有在上完沙拉后才会送来。服务员一直等到厨师准备好沙拉。这种状态称为阻塞状态。即使酒店发展壮大,每个顾客也应该有不同的服务员来服务。这增加了线程(服务员)的阻塞。
现在,来到Node Hotel,所有顾客都只有一名服务员。如果第一位顾客点汤,服务员会告诉厨师,然后去找第二位顾客。食物准备好后,服务员将食物送到顾客手中。在这里,客户不会等待。这种状态称为非阻塞状态。单个服务员(线程)为所有客户服务并让他们开心。
因此,作为单线程应用程序的 Node 非常快。