什么是Node.js?

我没有完全得到Node.js的全部内容。 也许这是因为我主要是一个基于Web的商业应用程序开发人员。 它是什么以及它的用途是什么?

我迄今为止的理解是:

  • 编程模型是事件驱动的,尤其是它处理I / O的方式。
  • 它使用JavaScript,解析器是V8。
  • 它可以很容易地用来创建并发的服务器应用程序。
  • 我的理解是否正确? 如果是的话,那么evented I / O有什么好处,它只是更多的并发性的东西? 另外,Node.js的方向是成为像基于JavaScript(基于V8的)编程模型的框架吗?


    我认为优点是:

  • 以极快的速度在虚拟机上以动态语言(JavaScript)进行Web开发(V8)。 它比Ruby,Python或Perl快得多。

  • 能够在单个进程上以最小的开销处理数千个并发连接。

  • JavaScript非常适用于具有一流功能对象和闭包的事件循环。 人们已经知道如何在浏览器中使用它来响应用户发起的事件。

  • 很多人已经了解JavaScript,即使是那些自称不是程序员的人。 它可以说是最流行的编程语言。

  • 在Web服务器上使用JavaScript以及浏览器可以减少两种编程环境之间的阻抗不匹配,这两种编程环境可以通过JSON沟通数据结构,这两种编程环境在等式两边都是一样的。 重复的表单验证代码可以在服务器和客户端之间共享等。


  • 我在工作中使用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.js后面,像Nginx(或Apache / Lighttd),放在一个专用的web服务器(用C语言编写并经过测试后可以回头测试)。 Web服务器可以高效地提供静态内容,访问日志记录,重写URL,终止SSL,强制访问规则以及管理多个子服务。 对于碰到实际节点服务的请求,Web服务器通过代理请求。 2)使用像Unicorn这样的框架来管理工作进程,定期回收它们等等。我还没有找到一个似乎完全被烘焙的Node.js服务框架; 它可能存在,但我还没有找到它,仍然在我的手卷“production.js”中使用〜150行。

    像Express这样的阅读框架使得看起来像标准的做法是通过一个全能的Node.js服务来提供所有的服务......“app.use(express.static(__ dirname +'/ public'))” 。 对于较低负载的服务和开发,这可能很好。 但只要您尝试将大量时间加载到您的服务上并让其全天候运行,您就会很快发现推动大型网站获得良好烘焙,强化C代码的动机,例如Nginx面向其网站并处理所有问题的静态内容请求(...直到您设置CDN,如Amazon CloudFront))。 对于这个有点幽默和毫不掩饰的负面看法,看看这个人。

    Node.js也发现越来越多的非服务用途。 即使你正在使用别的东西来提供web内容,你仍然可以使用Node.js作为构建工具,使用npm模块来组织代码,将Browserify拼接成单个资源,然后使用uglify-js将其缩小以供部署。 对于网络处理,JavaScript是一个完美的阻抗匹配,并且经常使其成为最简单的攻击路线。 例如,如果您想要浏览一堆JSON响应负载,则应该使用我的下划线 - CLI模块 - 结构化数据的实用工具带。

    优点缺点:

  • Pro:对于一个服务器人来说,在后端编写JavaScript已经成为学习现代UI模式的“门户药物”。 我不再畏惧编写客户端代码。
  • Pro:倾向于鼓励适当的错误检查(几乎所有的回调函数都会返回错误,唠叨程序员来处理它;另外,async.js和其他库处理“失败,如果任何这些子任务失败”范例比典型的同步代码好得多)
  • Pro:一些有趣且通常艰巨的任务变得微不足道 - 例如获取飞行中任务的状态,工作人员之间的通信或共享缓存状态
  • Pro:庞大的社区和庞大的图书馆基于稳固的软件包管理器(npm)
  • Con:JavaScript没有标准库。 当你使用JSON.parse或其他一些不需要添加npm模块的构建方式时,你会习惯于导入那些感觉不可思议的功能。 这意味着一切都有五个版本。 即使是Node.js“核心”中包含的模块,如果您对默认实现不满意,还有五个变体。 这导致了快速的演变,但也有一定程度的混乱。
  • 与简单的每个请求请求模式(LAMP)相比:

  • Pro:可扩展至数千个活动连接。 非常快速和非常有效。 对于网络车队,这可能意味着相对于PHP或Ruby而言,所需的盒子数量减少10倍
  • 亲:写平行模式很容易。 想象一下,你需要从Memcached中获取三个(或N个)blob。 在PHP中执行此操作...您是否只是编写代码获取第一个blob,然后是第二个,然后是第三个? 哇,这很慢。 有一个特殊的PECL模块可以解决Memcached的特定问题,但是如果您想要与数据库查询并行地提取一些Memcached数据呢? 在Node.js中,因为范例是异步的,有Web请求并行执行多个事情是非常自然的。
  • Con:异步代码基本上比同步代码复杂,如果开发人员没有充分了解并行执行的实际含义,那么开发人员很难了解前面的学习曲线。 尽管如此,与使用锁定编写任何类型的多线程代码相比,它要困难得多。
  • Con:如果计算密集型请求运行时间例如为100毫秒,它将会停止处理在同一个Node.js进程中处理的其他请求... AKA,协作式多任务处理。 这可以通过Web Workers模式(分离子流程来处理昂贵的任务)来缓解。 或者,您可以使用大量的Node.js工作者,并且只让每个人同时处理单个请求(因为没有进程回收,所以仍然非常高效)。
  • Con:运行一个生产系统要比Apache + PHP,Perl,Ruby等CGI模型复杂得多。未处理的异常会降低整个过程,因此需要逻辑来重新启动失败的工作器(请参阅集群)。 具有越野车本机代码的模块可能会导致进程崩溃。 每当工作人员死亡时,它所处理的任何请求都将被丢弃,因此一个漏洞百出的API可能会轻易降低其他合并API的服务质量。
  • 与Java / C#/ C编写“真正的”服务(真的吗?)

  • Pro:在Node.js中执行异步操作比在其他任何地方执行线程安全性更简单,并且可以提供更大的好处。 Node.js是迄今为止我工作过的最不痛苦的异步范例。使用好的库,它比编写同步代码稍微难一些。
  • Pro:没有多线程/锁定错误。 诚然,您可以在撰写更详细的代码时进行投入,这些代码可以表达正确的异步工作流程,而无需阻止操作。 而且你需要编写一些测试并使其正常工作(这是一种脚本语言,胖指法变量名只能在单元测试时被捕获)。 但是,一旦你开始工作,海森堡的表面面积 - 奇怪的问题只会在一百万次运行中出现一次 - 表面面积要低得多。 编写Node.js代码的税很大程度上被加载到编码阶段。 那么你往往会得到稳定的代码。
  • Pro:JavaScript对于表达功能来说更加轻量。 很难用文字来证明这一点,但是JSON,动态类型,lambda表示法,原型继承,轻量级模块,无论如何......它只是用较少的代码来表达相同的想法。
  • Con:也许你真的很喜欢用Java编码服务?
  • 有关JavaScript和Node.js的另一个角度,请查看从Java到Node.js,这是一篇关于Java开发人员的博客文章,介绍如何学习Node.js。


    模块在考虑节点时,请记住,您选择的JavaScript库将定义您的体验。 大多数人至少使用两个异步模式助手(Step,Futures,Async)和一个JavaScript糖模块(Underscore.js)。

    助手/ JavaScript糖:

  • Underscore.js - 使用这个。 去做就对了。 它使你的代码更好,并且可以读取诸如_.isString()和_.isArray()之类的东西。 我不确定你如何写出安全的代码。 另外,对于增强的命令行fu,请查看我自己的Underscore-CLI。
  • 异步模式模块:

  • 步骤 - 表达串行和并行操作组合的非常优雅的方式。 我个人的建议。 查看我的帖子,了解步码的外观。
  • 期货 - 更灵活(这真的是一件好事?)通过需求表达订单的方式。 可以表达“开始a,b,c并行”,当A和B完成时,启动AB,当A和C完成时,启动AC。 这种灵活性需要更多注意力来避免工作流程中的错误(比如从不调用回调或多次调用)。 请参阅Raynos关于使用期货的文章(这是让我“获得”期货的文章)。
  • 异步 - 更传统的库,每种模式都有一种方法。 在开始我的宗教转换之前,我开始了这一步,并随后意识到Async中的所有模式都可以用一个更具可读性的范式在Step中表达。
  • TameJS - 由OKCupid编写,它是一个预编译器,它增加了一种新的语言“等待”,以优雅地编写串行和并行工作流程。 模式看起来很棒,但它确实需要预编译。 我仍然在这个问题上下定决心。
  • StreamlineJS - 与TameJS的竞争对手。 我倾向于驯服,但你可以自己决定。
  • 或者阅读有关异步库的所有信息,请参阅面板与作者的访谈。

    Web框架:

  • Express Ruby on Rails-esk框架来组织网站。 它使用JADE作为XML / HTML模板引擎,这使得构建HTML远不那么痛苦,甚至几乎优雅。
  • jQuery虽然技术上不是节点模块,但jQuery很快成为客户端用户界面的事实标准。 jQuery提供CSS样式的选择器来查询可以操作的DOM元素集(set handlers,properties,styles等)。 同样,Twitter的Bootstrap CSS框架,用于MVC模式的Backbone.js以及用于将所有JavaScript文件拼接成单个文件的Browserify.js。 这些模块已经成为事实上的标准,所以如果你没有听说过它们,你至少应该检查它们。
  • 测试:

  • JSHint - 必须使用; 起初我没有使用这个,现在看起来很难理解。 JSLint添加了一些基本的验证,你可以用Java等编译语言获得。 不匹配的括号,未声明的变量,许多形状和大小的类型。 你也可以开启我称之为“肛门模式”的各种形式,你可以验证空白的风格和什么,如果那是你的一杯茶,这是可以的 - 但真正的价值来自于获得即时反馈的确切行号你忘了关闭“)”......而不必运行你的代码并击中违规行。 “JSHint”是Douglas Crockford的JSLint的一个更可配置的变体。
  • 摩卡竞争对手誓言,我开始喜欢。 这两个框架都能很好地处理基础知识,但在Mocha中复杂的模式往往更容易表达。
  • 誓言誓言真的很优雅。 它打印出一个可爱的报告(--spec),显示哪些测试用例通过/失败。 花30分钟时间学习它,并且您可以用最少的努力为您的模块创建基本测试。
  • 僵尸 - 使用JSDom作为虚拟“浏览器”的HTML和JavaScript无头测试。 非常强大的东西。 将它与Replay结合起来,可以快速确定浏览器内代码的测试结果。
  • 评论如何“思考”测试:
  • 测试是非可选的。 使用JavaScript这样的动态语言,几乎没有静态检查。 例如,将两个参数传递给期望为4的方法在代码执行之前不会中断。 在JavaScript中创建bug相当低吧。 基本测试对弥补编译语言的验证差距至关重要。
  • 忘记验证,只是让你的代码执行。 对于每种方法,我的第一个验证案例是“没有中断”,这就是最经常发生的情况。 证明你的代码运行时不会丢失80%的错误,并且会做很多事情来提高你的代码的可信度,以至于你会发现自己回头并添加你跳过的细微的验证案例。
  • 从小处开始,打破惯性障碍。 我们都很懒惰,时间紧迫,很容易将测试看作“额外工作”。 所以从小开始。 编写测试用例0 - 加载你的模块并报告成功。 如果你强迫自己这么做,那么测试的惯性障碍就会​​被打破。 这是您第一次使用<30分钟,包括阅读文档。 现在编写测试用例1 - 调用其中一个方法并验证“没有任何中断”,也就是说,您不会收到错误。 测试用例1应该花费不到一分钟的时间。 随着惯性的消失,增加测试覆盖范围变得很容易。
  • 现在用你的代码演化你的测试。 不要被模拟服务器和所有这些“正确的”端到端测试看起来吓倒。 代码从简单开始并演变为处理新案例; 测试也应该。 当您为代码添加新案例和新复杂性时,请添加测试用例以运行新代码。 当您发现错误时,请添加验证和/或新案例来覆盖有缺陷的代码。 当你正在调试并失去对一段代码的信心时,请回过头来添加测试来证明它正在做你认为的事情。 捕获示例数据的字符串(来自您调用的其他服务,您抓取的网站),并将它们提供给解析代码。 在这里的一些情况下,改进了验证,并且最终会得到高度可靠的代码。
  • 另外,请查看推荐的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作为一个非常慎重的设计选择,每个进程只有一个线程。 因此,多线程同时访问数据基本上是不可能的。 因此,不需要锁。 线程很难。 真的很难。 如果你不相信,你没有做足够的线程编程。 正确锁定是很困难的,并且会导致很难追踪的错误。 消除锁和多线程会导致最糟糕的一类错误消失。 这可能是节点的最大优势。

    但我如何利用我的16核心盒?

    两种方式:

  • 对于图像编码等繁重的计算任务,Node.js可以启动子进程或将消息发送到其他工作进程。 在这个设计中,你将有一个线程管理事件流和N个进程,执行繁重的计算任务并咀嚼其他15个CPU。
  • 为了扩展web服务的吞吐量,您应该在一个盒子上运行多个Node.js服务器,每个核心使用一个集群(使用Node.js v0.6.x,此处链接的官方“集群”模块将替换learnboost版本,该版本具有一个不同的API)。 然后,这些本地Node.js服务器可以在套接字上竞争以接受新的连接,从而平衡它们之间的负载。 一旦连接被接受,它就会紧密地绑定到这些共享进程中的单个进程。 理论上,这听起来很糟糕,但实际上它运行得很好,并且可以避免编写线程安全代码的麻烦。 另外,这意味着Node.js可以获得出色的CPU高速缓存亲和性,更有效地利用内存带宽。
  • 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下编译大量的JIT与解释只作为执行一次代码后备)。 是的,我们都希望我们能够修复一些不寻常的JavaScript语言选择,但实际上并没有那么糟糕。 而且,这种语言非常灵活,你实际上不是编写JavaScript代码,而是使用JavaScript或JavaScript编写Step或jQuery,而不是任何其他语言,这些库定义了经验。 要构建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的一个实现。 它可以让你运行独立的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是真正令人兴奋的,这是我对图书馆/平台的介绍...我发现它很好。

    链接地址: http://www.djcxy.com/p/88891.html

    上一篇: What is Node.js?

    下一篇: How to add br tag with Jade HTML