Zong
[书单推荐]《深入浅出Node.js》
  • Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境。
  • Node.js 使用了一个事件驱动、非阻塞式 I/O 的模型,使其轻量又高效。

2018年12月,2018年的最后一个月,我选择开始阅读《深入浅出Node.js》,在读完本书后,我找到印刷信息,看到第一版时间是2013年12月,也就是5年前。不得不说作者朴灵之强大。

我也不想中规中矩的把书中的内容搬运出来记录在此,虽然说中规中矩的搬运过程是可以加深记忆的,但是我最后决定还是算了,毕竟这不如直接去看书或者网上冲浪来的更快些。那么为了写这篇博客,我还是得从书中搬运一些内容至此,OK,搬运就搬运吧,但是我仅参考了印刷信息及目录。当然我相信未来当我再次深入Node.js的时候,我任然能从中获得实践经验。

首先来谈论下Node.js为何可以在后端领域崛起,看下近年来后端服务模型的变迁:

  • 石器时代:同步
  • 青铜时代:复制进程
  • 白银时代:多线程
  • 黄金时代:事件驱动

Node.js得以从后端领域崛起的原因之一是依靠事件驱动这一优点。

我先来谈谈我对这4个时代的理解,可以说石器时代的服务端处理请求都是同步进行的,形象点理解就是,你在办理业务的时候需要排队等候。青铜时代为了解决这个问题使用了复制进程,就好比多窗口办理业务,大家在银行或者营业厅都有遇到过吧。白银时代多线程可以来说是一个质的飞跃,比如 Java 就是多线程的, JavaScript 就是单线程的,那么同样的,多线程也带来了一些复杂的问题,比如锁状态等……,利用 JavaScript 的单线程也就避免了锁状态等问题。黄金时代则是利用事件驱动,事件驱动讲通俗点可以理解成 setTimeout ,只不过 setTimeout 的第二参数 delay 是由毫秒数决定,而事件驱动则是由事件决定,你可以理解成当满足这个事件时,执行需要执行的函数,其实在浏览器环境中 window.addEventListener 也是一种。

那么 Node.js 的非阻塞式 I/O 的模型充分利用了事件驱动发挥了其高效的性能。举个例子,当你在执行 I/O 操作时,如果代码阻塞,那么你后面的代码会受到阻塞,在进行大型 I/O 操作时会很严重的影响到你的程序效率。非阻塞式 I/O 的模型却不是这样,则采用回调的形式,来执行 I/O 操作完成后应该执行的代码。这种非阻塞的形式是非常的高效的。

这些特点使得 Node.js 得以在后端领域崛起,并且这些特点能让你很深刻的感受异步编程,但是 Node.js 也同样存在着缺点,总之万物都有 Good Parts 和 Bad Parts,所以在认识万物时,都得充分的知道这两部分,值得学习的是要学会正面面对和接受 Bad Parts ,本书中写到了很多面对 Bad Parts 时提供的解决方案,这样就能更好的提升 Node.js 性能,将 Node.js 的性能发挥到极致。

接下来谈论下 Bad Parts ,一定要说是 Bad Parts 吗?好像也不一定,因为它让你学到了更多的知识:

首先要面对的问题是单线程,毕竟 Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境。OK,那么单线程有什么问题呢?有个最致命的问题,一但线程出错,整个线程就会退出……捞不捞?说捞也捞,说不捞也不捞,要怪就怪开发没把抛异常写好,导致线程退出。单线程还有什么问题呢,你看,现在都是多核 CPU 单线程开着一个进程在跑, CPU 资源是不是浪费了,有一张很搞笑的图。

pic-1

那么如何利用起其他的核呢? Node.js 提供了 child_process(子进程)的功能,你可以启动跟你服务器 CPU 内核数相同的进程来提供服务,来提升你的服务能力,关于进程自动重启,进程监听同一端口,负载均衡等等实践可以看书或自己尝试。

再来需要面对的问题就是内存控制了,毕竟服务器也好,电脑也好,内存总是有限的。内存控制的主要手段有手动释放内存和自动的垃圾回收,手动释放内存其实就比较考验开发的基础。毕竟内存泄漏这个问题还是比较棘手的,泄漏了多了也就炸了。

再者是一些常用的数据存在内存里面,用户量多了,内存一样爆,存数据库吗?也不行数据库存储毕竟也是异步的,也会出现很多意想不到的问题。社区现在一般都用 Redis 来解决,用于存放一些 Session 数据和常用数据,当然我记得书中还提及了其他的工具,当然这不重要,重要的是你要知道如何控制内存。

来讲讲一个程序(服务端代码、前端代码、开源项目等等)是否健壮,这时候需要对程序本身进行测试,单元测试是其中必不可少的一部分。说到单元测试,我对我自己的玩具项目编写了单元测试代码,在编写单元测试的过程中我也发现,测试覆盖率报告同样也很重要,它能告诉我我的单元测试编写的是否全面,这时候你会发现 Travis CI , Jenkins 这类自动化工具的重要性。它们可以帮你完成一些繁琐而又重复的事情,不止是在生成测试覆盖率报告上,还有打包部署等等功能,所以好好利用这些自动化工具能提高你的开发效率,当然测试是用来提高你的代码质量。同样的,除了单元测试还有性能测试的存在。当然在项目上线后,对项目进行预警、监控显得同样的重要,这里到头来还是会回归到一个问题,用户体验。

当阅读完本书后,我才领略到后端领域如此之大,本书提及的内容如此之广泛,不仅是更了解了服务端,也对个工程化有了更多的认识和学习,也同样的,我需要花更多的时间去实践它们,所以我的 JavaScript 之路仍然在继续,在继续前行,脚下的砖也在慢慢的砌。