OurJS


OurJS-我们的JS, 我们的技术-IT文摘; 专注JS相关领域;
我们热爱编程, 我们热爱技术;我们是高大上, 有品味的码农;

欢迎您订阅我们的技术周刊


我们会向您分享我们精心收集整理的,最新的行业资讯,技术动态,外文翻译,热点文章;
我们使用第三方邮件列表向您推送,我们不保存您的任何个人资料,注重您的隐私,您可以随时退订,

欢迎分享您的观点,经验,技巧,心得

让我们一起找寻程序员的快乐,探索技术, 发现IT人生的乐趣;


本网站使用缓存技术每次加载仅需很小流量, 可在手机中流畅浏览;
如果您发现任何BUG,请即时告知我们: ourjs(at)ourjs.com

使用集群(recluster)扩展多线程Node.JS


分享到


分类 JS学习   关键字 JavaScript   发布 kris  1400289977725
注意 转载须保留原文链接,译文链接,作者译者等信息。  
简单的多进程服务

Gary ChambersGary Chambers

使用经典的Node.JS写的服务真的很快,一部分得益于它的非阻塞I/O接口,一部分得益于JavaScript V8引擎的特别优化。当然,其中的一个限制就是:JavaScript是单线程的,所以仅会使用到处理器的一个内核。不过,通过 recluster (集群)模块(Github: doxout/recluster, MIT) 让多核处理器发挥出它的优势是有可能的。


使用recluster


Recluster是建立在Node.JS内部集群处理能力之上的(cluster),为扩展子进程提供了一个简单的API,从而将程序扩展到所有可用的CPU核心。它也增加了一些细微的东西,像容错处理(expoenti... backoff)和热重启。

var cluster = recluster("/path/to/worker.js", {
    workers: 4,
    backoff: 10
});
cluster.run();

这段代码会产生4个工作(worker)进程,当一个子进程死掉会自动恢复(respawning)。工作进程(worker)主要负责初始化应用,绑定sockets或接口。因为这些,通常使用Node.JS的domain来封装你的应用,从而捕获异常:

var app = domain.create();
app.on("error", function(err) {
    cluster.worker.disconnect();
});
app.run(function() {
    http.createServer(function(req, res) {
        res.end("Hello World\n");
    }).listen(8000);
});


使用domain,工作进程的任何异常都会被domain的捕获,然后工作进程就可以优雅地死去了。当我们需要保证worker在一个不确定的状态下正常工作时,这通常都是一个很好的方案。


你可能会注意到,服务是在worker中实现的,而非父进程,这意味着我们要在同一个端口上绑定很多次,这明显不行,但是Node的集群机制帮我们处理了这个问题:任何在Worker代码中绑定接口或socket的操作其实都是在它的父进程中实现的;所有的工作进程都会共享同样的socket.

这样简单的处理方法使任何Node.js应用的多核布署都变得非常容易,但是这里也有限制。


状态和内存共享


Node.js操作的状态共享功能不是很多,而且没有本地的内存共享方法(注* 在进程间共享内存其实是不太安全的),但是这些限制可以在底层的灵性性上避免。

当一个应用从一个进程扩展开来时,维护状态变得越来越没有价值。在理想的状态下,应用应该是完全无状态的。客户端不确定到底是哪一个进程处理了它的请求,所以这并不总是可行的,比如:维护那些像带有用户会话状态(session)的连接,到合适的web应用这种情况。那么你该怎么办?

其实Node.js本身就开放了消息API(message),可以用来在进程间传递消息。这里有个简单的例子,这意味着所有的workers都会被通知到状态改变。

// Worker进程
http.createServer(function(req, res) {
    // do something to mutate state, and then...
    process.send("State changed!");
}).listen(8000);
// 父进程
worker.on("message", function(message) {
    // hypothetical connection pool object
    pool.broadcast(message);
});

