当前位置: 首页 > news >正文

hot code loading in nodejs

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.

转载于:https://www.cnblogs.com/hangj/p/4989628.html

相关文章:

  • java中的基本数据类型
  • Eclipse如何生成jar包
  • 磁盘文件系统管理命令
  • java中char数据类型的使用
  • java中数据类型间的强制转换
  • Linux 命令行发邮件sendmail,mailutils,mutt msmtp
  • System.out.println与System.out.print的区别
  • 用tomcat搭建https
  • java语句
  • 痛下决心学java
  • 第三方登录(QQ篇)
  • java中的访问权限
  • Scala特质
  • java中的全局变量与局部变量
  • WPF自定义控件与样式(9)-树控件TreeView与菜单Menu-ContextMenu
  • Android交互
  • ES学习笔记(12)--Symbol
  • flask接收请求并推入栈
  • golang 发送GET和POST示例
  • PV统计优化设计
  • redis学习笔记(三):列表、集合、有序集合
  • seaborn 安装成功 + ImportError: DLL load failed: 找不到指定的模块 问题解决
  • Spark VS Hadoop:两大大数据分析系统深度解读
  • Spring Boot快速入门(一):Hello Spring Boot
  • 成为一名优秀的Developer的书单
  • 前端工程化(Gulp、Webpack)-webpack
  • 深入浅出Node.js
  • 使用parted解决大于2T的磁盘分区
  • 用jQuery怎么做到前后端分离
  • HanLP分词命名实体提取详解
  • ​软考-高级-系统架构设计师教程(清华第2版)【第15章 面向服务架构设计理论与实践(P527~554)-思维导图】​
  • #pragma预处理命令
  • #我与Java虚拟机的故事#连载03:面试过的百度,滴滴,快手都问了这些问题
  • #我与Java虚拟机的故事#连载15:完整阅读的第一本技术书籍
  • (2)关于RabbitMq 的 Topic Exchange 主题交换机
  • (42)STM32——LCD显示屏实验笔记
  • (Git) gitignore基础使用
  • (NO.00004)iOS实现打砖块游戏(九):游戏中小球与反弹棒的碰撞
  • (附源码)spring boot北京冬奥会志愿者报名系统 毕业设计 150947
  • (附源码)计算机毕业设计SSM基于java的云顶博客系统
  • (附源码)计算机毕业设计SSM疫情下的学生出入管理系统
  • (十三)Java springcloud B2B2C o2o多用户商城 springcloud架构 - SSO单点登录之OAuth2.0 根据token获取用户信息(4)...
  • (完整代码)R语言中利用SVM-RFE机器学习算法筛选关键因子
  • (译) 理解 Elixir 中的宏 Macro, 第四部分:深入化
  • (源码版)2024美国大学生数学建模E题财产保险的可持续模型详解思路+具体代码季节性时序预测SARIMA天气预测建模
  • .htaccess 强制https 单独排除某个目录
  • .NET Core WebAPI中使用swagger版本控制,添加注释
  • .Net(C#)常用转换byte转uint32、byte转float等
  • .NET/C# 使用 SpanT 为字符串处理提升性能
  • .NET开源的一个小而快并且功能强大的 Windows 动态桌面软件 - DreamScene2
  • .Net下C#针对Excel开发控件汇总(ClosedXML,EPPlus,NPOI)
  • .Net中ListT 泛型转成DataTable、DataSet
  • [ CTF ] WriteUp- 2022年第三届“网鼎杯”网络安全大赛(白虎组)
  • [202209]mysql8.0 双主集群搭建 亲测可用
  • [Asp.net MVC]Asp.net MVC5系列——Razor语法