背景
相信使用 Node.js 开发过 Web 应用的同学一定苦恼过新修改的代码必须要重启 Node.js 进程后才能更新的问题。习惯使用 PHP 开发的同学更会非常的不适用,大呼果然还是我大PHP才是世界上更好的编程语言。手动重启进程不仅仅是非常恼人的重复劳动,当应用规模稍大以后,启动时间也逐渐开始不容忽视。
当然作为程序猿,无论使用哪种语言,都不会让这样的事情折磨自己。解决这类问题最直接和普适的手段就是监听文件修改并重启进程。这个 *** 也已经有很多成熟的解决方案提供了,比如已经被弃坑的 node-supervisor,以及现在比较火的 PM2 ,或者比较轻量级的 node-dev 等等均是这样的思路。
本文则提供了另外一种思路,只需要很小的改造,就可以实现真正的0重启热更新代码,解决 Node.js 开发 Web 应用时恼人的代码更新问题。
总体思路
说起代码热更新,当下最有名的当属 Erlang 语言的热更新功能,这门语言的特色在于高并发和分布式编程,主要的应用场景则是类似证券交易、游戏服务端等领域。这些场景都或多或少要求服务拥有在运行中运维的手段,而代码热更新就是其中非常重要的一环,因此我们可以先简单的了解一下 Erlang 的做法。
由于我也没有使用过 Erlang ,以下内容均为道听途说,如果希望深入和准确的了解 Erlang 的代码热更新实现,更好还是查阅官方文档。
Erlang 的代码加载由一个名为code_server的模块管理,除了启动时的一些必要代码外,大部分的代码均是由code_server加载。 当code_server发现模块代码被更新后,会重新加载模块,此后的新请求会使用新模块执行,而原有还在执行的请求则继续使用老模块执行。 老模块会在新模块加载后,被打上old标签,新模块则是current标签。当下一次热更新的时候,Erlang 会扫描还在执行老模块的进行并杀掉,再继续按照这个逻辑更新模块。 Erlang 中并非所有代码均允许热更新,如 kernel, stdlib, compiler 等基础模块默认是不允许更新的
我们可以发现 Node.js 中也有与code_server类似的模块,即 require 体系,因此 Erlang 的做法应该也可以在 Node.js 上做一些尝试。通过了解 Erlang 的做法,我们可以大概的总结出在 Node.js 中解决代码热更新的关键问题点
如何更新模块代码 如何使用新模块处理请求 如何释放老模块的资源
那么接下来我们就逐个的解析这些问题点。
如何更新模块代码
要解决模块代码更新的问题,我们就需要去阅读 Node.js 的模块管理器实现,直接上链接 module.js。通过简单的阅读,我们可以发现核心的代码就在于 Module._load ,稍微精简一下代码贴出来。
// Check the cache for the requested file.
// 1. If a module already exists in the cache: return its exports object.
// 2. If the module is native: call `NativeModule.require()` with the
// filename and return the result.
// 3. Otherwise, create a new module for the file and save it to the cache.
// Then have it load the file contents before returning its exports
// object.
Module._load = function(request, parent, isMain) {
var filename = Module._resolveFilename(request, parent);
var cachedModule = Module._cache[filename];
if (cachedModule) {
return cachedModule.exports;
}
var module = new Module(filename, parent);
Module._cache[filename] = module;
module.load(filename);
return module.exports;
};
require.cache = Module._cache;
可以发现其中的核心就是 Module._cache ,只要清除了这个模块缓存,下一次 require 的时候,模块管理器就会重新加载最新的代码了。
写一个小程序验证一下:
// main.js
function cleanCache (module) {
var path = require.resolve(module);
require.cache[path] = null;
}
setInterval(function () {
cleanCache(\\\’./code.js\\\’);
var code = require(\\\’./code.js\\\’);
console.log(code);
}, 5000);
// code.js
module.exports = \\\’hello world\\\’;
我们执行一下 main.js ,同时取修改 code.js 的内容,就可以发现控制台中,我们代码成功的更新为了最新的代码。
那么模块管理器更新代码的问题已经解决了,接下来再看看在 Web 应用中,我们如何让新的模块可以被实际执行。
更多关于 云服务器, 域名注册, 虚拟主机的问题,请访问 西部数码官网: www.west.cn前言:本文是原创首发。做站有几年了 (1)初识网络: 高中毕业时候,造化弄人,读了个计算机会计专业(听说好考,找工作容易,呵呵),结果不感兴趣,两年毕业后,全科考试通过,但会计证我都没拿就走了,觉得没意思,会计应该是女人干的活。大专期间,空闲时间很多,那时候有空就去机房(费用从餐...
编者:蓝色理想 www.blueidea.com 成立于1999年的10月,作为国内最大的设计类站点之一,以建设网站设计与开发人员之家为宗旨,以介绍网络开发技术与网站创作设计交流为主要内容。其网站内容制作精良,每天都会有会员精心制作的教程发布,无私地对网友进行帮助,而且还举办过不少设计比赛并...
这是一篇很难得的博客文章 ,一个自己说文笔不好,但是字里行间对公司深情的员工 ———————————————————————————— 看到很多朋友写博客在介绍自己的站,我虽然文笔不好,但是也时常有这种冲动,想把心里面的一些想法,或者自己的作品能让更多人去了解和指出不足的地方。 很荣幸加...
站长网(www.admin5.com) 与百度知道互联网(zhidao.baidu.com) 紧密合作,一起解决更多互联网方面的问题。给更多的站长和网络人解决问题。服务于互联网作努力本站站长 图王 也荣誉为百度知道知识专家团的一员。为更多的朋友解决网络问题 希望大家继续支持 站长网 支持 百...
仅以此文献给在PR上挣扎的站长们 google拥有世界上领先的搜索引擎技术,他们有最大的资金后盾,有最强的技术团队,有着别的公司无法比拟的公司文化底蕴。google全球最大的搜索引擎,搜索引擎界的大哥大。  ...
有个女孩叫君儿,男孩叫磊。他们通过QQ聊天认识了,然后经常写信聊天,到相识相知。03年的圣诞节他们见面了,彼此感觉应该还算 很不错,晚上在一起吃饭,在晚上一起去了我们学校过圣诞节。这一晚,君回学校宿舍了,2004年1月1日 元旦到了,磊磊非常想君儿,磊就打电话喊君一起出来玩,那一晚上我们都没有...