【译】 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 ...
随机推荐
- Codeforces Gym 100523E E - Gophers SET
E - GophersTime Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hust.edu.cn/vjudge/contest/view.a ...
- 从零开始学习Hadoop--前言
Hadoop是最著名使用最广泛的分布式大数据处理框架,它是用Java开发的. 这本书有一个明确的目标:只要有一台能上网的计算机,就可以让读者在最短的时间内,学会Hadoop的初级开发.所以,这本书只讲 ...
- search result
https://github.com/search?l=java&p=86&q=Floating+window&type=Code&utf8=%E2%9C%93http ...
- android152 笔记 4
42. Android中Task任务栈的分配. 首先我们来看下Task的定义,Google是这样定义Task的:a task is what the user experiences as an &q ...
- PAT 1020
1020. Tree Traversals (25) Suppose that all the keys in a binary tree are distinct positive integers ...
- mysql重连,连接丢失:The last packet successfully received from the server--转载
原文地址:http://nkcoder.github.io/blog/20140712/mysql-reconnect-packet-lost/ 1.1 错误信息: Caused by: com.my ...
- ( 转转)Android初级开发第九讲--Intent最全用法(打开文件跳转页面等)
大家好,今天跟大家谈谈Intent的用法. Intent在安卓中主要用于打开另外一个页面,这个页面可能是一个activity也可能是一个应用,也可能是 其它…… 且看下面介绍,总结摘抄网友一些 ...
- 用 UIViewPropertyAnimator 编写动画
[iOS 10 day by day] Day 1:开发 iMessage 的第三方插件 [iOS 10 day by day] Day 2:线程竞态检测工具 Thread Sanitizer < ...
- hdfs: 数据流(二)
大部分的HDFS程序对文件操作需要的是一次写多次读取的操作模式. 一个文件一旦创建.写入.关闭之后就不需要修改了.这个假定简单化了数据一致的问题和并使高吞吐量的数据访问变得可能. 1. 读文件 从上图 ...
- cocos2d-x3.x使用rapidjson
rapidjson效率高,所以之前cocostudio里面解析用的jsoncpp也换成了rapidjson. 引擎又带有rapidjson库,所以不用单独去下载,直接就可以用. 这里主要写一下关于解析 ...