我不完全了解Node.js的全部内容。也许是因为我主要是一个基于 Web 的业务应用程序开发人员。它是什么以及它的用途是什么?
到目前为止,我的理解是:
- 编程模型是事件驱动的,尤其是它处理I/O的方式。
- 它使用JavaScript,解析器是V8。
- 它可以很容易地用于创建并发服务器应用程序。
我的理解正确吗?如果是,那么事件 I/O 的好处是什么,仅仅是并发的东西更多吗?另外,Node.js 的方向是成为一个框架,比如基于 JavaScript(基于 V8)的编程模型吗?
我不完全了解Node.js的全部内容。也许是因为我主要是一个基于 Web 的业务应用程序开发人员。它是什么以及它的用途是什么?
到目前为止,我的理解是:
我的理解正确吗?如果是,那么事件 I/O 的好处是什么,仅仅是并发的东西更多吗?另外,Node.js 的方向是成为一个框架,比如基于 JavaScript(基于 V8)的编程模型吗?
我在工作中使用 Node.js,发现它非常强大。被迫选择一个词来描述 Node.js,我会说“有趣”(这不是一个纯粹的正面形容词)。社区充满活力和成长。JavaScript,尽管它很奇怪,但它可能是一种很好的编码语言。而且你每天都会重新思考自己对“最佳实践”和结构良好的代码模式的理解。现在有大量的想法涌入 Node.js,在其中工作会让你接触到所有这些想法——伟大的精神举重。
生产中的 Node.js 绝对是可能的,但与文档中看似承诺的“交钥匙”部署相去甚远。在 Node.js v0.6.x 中,“集群”已集成到平台中,提供了必不可少的构建块之一,但我的“production.js”脚本仍然有大约 150 行逻辑来处理诸如创建日志之类的事情目录,回收死工人等。对于“严肃”的生产服务,您还需要准备好限制传入连接并执行 Apache 为PHP所做的所有事情。公平地说,Ruby on Rails确实存在这个问题。它通过两种互补的机制来解决:1)将 Ruby 放在 Rails/Node 上。阿帕奇/ Lighttd)。网络服务器可以有效地提供静态内容、访问日志、重写 URL、终止SSL、执行访问规则以及管理多个子服务。对于命中实际节点服务的请求,网络服务器通过代理请求。2) 使用像Unicorn这样的框架来管理工作进程,定期回收它们等。我还没有找到一个看起来完全成熟的 Node.js 服务框架;它可能存在,但我还没有找到它,并且在我的手卷“production.js”中仍然使用约 150 行。
阅读Express之类的框架,似乎标准做法是通过一个万事通的 Node.js 服务来提供所有服务……“app.use(express.static(__dirname + '/public'))” . 对于低负载服务和开发,这可能没问题。但是,一旦您尝试将大量时间加载到您的服务上并让它 24/7 全天候运行,您就会很快发现推动大型网站拥有完善的、硬化的 C 代码(如Nginx )在他们的网站前面并处理所有内容的动机静态内容请求(...直到您设置CDN,如Amazon CloudFront))。对于这个有点幽默和毫不掩饰的负面看法,看看这个家伙。
Node.js 也在发现越来越多的非服务用途。即使您使用其他东西来提供 Web 内容,您仍然可以使用 Node.js 作为构建工具,使用npm模块来组织您的代码,Browserify将其拼接成单个资产,并使用uglify-js将其缩小以进行部署. 对于处理网络,JavaScript 是一个完美的阻抗匹配,并且经常使它成为最简单的攻击途径。例如,如果你想通过一堆JSON响应负载来卑躬屈膝,你应该使用我的underscore-CLI模块,结构化数据的实用程序带。
有关 JavaScript 和 Node.js 的另一个观点,请查看从 Java 到 Node.js,这是一篇关于 Java 开发人员学习 Node.js 的印象和经验的博客文章。
模块 在考虑节点时,请记住,您选择的 JavaScript 库将定义您的体验。大多数人至少使用两个,一个异步模式助手(Step、Futures、Async)和一个 JavaScript 糖模块(Underscore.js)。
助手/JavaScript 糖:
异步模式模块:
或者要阅读有关异步库的所有信息,请参阅与作者的小组访谈。
网络框架:
测试:
此外,请查看推荐的 Node.js 模块的官方列表。然而,GitHub 的 Node Modules Wiki要完整得多,也是一个很好的资源。
要了解 Node,考虑一些关键的设计选择会很有帮助:
Node.js 是基于事件和异步/非阻塞的. 事件,如传入的 HTTP 连接将触发一个 JavaScript 函数,该函数会做一些工作并启动其他异步任务,如连接到数据库或从另一台服务器提取内容。一旦这些任务被启动,事件函数就会结束,Node.js 会重新进入睡眠状态。一旦发生其他事情,例如建立数据库连接或外部服务器响应内容,回调函数就会触发,并且执行更多 JavaScript 代码,可能会启动更多异步任务(例如数据库查询)。通过这种方式,Node.js 将愉快地为多个并行工作流交错活动,在任何时间点运行任何未被阻塞的活动。这就是为什么 Node.js 在管理数千个同时连接方面做得如此出色的原因。
为什么不像其他人一样每个连接只使用一个进程/线程?在 Node.js 中,新连接只是一个非常小的堆分配。启动一个新进程需要更多的内存,在某些平台上是一兆字节。但真正的成本是与上下文切换相关的开销。当你有 10^6 个内核线程时,内核必须做很多工作来确定下一个应该执行的人。为 Linux 构建 O(1) 调度程序已经投入了大量工作,但最终,与 10^6 个进程竞争 CPU 时间相比,拥有单个事件驱动进程的效率要高得多。此外,在过载情况下,多进程模型的行为非常糟糕,导致关键的管理和管理服务,尤其是 SSHD(这意味着您甚至无法登录到盒子来弄清楚它到底有多糟糕)。
Node.js 是单线程和无锁的。Node.js,作为一个非常慎重的设计选择,每个进程只有一个线程。正因为如此,多个线程同时访问数据基本上是不可能的。因此,不需要锁。线程很难。真的真的很难。如果您不相信这一点,那么您还没有完成足够多的线程编程。正确锁定很难,并且会导致很难追踪的错误。消除锁和多线程使最讨厌的错误类别之一消失了。这可能是 node.js 的最大优势。
但是如何利用我的 16 芯盒子呢?
两种方式:
Node.js 让您可以毫不费力地做一些非常强大的事情。假设您有一个 Node.js 程序,它执行各种任务,在TCP端口上侦听命令,对一些图像进行编码,等等。使用五行代码,您可以添加一个基于 HTTP 的 Web 管理门户,该门户显示活动任务的当前状态。这很容易做到:
var http = require('http');
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end(myJavascriptObject.getSomeStatusInfo());
}).listen(1337, "127.0.0.1");
现在您可以点击 URL 并检查正在运行的进程的状态。添加几个按钮,您就有了一个“管理门户”。如果您有一个正在运行的 Perl / Python / Ruby 脚本,那么仅仅“投入管理门户”并不是很简单。
但是 JavaScript 不是慢/坏/邪恶/魔鬼的产物吗?JavaScript 有一些奇怪的地方,但“好的部分”有一种非常强大的语言,无论如何,JavaScript 是客户端(浏览器)上的语言。JavaScript 将继续存在;其他语言将其定位为 IL,世界一流的人才正在竞相生产最先进的 JavaScript 引擎。由于 JavaScript 在浏览器中的作用,大量的工程工作被投入到使 JavaScript 快速运行。 V8是最新最好的 javascript 引擎,至少在这个月是这样。它在效率和稳定性方面都击败了其他脚本语言(看着你,Ruby)。只有在微软、谷歌和 Mozilla 的庞大团队致力于解决这个问题,竞争构建最好的 JavaScript 引擎时,它才会变得更好(它不再是 JavaScript“解释器”,因为所有现代引擎都执行大量的JIT在引擎盖下编译,解释仅作为一次执行代码的后备)。是的,我们都希望我们可以修复一些奇怪的 JavaScript 语言选择,但这真的没那么糟糕。而且该语言非常灵活,以至于您实际上不是在编写 JavaScript,而是在编写 Step 或 jQuery —— 与任何其他语言相比,在 JavaScript 中,库定义了体验。无论如何,要构建 Web 应用程序,您几乎都必须了解 JavaScript,因此在服务器上使用它进行编码具有某种技能组合的协同作用。它让我不再害怕编写客户端代码。
此外,如果你真的讨厌 JavaScript,你可以使用像CoffeeScript这样的语法糖。或任何其他创建 JavaScript 代码的东西,例如Google Web Toolkit (GWT)。
说到 JavaScript,什么是“闭包”?- 几乎可以说您在调用链中保留词法范围的变量。;) 像这样:
var myData = "foo";
database.connect( 'user:pass', function myCallback( result ) {
database.query("SELECT * from Foo where id = " + myData);
} );
// Note that doSomethingElse() executes _BEFORE_ "database.query" which is inside a callback
doSomethingElse();
看看你如何可以只使用“myData”而不做任何尴尬的事情,比如将它存储到一个对象中?与 Java 不同,“myData”变量不必是只读的。这种强大的语言特性使异步编程变得不那么冗长和痛苦。
编写异步代码总是比编写简单的单线程脚本更复杂,但使用 Node.js,这并没有那么困难,而且除了效率和可扩展至数千个并发连接之外,您还可以获得很多好处。 ..
我认为优点是:
在速度极快的虚拟机 (V8) 上使用动态语言 (JavaScript) 进行 Web 开发。它比 Ruby、Python 或 Perl 快得多。
能够在单个进程上以最小的开销处理数千个并发连接。
JavaScript 非常适合具有一流函数对象和闭包的事件循环。人们已经知道如何以这种方式使用它,并在浏览器中使用它来响应用户发起的事件。
很多人已经知道 JavaScript,即使是那些不自称是程序员的人。它可以说是最流行的编程语言。
在 Web 服务器和浏览器上使用 JavaScript 可以减少两个编程环境之间的阻抗不匹配,这两个编程环境可以通过 JSON 通信数据结构,在等式的两边都工作相同。可以在服务器和客户端之间共享重复的表单验证代码等。
V8是 JavaScript 的实现。它允许您运行独立的 JavaScript 应用程序(除其他外)。
Node.js 只是一个为 V8 编写的库,它执行事件 I/O。这个概念解释起来有点棘手,我相信有人会用比我更好的解释来回答......要点是,与其做一些输入或输出并等待它发生,你只是不要等待让它完成。例如,询问文件的最后编辑时间:
// Pseudo code
stat( 'somefile' )
这可能需要几毫秒,也可能需要几秒钟。使用事件I/O,您只需触发请求,而不是等待您附加一个在请求完成时运行的回调:
// Pseudo code
stat( 'somefile', function( result ) {
// Use the result here
} );
// ...more code here
这使它很像浏览器中的 JavaScript 代码(例如,具有Ajax风格的功能)。
有关更多信息,您应该查看文章Node.js 真的很令人兴奋,这是我对库/平台的介绍......我发现它非常好。
Node.js是为服务器端 JavaScript 代码构建的开源命令行工具。您可以下载tarball,编译并安装源代码。它允许您运行 JavaScript 程序。
JavaScript由 Google 开发的用于Chrome浏览器的 JavaScript 引擎V8执行。它使用 JavaScript API 来访问网络和文件系统。
它因其性能和执行并行操作的能力而广受欢迎。
理解 node.js是我目前找到的对node.js最好的解释。
以下是有关该主题的一些好文章。
闭包是在创建代码的上下文中执行代码的一种方式。
这对并发性意味着您可以定义变量,然后启动一个非阻塞I/O函数,并向其发送一个匿名函数以进行回调。
当任务完成时,回调函数将在带有变量的上下文中执行,这就是闭包。
闭包非常适合编写具有非阻塞 I/O 的应用程序的原因是它非常容易管理异步执行的函数的上下文。
两个很好的例子是关于如何管理模板和使用渐进增强。您只需要一些轻量级的 JavaScript 代码就可以使其完美运行。
我强烈建议您观看并阅读以下文章:
选择任何一种语言并尝试记住您将如何管理 HTML 文件模板以及在DOM结构中更新单个CSS类名称必须执行的操作(例如,用户单击了菜单项并且您希望将其标记为“选择”并更新页面内容)。
使用 Node.js,它就像在客户端 JavaScript 代码中一样简单。获取您的 DOM 节点并将您的 CSS 类应用于该节点。获取您的 DOM 节点和 innerHTML 您的内容(您将需要一些额外的 JavaScript 代码来执行此操作。阅读文章以了解更多信息)。
另一个很好的例子是,您可以使用同一段代码使您的网页与打开或关闭的 JavaScript 兼容。想象一下,您有一个用 JavaScript 进行的日期选择,允许您的用户使用日历选择任何日期。您可以编写(或使用)相同的 JavaScript 代码,使其在您的 JavaScript 打开或关闭的情况下工作。
有一个很好的快餐店类比,最能解释 Node.js 的事件驱动模型,请参阅完整文章Node.js、医生办公室和快餐店 - 了解事件驱动编程
这是一个摘要:
如果快餐店遵循传统的基于线程的模式,您会订购食物并排队等候直到收到。在您完成订单之前,您身后的人将无法订购。在事件驱动模型中,您订购食物然后排队等候。然后其他人都可以自由订购。
Node.js 是事件驱动的,但大多数 Web 服务器都是基于线程的。York 解释了 Node.js 的工作原理:
您使用 Web 浏览器在 Node.js Web 服务器上发出“/about.html”请求。
Node.js 服务器接受您的请求并调用一个函数从磁盘检索该文件。
当 Node.js 服务器正在等待检索文件时,它会为下一个 Web 请求提供服务。
检索文件时,会在 Node.js 服务器队列中插入一个回调函数。
Node.js 服务器执行该函数,在这种情况下将呈现“/about.html”页面并将其发送回您的 Web 浏览器。”
嗯,我明白了
- Node 的目标是提供一种简单的方法来构建可扩展的网络程序。
- Node 在设计上类似于 Ruby 的 Event Machine 或 Python 的 Twisted 等系统,并受其影响。
- V8 javascript 的事件 I/O。
对我来说,这意味着你在所有三个假设中都是正确的。图书馆看起来很有希望!
另外,别忘了提到 Google 的 V8 非常快。它实际上将 JavaScript 代码转换为具有已编译二进制性能的机器代码。因此,与所有其他伟大的事情一起,它的速度非常快。
问:编程模型是事件驱动的,尤其是它处理I/O的方式。
正确的。它使用回调,因此任何访问文件系统的请求都会导致请求被发送到文件系统,然后 Node.js 将开始处理它的下一个请求。一旦从文件系统得到响应,它只会担心 I/O 请求,此时它将运行回调代码。但是,可以进行同步 I/O 请求(即阻塞请求)。开发人员可以在异步(回调)或同步(等待)之间进行选择。
问:它使用 JavaScript,解析器是 V8。
是的
问:它可以很容易地用于创建并发服务器应用程序。
是的,尽管您需要手动编写大量 JavaScript。最好查看一个框架,例如http://www.easynodejs.com/ - 它带有完整的在线文档和示例应用程序。