这可能在应用非常小的时侯工作地很好,但是在应用中它不能保证状态的统一,而且很容易引起状态的不连续。如果一个worker丢失了一条广播,或者在发送消息前它被kill掉了,这样我们就会有一个不一致的状态,而且非常难以找到原因,甚至变得更难调试了。

这不是说进程内消息没什么用,但当应用扩展和变得复杂时它就会略显不足。尤其是当我们从一个单进程程序,扩展到多服务器多集群模式时,消息传递就解决不到任何问题了。

更好的选择是创建一个共享的状态代理程序。通常这个后台程序用来替换掉内存状态,我们需要一个足够快的选项:像Redis那样的。(在Node.js中启用Redis不在本文讨论的范围,但它是一个相当简单的工作)。通过这样,我们就可以有效地将“状态”从应用层转移到持久层,还能得到更好地分层这个额外的奖励。

当你的应用把状态保持的需求处理好以后,我们就可以很自信地将我们的应用发布到集群上了,然后享用我们弹性的,可扩展的,高性能构架。

原文地址: 点此
社区评论 ( Beta版 )
  • #0 redstone 1400635526000
    直接用pm2不好吗?多直接。也不用改代码
  • #1 思念生了病 1400641429000
    @redstone

    这种项目有很多, 有人喜欢轻量极的
OnceDoc 您自己的企业内容管理系统——文档、流程、知识库、报表、网盘All In One

访问404页面,寻找丢失儿童
 热门文章 - 分享最多
  1. 编程是一个没有前途的工作
  2. 你已经毁了JavaScript
  3. 是什么让Node.js比Java更快?
  4. 现在,你为什么应该学Node.js
  5. 将JavaScript 作为第一编程语言
  6. 什么是最优秀的JavaScript框架?Angular or Backbone?
  7. 使用Backbone构建精美应用的7条建议
  8. 抛弃jQuery,深入原生的JavaScript
  9. 干嘛不在企业中使用Node.js呢?
  10. 用JavaScript的5个原因
  11. 用 OnceAir 搭建个人Git/Svn/照片备份服务器,每年电费7块钱

 相关阅读 - JS学习
  1. 抛弃jQuery,深入原生的JavaScript
  2. 使用Backbone构建精美应用的7条建议
  3. 在jQuery API文档中并未提及的get用法,只有读了源码才会知道哦
  4. 如何在一个VPS上连接Node.js到一个MongoDB数据库?
  5. 用Orchestrate 5步快速创建Node.js应用
  6. iFrame的妙用
  7. JavaScript的MVC模式向导
  8. 快乐Node程序员的10个习惯
  9. 我最喜欢的jQuery插件模板
  10. Javascript模块化编程:AMD规范及require.js用法

 关键字 - JavaScript
  1. 用JavaScript获取当月第一天和最后一天
  2. 用JavaScript测试图像上两点之间的距离
  3. JSON序列化(stringify)对象时排除某些属性的两种方法
  4. 5个现在就该使用的数组Array方法: indexOf/filter/forEach/map/reduce详解
  5. JavaScript运算出现很多小数导致运算不精确的问题,用toFixed解决
  6. 用JavaScript实现node.js中的path.join方法
  7. 如何用CSS将select/option文本居中或居右对齐
  8. JavaScript中新建一个带全局变量参数的new Function动态函数
  9. 设置select元素中option的默认值
  10. 在JavaScript中创建命名空间的几种写法

 欢迎订阅 - 技术周刊

我们热爱编程, 我们热爱技术; 我们是高端, 大气, 上档次, 有品味, 时刻需要和国际接轨的码农; 欢迎您订阅我们的技术周刊; 您只需要在右上角输入您的邮箱即可; 我们注重您的隐私,您可以随时退订.
加入我们吧! 让我们一起找寻码农的快乐,探索技术, 发现IT人生的乐趣;


 关注我们

我们的微信公众号: ourjs-com
打开微信扫一扫即可关注我们:
IT文摘-程序员(码农)技术周刊

ourjs官方微信号