Node.【10bet】js中的Worker Threads

来源:http://www.chinese-glasses.com 作者:Web前端 人气:181 发布时间:2020-04-15
摘要:其他例子: 使用cluster 将自己的Node服务器扩展为多线程服务器,clusternode 用nodejs的朋友都有了解,node是单线程的,也就是说跑在8核CPU上,只能使用一个核的算力。 单线程一直是node的一

其他例子:

使用cluster 将自己的Node服务器扩展为多线程服务器,clusternode

用nodejs的朋友都有了解,node是单线程的,也就是说跑在8核CPU上,只能使用一个核的算力。
单线程一直是node的一个诟病,但随着0.6版本中引入cluster之后,这个情况则得到了改变,开发人员可以依靠cluster很轻松的将自己的Node服务器扩展为多线程服务器了。

什么是Cluster

cluster是node提供的一个多线程库,用户可以使用它来创建多个线程,线程之间共享一个监听端口,当有外部请求这个端口时,cluster会将请求转发到随机线程里。因为每个node线程都会占用几十兆的内存,所以不能像php那样对每个请求创建一个线程,一般来说创建的线程数最多都不会超过cpu的核心数量。

复制代码 代码如下:

var cluster = require('cluster');
var http = require('http');
var numCPUs = require('os').cpus().length;

if (cluster.isMaster) {
  // Fork workers.
  for (var i = 0; i < numCPUs; i++) {
    cluster.fork();
  }

  cluster.on('exit', function(worker, code, signal) {
    console.log('worker ' + worker.process.pid + ' died');
  });
} else {
  // Workers can share any TCP connection
  // In this case its a HTTP server
  http.createServer(function(req, res) {
    res.writeHead(200);
    res.end("hello worldn");
  }).listen(8000);
}

如以上代码所示,程序运行时cluster.isMaster会被设置为true,当调用cluster.fork()之后,程序会创建一个线程,并重新运行,这时cluster.isMaster就被设置为false了。我们就主要通过这个变量来判断当前线程是不是子线程的。

还可以注意到,每个子线程被创建之后,都会监听8000端口而不会引起冲突,这就是cluster共享端口的功能了。

线程之间的通信

当线程被创建之后,他们彼此之间是没有共享内存或者数据的。所有的数据交换只能通过worker.send和worker.on('message',handler)在主线程里处理,下面列举一个广播系统的实例。

复制代码 代码如下:

var cluster = require('cluster');
var http = require('http');
var numCPUs = require('os').cpus().length;

if (cluster.isMaster) {

  var workers=[];
  //新建worker
  function newWorker(){
    var worker=cluster.fork();

10bet,    //监听信息,如果type为broadcast的话,则确定为广播
    worker.on('message', function(msg) {
      if(msg.type=='broadcast'){
        var event=msg.event;
        //向所有worker发送此条广播
        workers.forEach(function(worker){
          worker.send(event);
        })
      }
    });
    return worker;
  }

  for (var i = 0; i < numCPUs; i++) {
    workers.push(newWorker());
  }

    cluster.on('online',function(worker){
        console.log('worker %d is online',worker.id);
    })
} else {
  var worker=cluster.worker;

  //广播就是发送一个type为broadcast的信息,event就是广播内容
  worker.broadcast=function(event){
    worker.send({
      type:'broadcast',
      event:event
    });
  }

  //这里用worker.on貌似不能监听到返回的信息
  process.on('message',function(event){
    console.log('worker: '+worker.id+' recived event from '+event.workerId);
  })

  //发送广播
  worker.broadcast({
    message:'online',
    workerId:worker.id
  })
}

需要注意的问题

在上面也提到,线程之间是不能共享数据的,所有的数据交换只能通过线程之间的通信来交换。而且所交换的数据都是可序列化的,所以函数,文件描述符和HttpResponse之类的东西都不能传递。

