写点什么

Node.js V0.12 新特性之在单进程中跑多个实例

  • 2014-04-01
  • 本文字数:1962 字

    阅读完需:约 6 分钟

实例

经常有人提出,希望 Node.js 能被嵌入到其他程序中,特别是让它能跟其他事件循环整合而且(与此同时)支持多个 Node 执行情境:也就是说让多个 Node 实例在同一个进程中和平共处的能力。想象一下,比如有个 node-webkit 程序,每个窗口都运行在自己的 Node 实例上,各窗口彼此相互独立。或者把 Node 嵌在手机或网络交换机里,处理多连接的路由逻辑,但却只是在单个进程中,并且不久的将来就能实现。

一个客户找到我们,说他们的程序需要这类功能。他们经过调研,肯定了我们在 Node 核心和 libuv 上的贡献和专业能力,决定请我们帮忙。这是个相当有挑战性的订单,因为Node 一开始就是- 并且现在仍然是- 一个单线程的程序,围绕着单一事件循环的概念构建,用上百个全局变量存放各种状态。

你可以想象一下,在这样的代码库上加装线程安全是多么容易出错的任务,所以那不是我们要做的- 或者说我们还没那么做。我们希望这个修改对客户来说经济实惠,并且向前迈出这一步也能帮到整个社区。顺便说一下,如果你发现自己需要对Node 做些修改,可自己又没时间研究该怎么改,我们可以帮忙!

引入多情境

实际上,我们在Node v0.12 中实现了在同一个事件循环中使用多个执行情境的能力。别担心:对普通用户来说并没有显性的变化,一切都和以前一样。但如果你是嵌入开发人员,或本地附加组件作者,请继续往下看!

提交 756b622 中的“多情境”工作是第一次,也是最重要的清理任务:它把所有全局变量审了一遍,首先去掉了那些不需要放在全局中的变量,并将剩下的变成了执行情境的属性。虽然那还不足以保证线程安全,但这第一步很重要。

第二步是让 Node 内部意识到多执行情境的存在。C++ 运行时在任何地方进入 V8 VM,都要先确保它进入的是正确的情境。下面是一个简单的例子:

复制代码
function onconnect() {
this.write('GET / HTTP/1.1\r\n' +
'Host: strongloop.com\r\n' +
'\r\n');
this.pipe(process.stdout);
}
require('net').connect(80, 'strongloop.com', onconnect);

Execution-wise,差不多应该是这个样子的:

复制代码
<enter VM>
connect(80, 'strongloop.com'); // kernel reports EINPROGRESS here
<leave VM>
<wait for TCP handshake to complete>
<enter VM>
onconnect();
<leave vm>

在进入 VM 的调用之间可能会改变执行情境。因此 connect() 有必要记住当前情境,并且调用 onconnect() 能恢复它。如果做不到这一点,追踪 bug 将会变得极其困难。

好在 Node 可以自动把这个处理好;嵌入开发人员和本地附加组件作者不需要担心这个,除非他们想用 v8::Function::Call() 代替 node::MakeCallback() 进入 VM 做调用。

如果你是本地附加组件作者,想让你的附件组件具备识别情境的能力,你需要:

复制代码
* Instead of NODE_MODULE(), use
NODE_MODULE_CONTEXT_AWARE(). Before:
void Initialize(v8::Handle<v8::Object> exports) {
// ...
}
NODE_MODULE(foo, Initialize)

之后:

复制代码
void Initialize(v8::Handle<v8::Object> exports,
v8::Handle<v8::Value> module,
v8::Handle<v8::Context> context) {
// ...
}
NODE_MODULE_CONTEXT_AWARE(foo, Initialize);

能识别情境的初始化方法在嵌入创建的每个情境都会被调用一次。现在还没有各情境的清理函数,最终会由 node::AtExit() 承担这一职责,但目前还是一个针对进程的事件。如果对你来说这样不行,请在这里提交个bug。

将全局变量变成各情境的属性有几种办法,其中一个是为你自己宣称一个嵌入数据索引,并把所有东西都存在那里。

这些索引还没有全局注册表,所以仍有发生冲突的可能。有没有想试着给打个补丁?同时挑一个差不多大的随机数(比如2^10 到2^16 之间的),但不要太极端:V8 用一个非稀疏矩阵作为嵌入索引的内部存储。将索引宣称为1 << 29 就会消耗很多内存!

还有多少工作要做?

