Hot Code Loading in Node.js

Node.js Web应用代码热更新的另类思路

Reading through Fever today, this post by Jack Moffitt caught my eye. In it, he discusses a hack to allow a running Python process to dynamically reload code. While the hack itself, shall we say, lacks subtlety, Jack's post got me thinking. It's true, Erlang's hot code loading is a great feature, enabling Erlang's 99.9999999% uptime claims. It occurred to me that it wouldn't be terribly difficult to implement for node.js' CommonJS-based module loader.

A few hours (and a tasty home-made Paella later), here's my answer: Hotload node branch.

Umm… What does it do?

var requestHandler = require('./myRequestHandler');

process.watchFile('./myRequestHandler', function () {
module.unCacheModule('./myRequestHandler');
requestHandler = require('./myRequestHandler');
} var reqHandlerClosure = function (req, res) {
requestHandler.handle(req, res);
} http.createServer(reqHandlerClosure).listen(8000);

Now, any time you modify myRequestHandler.js, the above code will notice and replace the local requestHandler with the new code. Any existing requests will continue to use the old code, while any new incoming requests will use the new code. All without shutting down the server, bouncing any requests, prematurely killing any requests, or even relying on an intelligent load balancer.

Awesome! How does it work?

Basically, all node modules are created as sandboxes, so that as long as you don't use global variables, you can be sure that any modules you write won't stomp on others' code, and vice versa, you can be sure that others' modules won't stomp on your code.

Modules are loaded by require()ing them and assigning the return to a local variable, like so:

var http = require('http');

The important insight is that the return value of require() is a self-contained closure. There's no reason it has to be the same each time. Essentially, require(file) says "read file, seal it in a protective case, and return that protective case." require() is smart, though, and caches modules so that multiple attempts torequire() the same module don't waste time (synchronously) reading from disk. Those caches don't get invalidated, though, and even though we can detect when files change, we can't just call require() again, since the cached version takes precedence.

There are a few ways to fix this, but the subtleties rapidly complicate matters. If the ultimate goal is to allow an already-executing module (e.g., an http request handler) to continue executing while new code is loaded, then automatic code reloading is out, since changing one module will change them all. In the approach I've taken here, I tried to achieve two goals:

  1. Make minimal changes to the existing node.js require() logic.
  2. Ensure that any require() calls within an already-loaded module will return functions corresponding to the pre-hot load version of the code.

The latter goal is important because a module expects a specific set of behaviour from the modules on which it depends. Hot loading only works so long as modules have a consistent view of the world.

To accomplish these goals, all I've done is move the module cache from a global one into the module itself. Reloading is minimised by copying parent's caches into child modules (made fast and efficient thanks to V8's approach to variable handling). Any module can load a new version of any loaded modules by first removing that module from its local cache. This doesn't affect any other modules (including dependent modules), but will ensure that any sub-modules are reloaded, as long as they're not in the parent's cache.

By taking a relatively conservative approach to module reloading, I believe this is a flexible and powerful approach to hot code reloading. Most server applications have a strongly hierarchical code structure; as long as code reloading is done at the top-level, before many modules have been required, it can be done simply and efficiently.

While I hope this patch or a modified one will make it into node.js, this approach can be adapted to exist outside of node's core, at the expense of maintaining two require() implementations.

hot code loading in nodejs的更多相关文章

  1. how to read openstack code: loading process

    之前我们了解了neutron的结构,plugin 和 extension等信息.这一章我们看一下neutron如何加载这些plugin和extension.也就是neutron的启动过程.本文涉及的代 ...

  2. Nodejs in Visual Studio Code 02.学习Nodejs

    1.开始 源码下载:https://github.com/sayar/NodeMVA 在线视频:https://mva.microsoft.com/en-US/training-courses/usi ...

  3. crossplatform---Nodejs in Visual Studio Code 02.学习Nodejs

    1.开始 源码下载:https://github.com/sayar/NodeMVA 在线视频:https://mva.microsoft.com/en-US/training-courses/usi ...

  4. Visual Studio Code 断点调试Nodejs程序跳过node内部模块(internal modules)

    Built-in core modules of Node.js can be referred to by the ‘magic name’ <node_internals> in a ...

  5. Nodejs in Visual Studio Code 01.简单介绍Nodejs

    1.开始 作者自己:开发人员,Asp.Net , html / js , restful , memcached , oracle ,windows , iis 目标读者:供自己以后回顾 2.我看No ...

  6. crossplatform---Nodejs in Visual Studio Code 01.简单介绍Nodejs

    1.开始 作者自己:开发人员,Asp.Net , html / js , restful , memcached , oracle ,windows , iis 目标读者:供自己以后回顾 2.我看No ...

  7. NodeJS错误处理最佳实践

    NodeJS的错误处理让人痛苦,在很长的一段时间里,大量的错误被放任不管.但是要想建立一个健壮的Node.js程序就必须正确的处理这些错误,而且这并不难学.如果你实在没有耐心,那就直接绕过长篇大论跳到 ...

  8. linux -- ubuntu搭建nodejs环境

    需求:在web端做一个实时性功能比较强的模块, 客户端:用websocket 服务端:node.js node.js介绍:node.js天生就是一个高效的服务端语言,可以直接使用 javascript ...

  9. 如何远程调试部署在CloudFoundry平台上的nodejs应用

    网络上关于如何本地调试nodejs应用的教程已经很多了,工具有Chrome开发者工具,Visual Studio Code,和nodejs周边的一些小工具等等. 在实际情况中,我们可能遇到本地运行良好 ...

随机推荐

  1. geoserver 开发1

    打开项目,会看见下面这些包(其实还有很多插件之类的包,我都删除了) 5)可以从Eclipse启动GeoServer了. 如果你已经安装了GeoServer,现在也可以打开它的登陆页面进行操作. 三 结 ...

  2. ILSpy 反编译.NET

    ILSpy 是一个开源的.NET反编译工具,简洁强大易用是它的特征.在绝大多数情况下,它都能很好的完成你对未知程序集内部代码的探索.

  3. Vue2.0 keep-alive 组件的最佳实践

    1.基本用法 vue2.0提供了一个keep-alive组件用来缓存组件,避免多次加载相应的组件,减少性能消耗 <keep-alive> <component> <!-- ...

  4. <Linux多线程服务端编程>学习记录

    使用智能指针解决多线程下 类的解析冲突问题 有这样一个场景 使用StockFactory记录Stock的信息  容器是map<string,smart_ptr>; 代码如下: #inclu ...

  5. DataStage 八、清除日志

    DataStage序列文章 DataStage 一.安装 DataStage 二.InfoSphere Information Server进程的启动和停止 DataStage 三.配置ODBC Da ...

  6. document.body和document.documentElement区别

    1.document.documentElement表示文档节点树的根节点,即<html> document.body是body节点 2. 页面具有 DTD,或者说指定了 DOCTYPE ...

  7. 2018.09.07 bzoj1096: [ZJOI2007]仓库建设(斜率优化dp)

    传送门 斜率优化dp经典题. 令f[i]表示i这个地方修建仓库的最优值,那么答案就是f[n]. 用dis[i]表示i到1的距离,sump[i]表示1~i所有工厂的p之和,sum[i]表示1~i所有工厂 ...

  8. 2018.07.06 POJ1273 Drainage Ditches(最大流)

    Drainage Ditches Time Limit: 1000MS Memory Limit: 10000K Description Every time it rains on Farmer J ...

  9. 第九章:叹词(L'interjection )

    ➊叹词的使用词类 .拟声词.如:    Ah !啊!呀!哎!      Hein  !嗯!呣!哎!    Paf  !啪!叭!             Pouf  !扑通(重物坠地声)    Euh ...

  10. spring boot web项目在IDEA下热部署解决办法(四步搞定)

    最近在用spring boot 做一个web站点,修改了类.html.js等,刷新页面,没有生效,非要手动去make一下或者重启,大大降低了开发效率. 什么是热部署? 应用启动后会把编译好的Class ...