如果使用cluster,则需要在程序设计的时候考虑到数据交换的问题,我自己的做法就是将类似session的这些数据都存放在redis里,每个线程都做好存取的工作,所有的数据都不放在node内存里。

最后一点,cluster目前还被Node官方标记为Experimental状态,api在将来也许会改变。

http://www.bkjia.com/Javascript/908664.htmlwww.bkjia.comtruehttp://www.bkjia.com/Javascript/908664.htmlTechArticle使用cluster 将自己的Node服务器扩展为多线程服务器,clusternode 用nodejs的朋友都有了解,node是单线程的,也就是说跑在8核CPU上,只能使用一...

最好的解决方案是

so,有人或许会考虑给node.js添加一个新的模块来允许我们创建一个同步线程,以此来解决cpu敏感处理的问题。

const { Worker, isMainThread, parentPort, workerData } = require('worker_threads'); if (isMainThread) { module.exports = function parseJSAsync(script) { return new Promise((resolve, reject) = { const worker = new Worker(filename, { workerData: script }); worker.on('message', resolve); worker.on('error', reject); worker.on('exit', (code) = { if (code !== 0) reject(new Error(`Worker stopped with exit code ${code}`)); }); }); }; } else { const { parse } = require('some-js-parsing-library'); const script = workerData; parentPort.postMessage(parse(script)); }

变成:

时间: 2019-10-06阅读: 206标签: Worker

然而,这不会实现的。如果添加一个线程,这个语言的本质就会发生变化。使用类或者函数添加一个线程作为新特性是不可能。在支持多线程的语言中(如java),“synchronized”之类的关键字就能帮助实现多线程。

$ node --experimental-worker test.js{ pong: ‘ping’ }

明白cpu操作和i/o操作是很重要的。如上所讲,Node中的代码不能并行执行。只是i/o是并行,因为他们是异步执行的。

这段代码实际做的是使用new Worker创建了一个线程,在线程的内部使用parentPort来监听和接受一次性的message信息,接收到信息后也会发布一个message个猪线程。

执行:

所以,worker线程(以下我们会使用这个node特有的概念)不能提升多少i/o敏感的任务,因为异步i/o本身就比worker高效很多。worker的主要任务是提升cpu敏感操作的性能。

对Worker的期望是什么(希望是):传递本地处理任务。(passing native handles around)锁死检测。锁死是指一种情形,一系列进程被锁定,因为每个进程都把持了一些资源,而且每个线程又在等待其他线程所把持的资源释放然后获取。锁死检测在worker thead中比较有用。更多的隔离,所以一旦一个线程收到了影响,其他的没事。对Worker不期望的是:不要认为worker会使所有的东西都很快速,有些情况下最好使用线程池。不要使用worker来进行io并行操作。不要认为衍生一个线程成本很低。最后:

Worker Theads在Node.10时开始可以使用,但是一直处于实验状态,在12.11.0时,变成稳定版本。

黄金准则:不要锁定事件轮垂,尽量关注和避免那些可能造成锁定的任务,像是同步网路调用或者无线死循环。

一个线程

一个进程

一个JS隐情实例

一个Node.js实例:一个计算机程序用来执行node.js的代码。

Workers有chrome开发工具,可用来监视Node.js中的workers。

一个Node.js实例

下面这些使Worker Theads与众不同:

已有的解决方案

原文,翻译来自:-threads-nodejs

constworker =require('worker_threads');

一个进程

此外,这里已经有一些应对cpu敏感处理的方案:多进程(例如,cluster API)来保证cpu最大被利用。

一句话,Node运行在一个单线程上,每次事件轮垂只有一个进程存在。一个代码一次执行(不是并行执行)。这个非常重要,因为它很简单,你不用考虑并发的问题。

本文由10bet发布于Web前端,转载请注明出处:Node.【10bet】js中的Worker Threads

关键词:

上一篇:没有了

下一篇:没有了

频道精选

最火资讯