Node.js开发指南 Node.js不适用的应用领域
沉沙 2018-06-13 来源 : 阅读 1312 评论 0

摘要:Node.js是一个服务器端JavaScript解释器,本文列举了Node.js不适用的应用领域,希望阅读本篇文章以后大家有所收获,帮助大家对Node.js的理解更加深入。

Node.js是一个服务器端JavaScript解释器,底层采用的还是libevent;它的目标是帮助程序员构建高度可伸缩的应用程序,目前 对Node.js 的采用状况,Node.js 官方站点有一些罗列,但是相当不完整。如果你自己公司用到,也可以在 github 上提交自己的 pull-request 来更新这个文档。

//nodejs.org/industry/

https://github.com/joyent/node/wiki/Projects,-Applications,-and-Companies-Using-Node

其实到今天为止,很少有哪些大的互联网公司是和 Node.js 无关的。LinkedIn,Yahho,Paypal, eBay, Walmart 都在将既有的系统向 Node.js 迁移(https://www.quora.com/Node-js/What-companies-are-using-Node-js-in- production 梯子看)。国内的淘宝、网易、百度等也都有很多项目运行在 Node.js 之上。

每天都有几百个新的 packages 被发布到 npm 上,小到几行代码,大到万行代码的 Framework。一天有7百万次的包下载(安装到某台电脑上),对于单一开发框架的社区来说,用沸腾的海洋来形容并不过分。


以下应用领域和程序员不适合选择Node.js:

· 计算密集型应用。Javascript 的计算性能是很难和 C 语言代码相比的。当然,也有反例://onlinevillage.blogspot.jp/2011/03/is-javascript- is-faster-than-c.html,只不过不具有典型性。

· 需要精密控制内存的分配和释放的场景,如果用 Node.js 实现 Redis 数据库,虽然程序会简单不少,但是 JVM 对内存数据结构的精密控制能力是比不了用 C 语言纯手工打造的。

· 大量且需要频繁通过 C Binding 调用 C library 的情况。这种场景下,往返参数的 Marshal/Unmarshal 的成本可能会大于 C Library 带来的性能提升。

· 实时性要求很高的场景,例如:交换机或者工控机器人。这是因为所有通过垃圾回收机制来管理内存的系统都有可能在 GC 过程中产生停顿,从而影响响应速度,而且很难优化。

· 需要单一进程控制大内存的场景:v8 引擎的设计限制,在 32-bit下有 1GB 最大堆尺寸的限制,在 64-bit下是1.7GB。当然,由于 node.js buffer 的分配不是在 v8 的堆上,因此可以超过此限制。这个限制可以通过向 v8 引擎传递max_old_space_size 参数来超越,但是也会带来 GC 的性能退化。这一问题在几乎所有 GC Based 的系统下都存在。

· 不关心系统吞吐率或者不需要异步调用的场景:例如,自动化脚本,这些脚本不需要关心多用户并发访问的性能消耗。用 Python 这样的“胶水”语言写起来会更简单。

· 某些非通用场景:例如 nginx 对于静态 web server 或者 反向代理的场景是特别设计的,这些场景中 nginx 的性能比 Node.js 要好。

· 强类型强迫症:有些 Java 或者 .NET 过来的程序员会认为只有强类型语言和严格定义的类型系统是专业化的象征,构造这样的系统是架构师的使命,而动态语言只是玩具,只能用来做 Demo 或者前端开发。

· 团队成员难以理解或者接受函数式编程:Javascript 本质上更像函数式语言,有些程序员在理解和使用闭包、高阶函数等概念时总是不能习惯,这个问题在国内的开发团队中还挺普遍的。

· 回调式编程的不习惯:Node.js 的异步IO 大量依赖回调。回调让程序的执行出现了两条路径,出现故障时调用栈也很难理解。这对习惯了同步编程的程序员来说一开始确实是个坎。async, Q promise 等 package 可以缓解这个问题(在 ES6 的Generator 普及之前),不过这也带来了更陡峭的学习曲线。一般情况下,需要半年到一年的习惯过程,当然前提是多看,多写。随着越来越多的经验分享,这个过程也在不断 地缩短。

除此之外的领域,或者没有上述问题的,都都可以享受到 Node.js 带来的生产力提升和稳定的性能保障。


性能的争议

不同开发环境间的性能对比从来都是有争议的话题。我只能说,当开发 Web 或 网络环境下的应用时,Node.js 靠以下几个方面来避免出现不必要的性能问题:

1. Chrome V8,一个可靠的优秀的虚拟机(hidden classes 和 inline caching),让 Javascript 的运行速度进入了第一阵营(C++, Java, .NET)。

2. 异步 IO 大大降低了线程数量,莫名其妙的死锁和等待的概率被降低了很多。大部分场景不用去考虑并发和同步锁,犯错误的机会少。而在 Python 中,异步 IO 并不是标准,并没有被贯穿到所有 Package 中,因此应用程序也就很难获得一致的性能保障。

3. 非常轻巧的“内核”。Node.js 的模块分为 Core Modules 和 Userland 两部分。Core Modules 非常精简,只包括 TCP, HTTP, DNS, File System, child processes 和其他一些模块,这些网络库还只有异步版本。相对地,在 Userland 中却有着海量的 Packages。开发应用的时候,我们根据应用的需求来组合 Userland 的 Packages,使得我们的应用程序有机会在一个很低的资源消耗水平下运行(在《Announcing ql.io》中 指出,一台开发服务器就可以支持 12 万活跃连接,平均每个连接消耗 2k 内存)。事实上,我开发的 WebSockte 应用在 Raspberry Pi 下都可以支持几百并发长连接(WebSocket)。和那些动辄上万个类的企业开发框架相比,这是一个巨大的优势。这种方式降低了出现问题的概率、查找问 题的成本以及减少部署成本。

对 Javascript 的绝对性能的追求一直没有停顿(例如, Mozilla 的 asm.js )。而 Node.js 则在绝对性能的基础上,确保应用程序可以获得稳定和可预测的性能保障( Benchmark 和实际的应用运行往往是两回事)。


Node.js继承了JavaScript 的灵活性,优秀的JS库应当如何选择

可以在 npmjs.org 或者 google 上搜索关键词。如果类似的返回很多,则看其被其他 package 依赖的数量有多少。上 github 上查看 starred 和 forks 的数量,读 issues。

如果是“名人”(substack, visionmedia (TJ Holowaychuk), dominictarr, rvagg 等)写的 Packages 自然会被加分。

最后是把 Git Repo. Clone 或者 Fork 下来, 阅读且注释他们的源代码。这个过程也可以发现很多他们依赖的其他 Packages。这是一个蛮享受的过程,可以学到很多新知识和新的用法。

还有一些乱枪打鸟的方法:

1. 在 Tweeter 上关注 @nodenpm,所有在 npm 上发布或者更新的 packages 都会在该 handle 上发布出来。在你的碎片时间没事可以刷刷这个,当然你需要梯子。

2. 关注一些推荐和评论账号:@dailyjs,@echojs 等。

3. Changelog 会提供不错的开源信息汇总,其中包括 Node.js、Javascript 和 npm 栏目。

4. Hacker News 则不会让你忽略软件行业的一些“大事”或者新概念。

一个项目开始前的研究阶段,我大约会浏览几十个 Packages,精读其中的5 ~ 10个。开发过程中则根据需要还会不断地发现和精读一些,这些都被我计入了项目的成本。

“自由选择,自己负责”,在这个庞大的开发社区了不要指望有人能告诉你“标准答案”。每个人面临的问题域和知识背景都不一样,坚持多看,多试,多思考,享受获得新知识的过程比获得“标准答案”更重要。


在众多的成熟开发框架下为什么需要Node.js

在每一个特定的问题域,大家总是在尝试找到最优解。这个过程是没有终结的,就想最终也会有其他框架代替 Node.js 一样。

今天的 Web,是无数相互连接的 Web Services 组成的,这些连接的本质是异步的。Node.js 天生异步的特性和这个场景的匹配度相对其他开发框架要更高,因此实现起来也更自然。

除此之外,Node.js 的设计基本原则遵循了 《Unix 的编程艺术》,参见 Isaac Z. Schlueter (前任 Node.js 的Gatekeeper,目前负责 npm 的商业化) 的Blog: Unix Philosophy and Node.js。

npm 和 stream 就是上述哲学的产物。


npm

npm 是 Node.js 的包管理系统。包管理系统不是新东西,但是和 npm 的那些前辈和表兄弟不同的是:

1. npm 直接集成在 Node.js 中,无需单独安装,发布,安装 packages 非常简单。

2. npmjs.org 提供一个统一的入口,你可以看到每个 package 被哪些 packages 所依赖,你也可以一目了然地看到它依赖了誰,以及最近的下载次数。结合到 github 上的更新情况,基本上对一个 package 的基本情况你都能了解到。

3. 约定俗成的发布规范:一个 git repo. 让你可以直接找到源代码;README.md 提供简要的说明让消费者能尽快用起来。

对于开发者来说,每一个 package 就是一个 “micro service”,是最小重用单元。大部分的 package 只有几百行代码,甚至有些只有几行代码。这样的重用粒度是在其他社区难以想象的。

在 Node.js 的应用的开发过程中,编写 “一口尺寸”(bite-size)的 module 是推荐的编程方式。这也很方便你把这些小 module 封装为 package 分享到社区当中,而不用担心泄露“企业机密”。

npm 是每一个 Noder 的 “home”,也是每一个 Node.js 应用的系统架构的一部分。


Stream

如果说,npm 提供了“开发时重用”的机制,那么 stream 的则提供了“运行时”不同组件之间的“重用”机制。stream 概念和 unix 中的 stream 对应,应用中的每一个 component 则对应 unix 的 filter。下面举一个实际的例子:

在某个应用中,我需要一个 API Server,它的客户端包括 Web Browser,iOS App., 以及网络中的其他 Server。Web Browser 和我们的 API Server 的通信基于 SockJS(当 然你也可以选择 SocketIO,或者 Faye 等),它为浏览器兼容提供了适当的 “Fallback” 方案;对于 iOS App.来说,由于不需要考虑浏览器兼容,则采用基于标准的 RFC 6455 的纯 WebSocket 通信协议,这样实现起来更简单;而对于其他 Server 来说,局域网内则用 TCP,互联网上则用 TLS 来保证传输安全。

我在 Node.js 上是这么实现的:

· 利用 donde 构建一个通信无关的 RPC Server 来提供 API 服务。

· 用 Node.js Core Modules 中的 tcp, tls 创建 TCP/TLS Server 并监听,用第三方的 SockJS 和 websocket-stream 分别创建 SockJS 和 WebSocket 的 Server 并监听。

· 当 Client 连接到不同的端口,在 Server 上就会创建基于该协议的 Commnucation Stream,然后创建一个新的 dnode 实例,得到一个 dnode 的 Stream。最后将 Commnucation Stream 和 dnode Stream 像接水管一样接到一起即可。


net.createServer(function(connStream){  
    dnodeStream = dnode({ func1: function(){} });  
    connStream.pipe(dnodeStream).pipe connStream;  
});

   

考虑到在不稳定的网络环境下的自动重连需求,也可以添加 reconnect。

不算你自己 RPC API 的实现逻辑,支持这么多的通信协议的 Server 框架只需要百十行代码,还加上了一定程度的异常处理。

tcp, tls, SockJS,或者 reconnect 的开发者并不能确定“消费者”是如何使用这些 Package 的,但是大家都支持 Stream 的接口,则让自己的 Package 能够被运用到更多的场景。

进一步,我们也可以多路复用一个底层的 Stream。我们把上面的例子再扩展一下:

在既有的通信连接上(connStream),除了提供 RPC API 之外,还需要添加分布式的状态同步功能,例如:通过 Scuttlebutt,完成 Client 与 Server 或 Server 与 Server 之间的常量数据自动同步,而不用为这些功能设计新的 RPC API。通过 mux-demux ,可以复用既有的网络通信 Stream(tcp, SockJS, Web Socket…),避免建立不必要的网络连接。

Stream 是 Node.js 的核心概念之一,其接口和工作方式被广泛地采用,为不同组件在运行时相互通信提供了最基本的支持。

在 Node.js 中,如何使用 Stream 可以用一本书的容量来描述,不是因为 Stream 的概念有多复杂,而是因为其组合方式非常丰富。


本文由职坐标整理发布,欢迎关注职坐标Node.js频道,学习更多WEB前端知识!

本文由 @沉沙 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式AI+学习就业服务平台 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved