原文: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负载均衡的更多相关文章

  1. 【译】 Node.js v0.12的新特性 -- 性能优化

    原文: https://strongloop.com/strongblog/performance-node-js-v-0-12-whats-new/ January 21, 2014/in Comm ...

  2. Node.js V0.12 新特性之性能优化

    v0.12悠长的开发周期(已经过去九个月了,并且还在继续,是有史以来最长的一次)让核心团队和贡献者们有充分的机会对性能做一些优化. 本文会介绍其中最值得注意的几个. http://www.infoq. ...

  3. Node.js V0.12新特性之性能优化

    v0.12悠长的开发周期(已经过去九个月了,并且还在继续,是有史以来最长的一次)让核心团队和贡献者们有充分的机会对性能做一些优化.本文会介绍其中最值得注意的几个. 支持塞住模式的可写流 现在可写流可以 ...

  4. Atitit js版本es5 es6新特性

    Atitit js版本es5 es6新特性 Es5( es5 其实就是adobe action script的标准化)1 es6新特性1 Es5( es5 其实就是adobe action scrip ...

  5. Node.js v0.10.31API手冊-控制台

    Node.js v0.10.31API手冊-文件夹 控制台 Object 用于向 stdout 和 stderr 打印字符.类似于大部分 Web 浏览器提供的 console 对象函数,在这里则是输出 ...

  6. Node.js v0.10.31API手冊-事件

    Node.js v0.10.31API手冊-文件夹 Events(事件) Node里面的很多对象都会分发事件:一个net.Server对象会在每次有新连接时分发一个事件, 一个fs.readStrea ...

  7. 介绍Ext JS 4.2的新特性的《深入浅出Ext JS》上市

    以用户为中心的时代,应用的界面外观变得越来越重要.然而,很多程序员都缺乏美术功底,要开发出界面美观的应用实属不易.Ext JS的出现,为广大程序员解决了这一难题.它有丰富多彩的界面和强大的功能,是开发 ...

  8. atitit.js 各版本 and 新特性跟浏览器支持报告

    atitit.js 各版本 and 新特性跟浏览器支持报告 一个完整的JavaScript实现是由以下3个不同部分组成的 •核心(ECMAScript)--JavaScript的核心ECMAScrip ...

  9. Node.js v0.10.31API手工-DNS

    原版的API品种,这是从以前的翻译和翻译风格不同 Node.js v0.10.31API手冊-文件夹 DNS 使用 require('dns') 引入此模块. dns 模块中的全部方法都使用了 C-A ...

随机推荐

  1. Codeforces Round #331 (Div. 2) D. Wilbur and Trees 记忆化搜索

    D. Wilbur and Trees Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/596/p ...

  2. [ES6] 16. Object Enhancements

    Define object: var color = "blue"; var speed = 120; var car = {color, speed}; console.log( ...

  3. JS 文本输入框放大镜效果

    JS 文本输入框放大镜效果 今天下午研究了下 "文本输入框放大镜效果" 当然KISSY官网也有这种组件 请看kissy demo 其实这种效果 对于很多童鞋来说 应该并不陌生!我今 ...

  4. const int * pi/int * const pi的区别

    前面有一篇文章:数组名就是常量指针 参考文章:http://blog.pfan.cn/whyhappy/5164.html const int * pi .int const * pi与int *   ...

  5. Source Insight新建工程文件

    options->document options ->document type ->c source file 下 //添加 “.S”结尾的汇编语言支持   project -& ...

  6. [改善Java代码]Lock与synchronized是不一样的

    很多编码者都会还说,Lock类和synchronized关键字用在代码块的并发性和内存上时语义是一样的.

  7. 【转】【CDC翻客】移动端App测试实用指南

     译者注:本文从测试人员的角度出发,提出了100多个在测试移动App过程中需要考虑的问题.不管你是测试人员.开发.产品经理或是交互设计师,在进行移动App开发时,这些问题都很有参考价值.我和Queen ...

  8. CSS3秘笈第三版涵盖HTML5学习笔记1~5章

    第一部分----CSS基础知识 第1章,CSS需要的HTML HTML越简单,对搜索引擎越友好 div是块级元素,span是行内元素 <section>标签包含一组相关的内容,就像一本书中 ...

  9. 在虚拟机中安装Linux

    安装CentOS 6.4教程(详细步骤) CentOS是RHEL的克隆版本,功能上是一模一样的,另外重新编译之后还修复了一些后者的bug.主要区别就是CentOS免费,但没有官方的技术支持,而RHEL ...

  10. Linux 命令 - wget: 非交互式网络下载器

    命令格式 wget [option]... [URL]... 命令参数 启动选项 -V, --version 打印版本信息 -h, --help 打印帮助信息 日志和输入文件选项 -o logfile ...