为试图解释什么是 Node.js,本文探究了它能解决的问题,它如何工做,如何运行一个简单应用程序,最后,Node 什么时候是和什么时候不是一个好的解决方案。本文不涉及如何编写一个复杂的 Node 应用程序,也不是一份全面的 Node 教程。阅读本文应该有助于您决定是否应该学习 Node,以便将其用于您的业务。程序员
Node 公开宣称的目标是 “旨在提供一种简单的构建可伸缩网络程序的方法”。当前的服务器程序有什么问题?咱们来作个数学题。在 Java™ 和 PHP 这类语言中,每一个链接都会生成一个新线程,每一个新线程可能须要 2 MB 配套内存。在一个拥有 8 GB RAM 的系统上,理论上最大的并发链接数量是 4,000 个用户。随着您的客户端基础的增加,您但愿您的 web 应用程序支持更多用户,这样,您必须添加更多服务器。固然,这会增长业务成本,尤为是服务器成本、运输成本和人工成本。除这些成本上升外,还有一个技术问 题:用户可能针对每一个请求使用不一样的服务器,所以,任何共享资源都必须在全部服务器之间共享。例如,在 Java 中,静态变量和缓存须要在每一个服务器上的 JVMs 之间共享。这就是整个 web 应用程序架构中的瓶颈:一个服务器可以处理的并发链接的最大数量。数据库
Node 解决这个问题的方法是:更改链接链接到服务器的方式。每一个链接都建立一个进程,该进程不须要配套内存块,而不是为每一个链接生成一个新的 OS 线程(并向其分配一些配套内存)。Node 声称它毫不会死锁,由于它根本不容许使用锁,它不会直接阻塞 I/O 调用。Node 还宣称,运行它的服务器能支持数万个并发链接。事实上,Node 经过将整个系统中的瓶颈从最大链接数量更改到单个系统的流量来改变服务器面貌。编程
如今您有了一个能处理数万条并发链接的程序,那么您能经过 Node 实际构建什么呢?若是您有一个 web 应用程序须要处理这么多链接,那将是一件很 “恐怖” 的事!那是一种 “若是您有这个问题,那么它根本不是问题” 的问题。在回答上面的问题以前,咱们先看看 Node 如何工做以及它被设计的如何运行。ubuntu
没错,Node 是一个服务器程序。可是,它确定不 像 Apache 或 Tomcat。那些服务器是独立服务器产品,能够当即安装并部署应用程序。经过这些产品,您能够在一分钟内启动并运行一个服务器。Node 确定不是这种产品。Apache 能添加一个 PHP 模块来容许开发人员建立动态 web 页,使用 Tomcat 的程序员能部署 JSPs 来建立动态 web 页。Node 确定不是这种类型。缓存
在 Node 的早期阶段(当前是 version 0.4.6),它还不是一个 “运行就绪” 的服务器程序,您还不能安装它,向其中放置文件,拥有一个功能齐全的 web 服务器。即便是要实现 web 服务器在安装完成后启动并运行这个基本功能,也还须要作大量工做。服务器
Node 自己运行 V8 JavaScript。等等,服务器上的 JavaScript?没错,您没有看错。服务器端 JavaScript 是一个相对较新的概念,这个概念是大约两年前在 developerWorks 上讨论 Aptana Jaxer 产品时提到的(参见 参考资料)。尽管 Jaxer 一直没有真正流行,但这个理念自己并非高不可攀的 — 为什么不能在服务器上使用客户机上使用的编程语言?
什么使 V8?V8 JavaScript 引擎是 Google 用于他们的 Chrome 浏览器的底层 JavaScript 引擎。不多有人考虑 JavaScript 在客户机上实际作了些什么?实际上,JavaScript 引擎负责解释并执行代码。使用 V8,Google 建立了一个以 C++ 编写的超快解释器,该解释器拥有另外一个独特特征;您能够下载该引擎并将其嵌入任何 应用程序。它不只限于在一个浏览器中运行。所以,Node 实际上使用 Google 编写的 V8 JavaScript 引擎并将其重建为在服务器上使用。太完美了!既然已经有一个不错的解决方案可用,为什么还要建立一种新语言呢?
许多程序员接受的教育使他们认为,面向对象编程是完美的编程设计,而对其余编程方法不屑一顾。Node 使用一个所谓的事件驱动编程模型。
清单 1. 客户端上使用 jQuery 的事件驱动编程
jQuery code on the client-side showing how Event-Driven programming works // When a button is pressed, an Event occurs – deal with it // directly right here in an anonymous function, where all the // necessary variables are present and can be referenced directly $(“#myButton”).click(function(){ if ($(“#myTextField”).val() != $(this).val()) alert(“Field must match button text”); });
实际上,服务器端和客户端没有任何区别。没错,这没有按钮点击操做,也没有向文本字段键入的操做,但在一个更高的层面上,事件正在 发生。一个链接被创建 — 事件!数据经过链接接收 — 事件!数据经过链接中止 — 事件!
为何这种设置类型对 Node 很理想?JavaScript 是一种很棒的事件驱动编程语言,由于它容许匿名函数和闭包,更重要的是,任何写过代码的人都熟悉它的语法。事件发生时调用的回调函数能够在捕获事件处编 写。这样,代码容易编写和维护,没有复杂的面向对象框架,没有接口,没有在上面架构任何内容的潜能。只需监听事件,编写一个回调函数,而后,事件驱动编程 将照管好一切!
最后,咱们来看一些代码!让咱们将讨论过的全部内容综合起来,建立咱们的第一个 Node 应用程序。因为咱们已经知道,Node 对于处理高流量应用程序很理想,咱们就来建立一个很是简单的 web 应用程序 — 一个为实现最大速度而构建的应用程序。下面是 “老板” 交代的关于咱们的样例应用程序的具体要求:建立一个随机数字生成器 RESTful API。这个应用程序应该接受一个输入:一个名为 “number” 的参数。而后,应用程序返回一个介于 0 和该参数之间的随机数字,并将生成的数字返回调用者。因为 “老板” 但愿它成为一个普遍流行的应用程序,所以它应该能处理 50,000 个并发用户。咱们来看看代码:
清单 2. Node 随机数字生成器
these modules need to be imported in order to use them. // Node has several modules. They are like any #include // or import statement in other languages var http = require(“http”); var url = require(“url”); // The most important line in any Node file. This function // does the actual process of creating the server. Technically, // Node tells the underlying operating system that whenever a // connection is made, this particular callback function should be // executed. Since we’re creating a web service with REST API, // we want an HTTP server, which requires the http variable // we created in the lines above. // Finally, you can see that the callback method receives a ‘request’ // and ‘response’ object automatically. This should be familiar // to any PHP or Java programmer. http.createServer(function(request, response) { // The response needs to handle all the headers, and the return codes // These types of things are handled automatically in server programs // like Apache and Tomcat, but Node requires everything to be done yourself response.writeHead(200, {“Content-Type”: “text/plain”}); // Here is some unique-looking code. This is how Node retrieves // parameters passed in from client requests. The url module // handles all these functions. The parse function // deconstructs the URL, and places the query key-values in the // query object. We can find the value for the “number” key // by referencing it directly – the beauty of JavaScript. var params = url.parse(request.url, true).query; var input = param.number; // These are the generic JavaScript methods that will create // our random number that gets passed back to the caller var numInput = new Number(input); var numOutput = new Number(Math.random() * numInput).toFixed(0); // Write the random number to response response.write(numOutput); // Node requires us to explicitly end this connection. This is because // Node allows you to keep a connection open and pass data back and forth, // though that advanced topic isn’t discussed in this article. response.end(); // When we create the server, we have to explicitly connect the HTTP server to // a port. Standard HTTP port is 80, so we’ll connect it to that one. }).listen(80); // Output a String to the console once the server starts up, letting us know everything // starts up correctly console.log(“Random Number Generator Running…”);
将上面的代码放到一个名为 “random.js” 的文件中。如今,要启动这个应用程序并运行它(进而建立 HTTP 服务器并监听端口 80 上的链接),只需在您的命令提示中输入如下命令:% node random.js
。下面是服务器已经启动并运行时它看起来的样子:
root@ubuntu:/home/moilanen/ws/mike# node random.js Random Number Generator Running... |
应用程序已经启动并运行。Node 正在监放任何链接,咱们来测试一下。因为咱们建立了一个简单的 RESTful API,咱们可使用咱们的 web 浏览器来访问这个应用程序。键入如下地址(确保您完成了上面的步骤):http://localhost/?number=27。
您的浏览器窗口将更改到一个介于 0 到 27 之间的随机数字。单击浏览器上的 “从新载入” 按钮,将获得另外一个随机数字。就是这样,这就是您的第一个 Node 应用程序!
到此为止,应该可以回答 “Node 是什么” 这个问题了,但您可能还不清楚何时应该使用它。这是一个须要提出的重要问题,由于 Node 对有一些东西有好处,但相反,对另外一些东西而言,目前 Node 可能不是一个好的解决方案。您须要当心决定什么时候使用 Node,由于在错误的状况下使用它可能会致使一个多余编码的 LOT。
正如您此前所看到的,Node 很是适合如下状况:您预计可能有很高的流量,而在响应客户端以前服务器端逻辑和处理所需不必定是巨大的。Node 表现出众的典型示例包括:
固然,在某些状况下,Node 并不是理想选择。下面是 Node 不擅长的领域:
<% for (int i=0; i<20; i++) { } %>
这样的 JSP 代码段中包含循环的 index.jsp 页。Node 不支持这类动态的、HTML 驱动的页面。一样,Node 不太适合做为 Apache 和 Tomcat 这样的网页服务器。所以,若是您想在 Node 中提供这样一个服务器端解决方案,必须本身编写整个解决方案。PHP 程序员不想在每次部署 web 应用程序时都编写一个针对 Apache 的 PHP 转换器,当目前为止,这正是 Node 要求您作的。问题是 “什么是 Node.js?” 应该已经获得解答。阅读本文以后,您应该能经过几个清晰简洁的句子回答这个问题。若是这样,那么您已经走到了许多编码员和程序员的前面。我和许多人都谈论 过 Node,但它们对 Node 到底是什么一直很迷惑。能够理解,他们具备的是 Apache 的思惟方式 — 服务器是一个应用程序,将 HTML 文件放入其中,一切就会正常运转。而 Node 是目的驱动的。它是一个软件程序,使用 JavaScript 来容许程序员轻松快速地建立快速、可伸缩的 web 服务器。Apache 是运行就绪的,而 Node 是编码就绪的。
Node 完成了它提供高度可伸缩服务器的目标。它并不分配一个 “每一个链接一个线程” 模型,而是使用一个 “每一个链接一个流程” 模型,只建立每一个链接须要的内存。它使用 Google 的一个很是快速的 JavaScript 引擎:V8 引擎。它使用一个事件驱动设计来保持代码最小且易于阅读。全部这些因素促成了 Node 的理想目标 — 编写一个高度可伸缩的解决方案变得比较容易。
与理解 Node 是 什么一样重要的是,理解它不是 什么。Node 并非 Apache 的一个替代品,后者旨在使 PHP web 应用程序更容易伸缩。事实确实如此。在 Node 的这个初始阶段,大量程序员使用它的可能性不大,但在它能发挥做用的场景中,它的表现很是好。
未来应该指望从 Node 获得什么呢?这也许是本文引出的最重要的问题。既然您知道了它如今的做用,您应该会想知道它下一步将作什么。在接下来的一年中,我期待着 Node 提供与现有的第三方支持库更好地集成。如今,许多第三方程序员已经研发了用于 Node 的插件,包括添加文件服务器支持和 MySQL 支持。但愿 Node 开始将它们集成到其核心功能中。最后,我还但愿 Node 支持某种动态页面模块,这样,您就能够在 HTML 文件中执行在 PHP 和 JSP(也许是一个 NSP,一个 Node 服务器页)中所作的操做。最后,但愿有一天会出现一个 “部署就绪” 的 Node 服务器,能够下载和安装,只需将您的 HTML 文件放到其中,就像使用 Apache 或 Tomcat 那样。Node 如今还处于初始阶段,但它发展得很快,可能不久就会出如今您的视野中。