【译】 Node.js v0.12的新特性 -- Cluster模式采用Round-Robin负载均衡
原文:https://strongloop.com/strongblog/whats-new-in-node-js-v0-12-cluster-round-robin-load-balancing
本文地址:http://www.cnblogs.com/jasonxuli/p/4522134.html
Node.js v0.12的新特性 -- Cluster采用轮询调度算法来进行负载均衡
November 19, 2013 by Ben Noordhuis
欢迎来到由Node的核心提交者 Ben Noordhuis 和 Bert Belder撰写的系列博文的第一篇。本系列可能由7-8篇构成,主要涵盖了Node.js v0.12的新特性。本文主要是关于新的轮询调度集群算法。
回顾Node内置的cluster模式
忆往昔,Node令人扼腕之限制即其内在之单线程模式。不管你的机器有多少核心,Node只会利用一个(同时警告用户,某些操作会利用一个线程池。对于大多数程序来说,相对于总的CPU时间,这只是九牛一毛,因此这样做并不会对利用处理器资源起到真正的帮助)。
这也是Node.js v0.8引入内置的cluster模块的原因。cluster模块让你可以启动一个作为监管者的主进程,以及一个或多个做实际工作的工作进程。
其中的一个目的是使得你更容易创建“甩手掌柜”式的多进程服务器。完美情况下,你应该可以用一个现有的单进程程序制造出足够多的工作进程而不需要修改任何代码。
当然,事情没那么容易。但是cluster模块使得程序有很少甚至没有共享状态,或者可以将共享状态保存在外部资源中,比如数据库或者web service。将程序转换成集群模式基本上只需要几行代码:
var cluster = require('cluster');
var os = require('os'); if (cluster.isMaster)
// Spawn as many workers as there are CPUs in the system.
for (var i = 0, n = os.cpus().length; i < n; i += 1)
cluster.fork();
else
// Start the application.
app();
程序也不需要知道它是在集群模式下运行。
假如你的app()是下面这样:
var http = require('http'); function app() {
var server = http.createServer(function(req, res) {
res.end('OK');
});
server.listen(8080, 'www.example.com');
}
cluster模块的魔力保证了工作进程可以绑定被请求的地址和端口,即使其他工作进程已经监听了。另外,它保证了外部连接被平均分配到监听的工作进程 -- 至少是理论上。
在Node.js v0.8 和 v0.10中,分配外部连接的算法是很直接的。当工作进程调用http.Server#listen()或者net.Server#listen()时,Node.js 发送消息告诉主进程去创建并绑定一个服务端socket并共享给该工作进程。如果已经有了一个被绑定的socket,主进程就跳过创建并绑定的阶段,直接共享已存在的socket给该工作进程。
这意味着所有的工作进程都监听同一个socket。当新的连接进入时,操作系统唤醒某个工作进程。该进程于是接受该连接然后开始工作。
目前一切都好。操作系统收集运行进程的无数指标,应该因此处于决定进程调度的最好位置。
实际情况
现在到了理论遭遇复杂现实的部分。我们逐渐搞清楚了这一点,操作系统认为的“最优”并不总是等于程序猿认为的“最优”。我们已经观察到,特殊情况下,多数连接由两三个进程承接 -- 特别是Linux和Solaris系统。
从操作系统的视角看,这是有道理的:上下文切换(挂起一个进程然后重新激活另一个进程)是一个相当耗资源的操作。如果有多个进程监听同一个socket,那么唤醒最近被阻塞的进程是最聪明的做法,因为执行上下文切换的几率最小。(当然,调度程序是复杂易变的讨厌鬼;上述解释必然只是实际情况的粗略概括,然而某些进程获得偏向对待的基本前提仍然有效)
不是所有的程序都有这个怪异的情况 -- 实际上多数并不会 -- 但是在有问题的那些例子中可以看到负载不均衡的现象。
确认了问题的根源后,我们有一些对应的疗法,但无一令人满意。暂时不监听这socket以便使其他工作进程有机会接受新的连接,这个办法有点儿用,但是不够。获得“特殊照顾”的工作进程接受连接的比例从90%掉到了60-70%,好了点儿,但是还不够。也不用在意这种办法对于程序处理很多短时连接的能力的显著影响。
事情越来越清晰了,就像产生随机数一样,分配连接处理工作太重要了,我们不能靠几率。经过多次讨论后我们达成了一致 -- 这根救命稻草就是直接抛弃目前的方案,整体切换到另外的方案。Node.js v0.11.2版本切换到轮询调度方案的原因就在于此:新的请求连接由主进程接受并选择一个工作进程来处理。
目前选择工作进程的算法并不深奥。就像它的名字那样,是轮询 -- 只是选中下一个可用的工作进程 -- 但是经过核心开发者和用户的测试表明,它工作的很好: 请求连接现在被分配的很平均。后面还有计划把选择算法变成可配置或者基于插件的方式。
如果你想回退到之前的任务分配方式,你可以设置cluster.schedulingPolicy:
var cluster = require('cluster');
// Set this before calling other cluster functions.
cluster.schedulingPolicy = cluster.SCHED_NONE;
cluster.fork();
或者用NODE_CLUSTER_SCHED_POLICY这个环境变量来配置:
$ export NODE_CLUSTER_SCHED_POLICY="none" # "rr" is round-robin
$ node app.js
一次性的方法是:
$ env NODE_CLUSTER_SCHED_POLICY="none" node app.js
关于Windows
MS Windows是仅有的将旧方法作为默认的平台。Node.js在Windows平台采用的IOCP来最大化性能。虽然多数情况下都不错,但是它使得传递连接的句柄到其他进程的成本很高。也许在libuv中可以绕过这一点,但是还不清楚这样做是否有必要:Windows的端口并没有太受到类似Linux和Solaris那样的影响。
【译】 Node.js v0.12的新特性 -- Cluster模式采用Round-Robin负载均衡的更多相关文章
- 【译】 Node.js v0.12的新特性 -- 性能优化
原文: https://strongloop.com/strongblog/performance-node-js-v-0-12-whats-new/ January 21, 2014/in Comm ...
- Node.js V0.12 新特性之性能优化
v0.12悠长的开发周期(已经过去九个月了,并且还在继续,是有史以来最长的一次)让核心团队和贡献者们有充分的机会对性能做一些优化. 本文会介绍其中最值得注意的几个. http://www.infoq. ...
- Node.js V0.12新特性之性能优化
v0.12悠长的开发周期(已经过去九个月了,并且还在继续,是有史以来最长的一次)让核心团队和贡献者们有充分的机会对性能做一些优化.本文会介绍其中最值得注意的几个. 支持塞住模式的可写流 现在可写流可以 ...
- Atitit js版本es5 es6新特性
Atitit js版本es5 es6新特性 Es5( es5 其实就是adobe action script的标准化)1 es6新特性1 Es5( es5 其实就是adobe action scrip ...
- Node.js v0.10.31API手冊-控制台
Node.js v0.10.31API手冊-文件夹 控制台 Object 用于向 stdout 和 stderr 打印字符.类似于大部分 Web 浏览器提供的 console 对象函数,在这里则是输出 ...
- Node.js v0.10.31API手冊-事件
Node.js v0.10.31API手冊-文件夹 Events(事件) Node里面的很多对象都会分发事件:一个net.Server对象会在每次有新连接时分发一个事件, 一个fs.readStrea ...
- 介绍Ext JS 4.2的新特性的《深入浅出Ext JS》上市
以用户为中心的时代,应用的界面外观变得越来越重要.然而,很多程序员都缺乏美术功底,要开发出界面美观的应用实属不易.Ext JS的出现,为广大程序员解决了这一难题.它有丰富多彩的界面和强大的功能,是开发 ...
- atitit.js 各版本 and 新特性跟浏览器支持报告
atitit.js 各版本 and 新特性跟浏览器支持报告 一个完整的JavaScript实现是由以下3个不同部分组成的 •核心(ECMAScript)--JavaScript的核心ECMAScrip ...
- Node.js v0.10.31API手工-DNS
原版的API品种,这是从以前的翻译和翻译风格不同 Node.js v0.10.31API手冊-文件夹 DNS 使用 require('dns') 引入此模块. dns 模块中的全部方法都使用了 C-A ...
随机推荐
- 使用Filter防止浏览器缓存页面或请求结果
仅仅须要两步: 1.定义一个Filter: /** * 防止浏览器缓存页面或请求结果 * @author XuJijun * */ public class NoCacheFilter impleme ...
- DB9 公头母头引脚定义及连接
1.实物及引脚简单介绍 在做开发的时候常常会用到串行接口,一般9针的串行接口居多.例如以下图所看到的: 公头母头用于连接线的採用上图封装.但用于开发板的时候採用90度弯角插针的封装.例如以下图: 各引 ...
- 在Web上调用Ocx控件
原文:http://blog.csdn.net/goodadult2012/article/details/6343369 在HTML页面中使用ActiveX控件包含三个基本操作:将控件放入HTML中 ...
- python selenium自动化(二)自动化注册流程
需求:使用python selenium来自动测试一个网站注册的流程. 假设这个网站的注册流程分为三步,需要提供比较多的信息: 在这个流程里面,需要用户填入信息.在下拉菜单中选择.选择单选的radio ...
- 使用导入导出进行备份和恢复OCR(10g)
Oracle推荐在对集群调整时,比方添加.删除节点之前,应对OCR进行备份,能够用export备份到指定文件.假设做了replace或者restore等操作,Oracle建议使用cluvfy comp ...
- rand值出现负数的解决方案
当rand($number)或者mt_rand($number)的时候,$number太大,超过pow(2,31) - 1;即整型最大值的时候,会出现负数. 如果只是单纯转换成整数而已的话,可以采用s ...
- Python学习 之 内建函数
1.常用函数:abs().max().min().len().divmod().pow().round() 例1:abs返回数字绝对值 abs(10) #结果10 abs(-10) #结果10 例2: ...
- UNIX标准化及实现之UNIX标准化、UNIX系统实现、标准和实现的关系以及ISO C标准头文件
一.UNIX标准化 1.ISO C (International Organization for Standardization) 2.IEEE POSIX (Institue of Electri ...
- HttpServer的使用
http://docs.oracle.com/javase/8/docs/jre/api/net/httpserver/spec/overview-summary.html 1.Package com ...
- Pass value from child popup window to parent page window using JavaScript--reference
Here Mudassar Ahmed Khan has explained how to pass value from child popup window to parent page wind ...