像Express这样的阅读框架使得看起来标准的做法就是通过一个万事通的Node.js服务来提供所有服务...... "app.use(express.static(__dirname + '/public'))" . 对于负载较低的服务和开发,'s probably fine. But as soon as you try to put big time load on your service and have it run 24/7, you'll很快就会发现推动大型网站拥有良好烘焙,强化的C代码(例如Nginx)面向其网站并处理所有静态内容请求的动机(......直到您设置了CDN,如Amazon CloudFront)) . 对于一个有点幽默和毫不掩饰的负面看法,请参阅this guy .
忘记验证,只需让代码执行即可 . 对于每种方法,我的第一个验证案例是"nothing breaks",并且's the case that fires most often. Proving that your code runs without throwing catches 80% of the bugs and will do so much to improve your code confidence that you' ll会发现自己回过头来添加您跳过的细微差别验证案例 .
Why not just use one process/thread per connection like everyone else? 在Node.js中,新连接只是一个非常小的堆分配 . 启动新进程需要更多内存,在某些平台上需要1兆字节 . 但实际成本是与上下文切换相关的开销 . 当你有10 ^ 6个内核线程时,内核必须做很多工作来确定下一步应该执行什么 . 一堆工作已经用于构建Linux的O(1)调度程序,但最终,它甚至可以登录框来弄清楚它是如何搞砸的 . )
Node.js lets you do some really powerful things without breaking a sweat. 假设您有一个Node.js程序可以执行各种任务,可以在TCP端口上搜索命令,对某些图像进行编码等等 . 使用五行代码,您可以添加基于HTTP的Web管理门户,该门户显示活动任务的当前状态 . 这很容易做到:
But isn't JavaScript slow / bad / evil / spawn-of-the-devil? JavaScript有一些奇怪的奇怪之处,但是由于"the good parts"在浏览器中有作用,因此大量的工程工作正在使JavaScript快速发展 . V8是最新最好的javascript引擎,至少在本月 . 它在效率和稳定性方面打破了其他脚本语言(看着你,Ruby) . 并且's only going to get better with huge teams working on the problem at Microsoft, Google, and Mozilla, competing to build the best JavaScript engine (It'不再是一个JavaScript "interpreter",因为所有现代引擎都会在引擎盖下进行大量编译,而解释仅仅是执行一次代码的回退 . 是的,我们都希望我们可以修复一些奇怪的JavaScript语言选择,但它编写JavaScript,你编写Step或jQuery - 比任何其他语言更多,在JavaScript中,库定义了体验 . 要构建Web应用程序,您无论如何都必须了解JavaScript,因此在服务器上使用它进行编码具有一种技能组合协同作用 . 这让我不怕写客户端代码 .
Speaking of JavaScript, what's a "closure"? - 几乎可以说你在调用链中保留了词法范围的变量 . ;) 像这样:
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();
10 回答
我认为其优点是:
在VM上以动态语言(JavaScript)进行Web开发,速度非常快(V8) . 它比Ruby,Python或Perl快得多 .
能够以最小的单个进程开销处理数千个并发连接 .
JavaScript非常适合具有第一类函数对象和闭包的事件循环 . 人们已经知道如何使用它在浏览器中使用它来响应用户发起的事件 .
很多人已经了解JavaScript,甚至是那些自称不是程序员的人 . 它可以说是最流行的编程语言 .
在Web服务器和浏览器上使用JavaScript可以减少两个编程环境之间的阻抗不匹配,这两个编程环境可以通过JSON传递数据结构,这两个方程在方程式的两侧都是相同的 . 可以在服务器和客户端等之间共享重复的表单验证代码 .
我在工作中使用Node.js,并发现它非常强大 . 被迫选择一个词来描述Node.js,我会说“有趣”(这不是一个纯正的形容词) . 社区充满活力,不断发展壮大 . 尽管JavaScript很奇怪,但它可以成为一种很好的编码语言 . 而且你每天都会重新思考自己对“最佳实践”和结构良好的代码模式的理解 . 现在有很多想法流入Node.js,并且在其中工作会让你接触到所有这些思想 - 精神上的举重 .
生产环境 中的Node.js绝对是可能的,但远远不是文档似乎承诺的"turn-key"部署 . 使用Node.js v0.6.x,"cluster"已经集成到平台中,提供了一个必不可少的构建块,但我的"production.js"脚本仍然是〜150行逻辑来处理诸如创建日志目录,回收死亡工作者之类的东西,对于"serious" 生产环境 服务,您还需要准备好限制传入连接并完成Apache为PHP所做的所有事情 . 公平地说,Ruby on Rails有这个确切的问题 . 它通过两种互补的机制解决:1)将Ruby放在Rails / Node.js后面的专用网络服务器(用C语言编写并测试到地狱和后面),如Nginx(或Apache / Lighttd) . Web服务器可以有效地提供静态内容,访问日志记录,重写URL,终止SSL,强制执行访问规则以及管理多个子服务 . 对于命中实际节点服务的请求,Web服务器代理请求 . 2)使用像Unicorn这样的框架来管理工作进程,定期回收它们等等 . 我发现它仍然在我的手工卷"production.js"中使用~150行 .
像Express这样的阅读框架使得看起来标准的做法就是通过一个万事通的Node.js服务来提供所有服务...... "app.use(express.static(__dirname + '/public'))" . 对于负载较低的服务和开发,'s probably fine. But as soon as you try to put big time load on your service and have it run 24/7, you'll很快就会发现推动大型网站拥有良好烘焙,强化的C代码(例如Nginx)面向其网站并处理所有静态内容请求的动机(......直到您设置了CDN,如Amazon CloudFront)) . 对于一个有点幽默和毫不掩饰的负面看法,请参阅this guy .
Node.js也发现越来越多的非服务用途 . 即使您使用其他东西来提供Web内容,您仍可以使用Node.js作为构建工具,使用npm模块来组织代码,Browserify将其拼接成单个资源,然后使用uglify-js将其缩小以进行部署 . 对于处理Web,JavaScript是一个完美的impedance match,并且经常使它成为最简单的攻击途径 . 例如,如果你想浏览一堆JSON响应有效负载,你应该使用我的underscore-CLI模块,即结构化数据的实用带 .
优点/缺点:
专业版:对于服务器人来说,在后端编写JavaScript是学习现代UI模式的一种方法 . 我不再害怕编写客户端代码 .
Pro:倾向于鼓励正确的错误检查(几乎所有的回调都会返回错误,唠叨程序员来处理它;同样,async.js和其他库比典型的同步代码更好地处理"fail if any of these subtasks fails"范例)
专业:一些有趣且通常很难的任务变得微不足道 - 比如获取飞行中的任务状态,工作人员之间的通信或共享缓存状态
专业:基于坚实的包管理器(npm)的庞大社区和大量优秀的图书馆
Con:JavaScript没有标准库 . 当你使用JSON.parse或其他一些不需要添加npm模块的方法时,你已经习惯了导入功能,感觉很奇怪 . 这意味着一切都有五个版本 . 如果您对默认实现不满意,甚至包含在Node.js _732602中的模块还有五个变体 . 这导致快速进化,但也有一定程度的混乱 .
与简单的每进程一个进程模型(LAMP):
Pro:可扩展到数千个活动连接 . 非常快速且非常高效 . 对于网络车队来说,这意味着与PHP或Ruby相比,所需的箱数减少了10倍
Pro:编写并行模式很容易 . 想象一下,你需要从Memcached中获取三个(或N个)blob . 在PHP中执行此操作...您只是编写代码获取第一个blob,然后是第二个,然后是第三个?哇,'s slow. There'是一个特殊的PECL模块来修复Memcached的特定问题,但是如果你想要与数据库查询并行获取一些Memcached数据呢?在Node.js中,因为范例是异步的,所以具有Web请求并行执行多个操作是非常自然的 .
Con:异步代码基本上比同步代码更复杂,如果没有深入理解并发执行实际意味着什么,那么前期学习曲线对于开发人员来说可能很难 . 但是,与使用锁定编写任何类型的多线程代码相比,它要困难得多 .
Con:如果计算密集型请求运行时间为100毫秒,则会停止处理在同一个Node.js进程中处理的其他请求... AKA,cooperative-multitasking . 这可以通过Web Workers模式(关闭子流程来处理昂贵的任务)来缓解 . 或者,您可以使用大量Node.js工作程序,并且只让每个工作程序同时处理单个请求(仍然相当有效,因为没有进程回收) .
Con:运行 生产环境 系统比Apache PHP,Perl,Ruby等CGI模型复杂得多 . 未处理的异常会导致整个过程失效,需要逻辑重启失败的工作者(参见cluster) . 具有错误本机代码的模块可能会使进程难以崩溃 . 每当一个工作者死亡时,它所处理的任何请求都会被删除,因此一个错误的API很容易降低其他共同API的服务质量 .
与在Java / C#/ C中编写“真实”服务(C?真的吗?)
Pro:在Node.js中执行异步比在其他任何地方执行线程安全更容易,并且可以提供更大的好处 . Node.js是迄今为止我曾经工作过的最不痛苦的异步范例 . 使用好的库,它只比编写同步代码稍微困难一些 .
Pro:没有多线程/锁定错误 . 没错,您可以在编写更详细的代码时进行投资,这些代码表达了一个没有阻塞操作的正确的异步工作流 . 而且你需要编写一些测试并使其工作(它是一种脚本语言,并且胖指法变量名只能在单元测试时捕获) . 但是,一旦你开始工作,表面区域就会出现一个奇怪的问题 - 只有一百万次运行 - 表面区域要低得多 . 编写Node.js代码的税收大量加载到编码阶段 . 然后你倾向于最终得到稳定的代码 .
Pro:JavaScript表达功能要轻得多 . 很难用文字证明这一点,但是JSON,动态类型,lambda符号,原型继承,轻量级模块,无论如何......它只是用较少的代码来表达相同的想法 .
Con:也许你真的非常喜欢用Java编写服务?
有关JavaScript和Node.js的另一个视角,请查看From Java to Node.js,这是一篇关于Java开发人员学习Node.js的印象和经验的博客文章 .
Modules 在考虑节点时,请记住,您选择的JavaScript库将定义您的体验 . 大多数人使用至少两个,一个异步模式助手(Step,Futures,Async)和一个JavaScript糖模块(Underscore.js) .
助手/ JavaScript糖:
异步模式模块:
Step - 表达串行和并行动作组合的一种非常优雅的方式 . 我的个人推荐 . 有关步骤代码的信息,请参阅my post .
Futures - 更灵活(这真的是一件好事吗?)通过要求表达排序的方式 . 能够表达像_732621这样的事情 . 这种灵活性需要更多的注意,以避免工作流中的错误(如从不调用回调,或多次调用它) . 关于使用期货,请参阅Raynos's post(这是让我"get"期货的帖子) .
Async - 更传统的库,每种模式都有一种方法 . 我在开始宗教转换之前开始使用它,然后逐步认识到Async中的所有模式都可以用一个更易读的范例来表达 .
TameJS - 由OKCupid撰写,它仍然在这个问题上做出决定 .
StreamlineJS - TameJS的竞争对手 . 我倾向于驯服,但你可以自己决定 .
或者阅读有关异步库的所有内容,请参阅作者的this panel-interview .
Web框架:
Express用于组织网站的Great Ruby on Rails-esk框架 . 它使用JADE作为XML / HTML模板引擎,这使得构建HTML变得更加痛苦,甚至更加优雅 .
jQuery虽然技术上不是节点模块,但jQuery正迅速成为客户端用户界面的事实标准 . jQuery为'query'提供了类似CSS的选择器,用于可以对其进行操作的DOM元素集(设置处理程序,属性,样式等) . 同样,Twitter的Bootstrap CSS框架,Backbone.js用于MVC模式,Browserify.js将所有JavaScript文件拼接成单个文件 . 这些模块都成为事实上的标准,所以如果你没有听说过,你至少应该检查它们 .
测试:
JSHint - 必须使用;我没有喝茶 - 但真正的 Value 来自于你忘记关闭的确切行号的即时反馈")" ...无需运行你的代码并点击违规行 . "JSHint"是Douglas Crockford的JSLint的更易配置的变体 .
Mocha誓言的竞争者,我开始更喜欢 . 两个框架都能很好地处理基础知识,但复杂的模式往往更容易在Mocha中表达 .
Vows誓言真的很优雅 . 它打印出一个可爱的报告(--spec),显示哪些测试用例通过/失败 . 花30分钟学习它,您可以轻松地为您的模块创建基本测试 .
Zombie - 使用JSDom作为虚拟"browser"对HTML和JavaScript进行无头测试 . 非常强大的东西 . 将它与Replay相结合,可以对浏览器内代码进行快速确定性测试 .
关于如何"think about"测试的评论:
测试是非可选的 . 使用像JavaScript这样的动态语言,很少有静态检查 . 例如,将两个参数传递给期望为4的方法,在执行代码之前不会中断 . 用于在JavaScript中创建错误的相当低的标准 . 基本测试对于弥补编译语言的验证差距至关重要 .
忘记验证,只需让代码执行即可 . 对于每种方法,我的第一个验证案例是"nothing breaks",并且's the case that fires most often. Proving that your code runs without throwing catches 80% of the bugs and will do so much to improve your code confidence that you' ll会发现自己回过头来添加您跳过的细微差别验证案例 .
从小处开始,打破惯性屏障 . 我们都很懒惰,时间紧迫,第一次这样做是<732656_ <30分钟,包括阅读文档 . 现在编写测试用例1 - 调用你的一个方法并验证"nothing breaks",也就是说,你没有收到错误 . 测试用例1应该不到一分钟 . 随着惯性消失,逐渐扩大测试覆盖范围变得容易 .
现在使用您的代码改进您的测试 . 不要被使用模拟服务器和所有这些的"correct"端到端测试看起来感到害怕 . 代码开始简单,并逐步发展以处理新案例;测试也应该 . 在为代码添加新案例和新复杂性时,添加测试用例以执行新代码 . 当您发现错误时,请添加验证和/或新案例以涵盖有缺陷的代码 . 当您调试并对一段代码失去信心时,请返回并添加测试以证明它正在执行您认为的操作 . 捕获示例数据的字符串(来自您调用的其他服务,您搜索的网站,等等)并将它们提供给您的解析代码 . 这里有一些案例,改进了验证,最终你会得到高度可靠的代码 .
另外,请查看推荐的Node.js模块的official list . 但是,GitHub's Node Modules Wiki要完整得多,资源也很好 .
要了解Node,考虑一些关键设计选择会很有帮助:
Node.js是 EVENT BASED 和 ASYNCHRONOUS / NON-BLOCKING . 事件,如传入的HTTP连接,将触发一个JavaScript函数,该函数执行一些工作并启动其他异步任务,如连接到数据库或从另一个服务器提取内容 . 一旦启动这些任务,事件函数就会完成,Node.js会重新进入休眠状态 . 一旦发生其他事情,例如正在 Build 的数据库连接或外部服务器响应内容,回调函数触发,执行更多JavaScript代码,可能会启动更多异步任务(如数据库查询) . 通过这种方式,Node.js将愉快地交错多个并行工作流的活动,运行在任何时间点未被阻止的任何活动 . 这就是Node.js在管理数千个同时连接方面做得非常出色的原因 .
Why not just use one process/thread per connection like everyone else? 在Node.js中,新连接只是一个非常小的堆分配 . 启动新进程需要更多内存,在某些平台上需要1兆字节 . 但实际成本是与上下文切换相关的开销 . 当你有10 ^ 6个内核线程时,内核必须做很多工作来确定下一步应该执行什么 . 一堆工作已经用于构建Linux的O(1)调度程序,但最终,它甚至可以登录框来弄清楚它是如何搞砸的 . )
Node.js是 SINGLE THREADED 和 LOCK FREE . Node.js作为一个非常谨慎的设计选择,每个进程只有一个线程 . 正因为如此,它认为,你还没有做足够的线程编程 . 正确锁定很困难,导致很难找到的错误 . 消除锁和多线程使得最糟糕的一类错误消失 . 这可能是节点的最大优势 .
But how do I take advantage of my 16 core box?
两种方式:
对于像图像编码这样的大型计算任务,Node.js可以启动子进程或向其他工作进程发送消息 . 在这个设计中,你有一个线程来管理事件流和N个进程执行繁重的计算任务并咀嚼其他15个CPU .
为了在web服务上扩展吞吐量,你应该在一个盒子上运行多个Node.js服务器,每个核心一个,使用cluster(使用Node.js v0.6.x,这里链接的官方"cluster"模块取代了有一个的Learnboost版本不同的API) . 然后,这些本地Node.js服务器可以在套接字上竞争以接受新连接,从而 balancer 它们之间的负载 . 一旦接受连接,它就会紧密绑定到这些共享进程中的一个 . 从理论上讲,这听起来很糟糕,但在实践中它运行良好,可以避免编写线程安全代码的麻烦 . 此外,这意味着Node.js可以获得出色的CPU缓存关联性,更有效地利用内存带宽 .
Node.js lets you do some really powerful things without breaking a sweat. 假设您有一个Node.js程序可以执行各种任务,可以在TCP端口上搜索命令,对某些图像进行编码等等 . 使用五行代码,您可以添加基于HTTP的Web管理门户,该门户显示活动任务的当前状态 . 这很容易做到:
现在,您可以点击URL并检查正在运行的进程的状态 . 添加几个按钮,您就有了一个“管理门户” . 如果你有一个正在运行的Perl / Python / Ruby脚本,那么“投入一个管理门户”并不是那么简单 .
But isn't JavaScript slow / bad / evil / spawn-of-the-devil? JavaScript有一些奇怪的奇怪之处,但是由于"the good parts"在浏览器中有作用,因此大量的工程工作正在使JavaScript快速发展 . V8是最新最好的javascript引擎,至少在本月 . 它在效率和稳定性方面打破了其他脚本语言(看着你,Ruby) . 并且's only going to get better with huge teams working on the problem at Microsoft, Google, and Mozilla, competing to build the best JavaScript engine (It'不再是一个JavaScript "interpreter",因为所有现代引擎都会在引擎盖下进行大量编译,而解释仅仅是执行一次代码的回退 . 是的,我们都希望我们可以修复一些奇怪的JavaScript语言选择,但它编写JavaScript,你编写Step或jQuery - 比任何其他语言更多,在JavaScript中,库定义了体验 . 要构建Web应用程序,您无论如何都必须了解JavaScript,因此在服务器上使用它进行编码具有一种技能组合协同作用 . 这让我不怕写客户端代码 .
此外,如果你真的讨厌JavaScript,你可以使用像CoffeeScript这样的语法糖 . 或者其他任何创建JavaScript代码的东西,比如Google Web Toolkit(GWT) .
Speaking of JavaScript, what's a "closure"? - 几乎可以说你在调用链中保留了词法范围的变量 . ;) 像这样:
看看如何只使用“myData”而不做任何尴尬的事情,比如将它存入对象?与Java不同,“myData”变量不必是只读的 . 这种强大的语言功能使异步编程更加简洁,减少了痛苦 .
编写异步代码总是比编写一个简单的单线程脚本更复杂,但是使用Node.js,除了数千个并发连接的效率和可伸缩性之外,它并没有那么难以获得很多好处 . ..
V8是JavaScript的实现 . 它允许您运行独立的JavaScript应用程序(以及其他内容) .
Node.js只是为V8编写的库,它实现了I / O.这个概念解释起来有点棘手,我相信有人会更好地回答解释比我... ...要点是,不是做一些输入或输出,等待它发生,你只是不等待它完成 . 例如,请求文件的上次编辑时间:
这可能需要几毫秒,或者可能需要几秒钟 . 使用_832689_事件,您只需触发请求,而不是等待您附加一个在请求完成时运行的回调:
这使它很像浏览器中的JavaScript代码(例如,具有Ajax样式功能) .
有关更多信息,请查看文章Node.js is genuinely exciting,这是我对库/平台的介绍......我发现它非常好 .
Node.js是为服务器端JavaScript代码构建的开源命令行工具 . 您可以下载tarball,编译并安装源代码 . 它允许您运行JavaScript程序 .
JavaScript由V8执行,这是一个由Google开发的JavaScript引擎,用于Chrome浏览器 . 它使用JavaScript API来访问网络和文件系统 .
它的性能和执行并行操作的能力很受欢迎 .
以下是关于该主题的一些好文章 .
闭包是一种在创建它的上下文中执行代码的方法 .
这对于可靠性来说意味着您可以定义变量,然后启动非阻塞I/O函数,并为其回调发送一个匿名函数 .
当任务完成后,回调函数将在带有变量的上下文中执行,这就是闭包 .
闭包非常适合编写具有非阻塞I / O的应用程序,因为管理异步执行的函数的上下文非常容易 .
两个很好的例子是关于如何管理模板并使用渐进增强功能 . 您只需要一些轻量级的JavaScript代码即可使其完美运行 .
我强烈建议您观看和阅读这些文章:
Video glass node
Node.js YUI DOM manipulation
选择任何语言并尝试记住如何管理HTML文件模板以及如何更新DOM结构中的单个CSS类名称(例如,用户单击菜单项并且您希望将其标记为"selected"并更新页面内容) .
使用Node.js就像在客户端JavaScript代码中一样简单 . 获取您的DOM节点并将CSS类应用于该节点 . 获取您的DOM节点和innerHTML您的内容(您将需要一些额外的JavaScript代码来执行此操作 . 阅读文章以了解更多信息) .
另一个很好的例子是,您可以使用相同的代码打开或关闭JavaScript来使您的网页兼容 . 想象一下,您有一个用JavaScript制作的日期选择,允许您的用户使用日历获取任何日期 . 您可以编写(或使用)相同的JavaScript代码,以使其与您的JavaScript打开或关闭一起使用 .
有一个非常好的快餐店比喻,最能说明Node.js的事件驱动模型,请参阅完整文章,Node.js, Doctor’s Offices and Fast Food Restaurants – Understanding Event-driven Programming
以下是摘要:
Node.js是事件驱动的,但大多数Web服务器都是基于线程的.York解释了Node.js的工作原理:
您使用Web浏览器在Node.js Web服务器上发出“/about.html”请求 .
Node.js服务器接受您的请求并调用函数从磁盘检索该文件 .
当Node.js服务器正在等待检索文件时,它为下一个Web请求提供服务 .
检索文件时,会有一个插入Node.js服务器队列的回调函数 .
Node.js服务器执行该功能,在这种情况下,该功能将呈现“/about.html”页面并将其发送回您的Web浏览器 . “
好吧,I understand that
对我而言,这意味着你在所有三个假设中都是正确的 . 图书馆看起来很有前途!
此外,不要忘记提到谷歌的V8非常快 . 它实际上将JavaScript代码转换为具有编译二进制的匹配性能的机器代码 . 因此,除了所有其他伟大的东西,它是无助的快速 .
问:编程模型是事件驱动的,尤其是它处理I/O的方式 .
正确 . 它使用回调,所以任何请求访问文件系统会导致请求被发送到文件系统,然后Node.js将开始处理它的下一个请求 . 一旦从文件系统获得响应,它只会担心I / O请求,此时它将运行回调代码 . 但是,可以进行同步I / O请求(即阻塞请求) . 开发人员可以在异步(回调)或同步(等待)之间进行选择 .
问:它使用JavaScript,解析器是V8 .
是
问:它可以很容易地用于创建并发服务器应用程序 .
是的,虽然您需要手动编写相当多的JavaScript代码 . 查看一个框架可能会更好,例如http://www.easynodejs.com/ - 它带有完整的在线文档和示例应用程序 .