这里还有些粗糙的边界需要打磨:process.chdir() 会改变所有情境的工作目录,但实际上应该只改变调用它的情境的工作目录;从多情境中加载附加组件还有些边界情况,等等诸如此类的地方。但那属于修修补补力求尽善尽美的工作了。基本框架已经到位了,并且那家赞助我们开发多情境特性的公司已经成功地用上它了。更重要的是,它为多线程多重租赁铺平了道路。那在Node v0.12 之前不太可能发生了,但我们可能会在Node v1.0 或另一个版本中见到它- 只要我们敢!

作者简介

本文最初由 Ben Noordhuis 发表在 StrongLoop 上。Ben Noordhuis 从 2010 年就跟着 Ryan Dahl 开发 Node.js 的核心代码。他一直在为改进 Node 核心代码而努力做着编码、调试和基准测试等工作。作为最高产的 Node 核心开发者之一,Ben 编写了 Node.js 和 libuv 中的很多代码。 StrongLoop 降低了在 Node 中开发APIs 的难度,还添加了监测、集群化以及私有注册的支持等DevOps 能力。

查看英文原文: What’s New in Node.js v0.12 – Running Multiple Instances in a Single Process

2014-04-01 22:564529
用户头像

发布了 45 篇内容, 共 26.2 次阅读, 收获喜欢 11 次。

关注

评论

发布
暂无评论
发现更多内容

量化策略交易软件开发|量化策略交易系统APP开发

系统开发

在函数计算中到底该不该使用 VPC?

donghui

Serverless

WiFi6 与 5G 的异同分析

石君

5G wifi 28天写作

百度智能小程序打造购票观影一站式体验,影视宣发新玩法助力行业复苏

DT极客

OpenYurt v0.3.0 重磅发布:全面提升边缘场景下应用部署效率

阿里巴巴云原生

阿里巴巴 开源 容器 云原生 k8s

Redis 学习笔记 03:字典

架构精进之路

redis 七日更 28天写作

自动驾驶汽车的发展史

anyRTC开发者

人工智能 自动驾驶 AI

比特币矿机工作原理

v16629866266

比特币 比特币区块链

Linux网络之 从 C10K 到 DPDK

赖猫

c++ Linux linux编程 C10K DPDK

开发更便捷 阿里云推出一站式应用研发平台EMAS 2.0

移动研发平台EMAS

阿里云 Serverless AI 低代码 移动研发平台

百度研究院的追星逐浪,中国科技的奋发自强

脑极体

高并发架构---TCP

赖猫

TCP 后端 高并发 TCP/IP 服务器开发

【HTML】已经废弃的align(图像对齐方式)

德育处主任

html html5 Web html/css 28天写作

数据库表数据量大读写缓慢如何优化(2)「查询分离」

我爱娃哈哈😍

数据库 大数据 架构 后端 优化

Intel首次公布11代酷睿桌面处理器性能:8核i9斩落锐龙12核

科技新消息

红牛交易所app系统开发

威掂l8929545452

区块链 系统开发 APP开发 红牛交易所

解决Windows2012 R2下安装PostgreSQL报错的问题

PostgreSQLChina

数据库 postgresql 开源

避免短信接口被黑客刷取的方法

香芋味的猫丶

短信防刷 接口安全 短信验证码 短信防轰炸 短信防火墙

BI项目失败?看看是不是缺少了这几项闭环!

博文视点Broadview

量化交易系统开发

威掂l8929545452

区块链 系统开发 量化交易系统 交易所

流行的后台管理系统模板总结

老魚

程序员 建站 web全栈

Linux I/O 原理和 Zero-copy 技术全面揭秘

赖猫

c++ Linux linux编程 服务器开发 I/O

开发老人笔记:Git 常用命令清单

华为云开发者联盟

git 代码 bug

区块链轻节点:“身”轻,责任重

华为云开发者联盟

区块链 数据 数据隐私 轻节点

TypeScript 渐进迁移指南

LeanCloud

JavaScript typescript nodejs

Java Optimizing 读书笔记(一)

绝影-大数据

需求条目化:一个让用户故事有效落地的套路

华为云开发者联盟

敏捷 项目 需求条目化

即构微信小程序直播组件是什么?有哪些功能?哪些小程序类目可以使用?

ZEGO即构

如何利用策略模式避免冗长的if-else/switch分支判断代码?

李尚智

Java 学习 设计模式

现货合约量化交易系统开发搭建

薇電13242772558

数字货币 策略模式

Serverless 架构到底要不要服务器?

Serverless Devs

Java 云计算 Serverless 运维 云原生

Node.js V0.12新特性之在单进程中跑多个实例_架构/框架_Ben Noordhuis_InfoQ精选文章