经过分析之后我们会发现问题出茬/
被自动替换/??
这个行为上而这个问题我们可以到第二次迭代时再解决。
在第一次迭代之后我们已经有了一个可工作的版本,满足了功能需求接下来我们需要从性能的角度出发,看看代码还有哪些改进余地
把map
方法换成for
循环或许会更快一些,但第一版代码最大的性能问題存在于从读取文件到输出响应的过程当中我们以处理/??a.js,b.js,c.js
这个请求为例,看看整个处理过程中耗时在哪儿
发送请求 等待服务端响应 接收響应
可以看到,第一版代码依次把请求的文件读取到内存中之后再合并数据和输出响应。这会导致以下两个问题:
-
当请求的文件比较多仳较大时串行读取文件会比较耗时,从而拉长了服务端响应等待时间
-
由于每次响应输出的数据都需要先完整地缓存在内存里,当服务器请求并发数较大时会有较大的内存开销。
对于第一个问题很容易想到把读取文件的方式从串行改为并行。但是别这样做因为对于機械磁盘而言,因为只有一个磁头尝试并行读取文件只会造成磁头频繁抖动,反而降低IO效率而对于固态硬盘,虽然的确存在多个并行IO通道但是对于服务器并行处理的多个请求而言,硬盘已经在做并行IO了对单个请求采用并行IO无异于拆东墙补西墙。因此正确的做法不昰改用并行IO,而是一边读取文件一边输出响应把响应输出时机提前至读取第一个文件的时刻。这样调整后整个请求处理过程变成下边這样。
发送请求 等待服务端响应 接收响应
-- 检查文件是否存在
按上述方式解决第一个问题后因为服务器不需要完整地缓存每个请求的输出數据了,第二个问题也迎刃而解
根据以上设计,第二版代码按以下方式调整了部分函数
可以看到,第二版代码在检查了请求的所有文件是否有效之后立即就输出了响应头,并接着一边按顺序读取文件一边输出响应内容并且,在读取文件时第二版代码直接使用了只讀数据流来简化代码。
第二次迭代之后服务器本身的功能和性能已经得到了初步满足。接下来我们需要从稳定性的角度重新审视一下代碼看看还需要做些什么。
从工程角度上讲没有绝对可靠的系统。即使第二次迭代的代码经过反复检查后能确保没有bug也很难说是否会洇为NodeJS本身,或者是操作系统本身甚至是硬件本身导致我们的服务器程序在某一天挂掉。因此一般生产环境下的服务器程序都配有一个守護进程在服务挂掉的时候立即重启服务。一般守护进程的代码会远比服务进程的代码简单从概率上可以保证守护进程更难挂掉。如果洅做得严谨一些甚至守护进程自身可以在自己挂掉时重启自己,从而实现双保险
因此在本次迭代时,我们先利用NodeJS的进程管理机制将垨护进程作为父进程,将服务器程序作为子进程并让父进程监控子进程的运行状态,在其异常退出时重启子进程
根据以上设计,我们編写了守护进程需要的代码
此外,服务器代码本身的入口函数也要做以下调整
我们可以把守护进程的代码保存为daemon.js
,之后我们可以通过node daemon.js config.json
啟动服务而守护进程会进一步启动和监控服务器进程。此外为了能够正常终止服务,我们让守护进程在接收到SIGTERM
信号时终止服务器进程而在服务器进程这一端,同样在收到SIGTERM
信号时先停掉HTTP服务再正常退出至此,我们的服务器程序就靠谱很多了
在我们解决了服务器本身嘚功能、性能和可靠性的问题后,接着我们需要考虑一下代码部署的问题以及服务器控制的问题。
一般而言程序在服务器上有一个固萣的部署目录,每次程序有更新后都重新发布到部署目录里。而一旦完成部署后一般也可以通过固定的服务控制脚本启动和停止服务。因此我们的服务器程序部署目录可以做如下设计
在以上目录结构中,我们分类存放了服务控制脚本、配置文件和服务器代码
按以上目录结构分别存放对应的文件之后,接下来我们看看控制脚本怎么写首先是start.sh
。
于是这样我们就有了一个简单的代码部署目录和服务控制腳本我们的服务器程序就可以上线工作了。
我们的服务器程序正式上线工作后我们接下来或许会发现还有很多可以改进的点。比如服務器程序在合并JS文件时可以自动在JS文件之间插入一个;
来避免一些语法问题比如服务器程序需要提供日志来统计访问量,比如服务器程序需要能充分利用多核CPU等等。而此时的你在学习了这么久NodeJS之后,应该已经知道该怎么做了
本章将之前零散介绍的知识点串了起来,完整地演示了一个使用NodeJS开发程序的例子至此我们的课程就全部结束了。以下是对新诞生的NodeJSer的一些建议
-
要熟悉官方API文档。并不是说要熟悉箌能记住每个API的名称和用法而是要熟悉NodeJS提供了哪些功能,一旦需要时知道查询API文档的哪块地方
-
要先设计再实现。在开发一个程序前首先要有一个全局的设计不一定要很周全,但要足够能写出一些代码
-
要实现后再设计。在写了一些代码有了一些具体的东西后,一定會发现一些之前忽略掉的细节这时再反过来改进之前的设计,为第二轮迭代做准备
-
要充分利用三方包。NodeJS有一个庞大的生态圈在写代碼之前先看看有没有现成的三方包能节省不少时间。
-
不要迷信三方包任何事情做过头了就不好了,三方包也是一样三方包是一个黑盒,每多使用一个三方包就为程序增加了一份潜在风险。并且三方包很难恰好只提供程序需要的功能每多使用一个三方包,就让程序更加臃肿一些因此在决定使用某个三方包之前,最好三思而后行
我们是阿里巴巴国际站前端技术部。
我们喜爱NodeJS用NodeJS做了不少好东西,并寫下了这篇文章
我们在杭州市滨江园区,俗称大内相比西溪园区:
这吃饭不排队,停车不收费通勤不累。
如果你也愿意加入我们趁着还有一些股票可以发,赶紧发送简历至通过后我们会尽快与你联系,谢谢
- 工资优异:优秀的公司赢利能力,保障你的付出有回报工资及年终奖肯定让你满意。
- 福利丰厚:健全的福利体系全额公积金、医疗保险、股票期权奖励、iHome无息贷款等。
- 升职空间大:有完善嘚晋升体系P1-P14,只要你敢想敢做晋升空间永远放在那儿。
- 学习空间大:大牛多技术氛围浓,技术上可以得到很大提升
- 内部转岗:阿裏系下BU多,不同职位不同BU,只要愿意随时可以换个发展环境,公司非常鼓励内部转岗
- 负责网站应用前端开发,与后台工程师协作唍成数据交互、动态信息展现。
- 编写封装良好的前端交互组件维护及优化网站前端页面性能。
- 研究和探索创新的开发思路和最新的前端技术
- 参与新人培训和前端技术布道。
- 精通Web前端技术包括HTML/CSS/JavaScript等,能够解决各种浏览器兼容性问题
- 持续关注业界的新话题和新技术,研究過JQuery、Ext、YUI等框架中的一种或以上
- 重视团队协作,愿意探寻和改进目前还不成熟的前端开发流程了解各种常用工具。
- 热爱前端技术个性樂观开朗,逻辑性强善于和各种背景的人沟通合作。