node . js中集群的模块深入解读

  


  

  

在如今机器的CPU都是多核的背景下,节点的单线程设计已经没法更充分的“压”榨机器性能了,所以从v0.8开始,节点新增了一个内置模块——“集群”,故名思议,它可以通过一个父进程管理一坨子进程的方式来实现集群的功能。

  

学习集群之前,需要了解过程相关的知识,如果不了解的话建议先阅读过程模块,child_process模块。
  

  

集群借助child_process模块的fork()方法来创建子进程,通过叉方式创建的子进程与父进程之间建立了IPC通道,支持双向通信。
  

  

集群模块最早出现在节点。js v0.8版本中
  

  


  

  

节点。js是单线程的,那么如果希望利用服务器的多核的资源的话,就应该多创建几个进程,由多个进程共同提供服务。如果直接采用下列方式启动多个服务的话,会提示端口占用。
  

        const http=要求(“http”);   赫特普。res createServer(点播)=比;{   res.writeHead (200);   res.end (“hello world \ n”);   }).listen (8000);//启动第一个服务节点索引。js和//启动第二个服务节点索引。js和      把呃;//未处理的“错误”事件   ^      错误:听EADDRINUSE::: 8000   在服务器上。setupListenHandle [_listen2) (net.js 1330:14):   listenInCluster (net.js 1378:12):   在服务器上。听(net.js 1465:7):   在对象灵活;anonymous>(/用户/洗剂/工作/学习/node-basic/集群/simple.js: 25:4)   在模块。_compile(内部/模块/cj/loader.js: 702:30)   在Object.Module._extensions . .js(内部/模块/cj/loader.js: 713:10)   在模块。负载(内部/模块/cj/loader.js: 612:32)   在tryModuleLoad(内部/模块/cj/loader.js: 551:12)   在Function.Module。_load(内部/模块/cj/loader.js: 543:3)   在Function.Module.runMain(内部/模块/cj/loader.js: 744:10)      

如果改用集群的话就没有问题
  

        const集群=要求(“集群”);   const http=要求(“http”);   const numCPUs=要求(os) .cpus . length ();      如果(cluster.isMaster) {   控制台。日志(“${大师的过程。pid}运行”);//叉工人。   (让我=0;我& lt;numCPUs;我+ +){   cluster.fork ();   }      集群。(“退出”(工人、代码、信号)=比;{   控制台。日志($ {worker.process的工人。pid}去世的);   });   其他}{//员工可以分享任何的TCP连接//在这种情况下,它是一个HTTP服务器   赫特普。res createServer(点播)=比;{   res.writeHead (200);   res.end (“hello world \ n”);   }).listen (8000);      控制台。日志(“工人${过程。pid}开始');   }//节点索引。js执行完启动了一个主进程和8个子进程(子进程数与cpu核数相一致)   主11851年运行   11852年工人   11854年工人   11853年工人   11855年工人   11857年工人   11858年工人   11856年工人   工人11859年开始      


  

  

集群创建的进程分两种,父进程和子进程,父进程只有一个,子进程有多个(一般根据cpu核数创建)

  
      <李>父进程负责监听端口接受请求,然后分发请求。   <李>子进程负责请求的处理。   
  

有三个问题需要回答:

  
      <李>子进程为何调用听不会进行端口绑定李   <李>父进程何时创建的TCP服务器   <李>父进程是如何完成分发的   
  


  

  

净。js源码中的听方法通过listenInCluster方法来区分是父进程还是子进程,不同进程的差异在listenInCluster方法中体现
  

        函数listenInCluster(服务器地址、端口、addressType积压,fd, excluseive) {      如果集群。isMaster | |独家){   服务器。_listen2(地址、端口、addressType积压,fd);   返回;   }      const serverQuery={地址:地址……};      集群。_getServer(服务器、serverQuery listenOnMasterHandle);      函数listenOnMasterHandle(呃,处理){   服务器。_handle=处理;   服务器。_listen2(地址、端口、addressType积压,fd);   }   }      

上面是精简过的代码,当子进程调用听方法时,会先执行_getServer,然后通过回调的形式指定服务器。_handle的值,之后再调用_listen2方法。
  

        集群。_getServer=函数(obj、期权、cb) {   …   const消息=util._extend ({   行为:“queryServer”,   指数:索引(indexesKey),   数据:零   },选项);      消息。地址=地址;      (发送消息(回复、处理)=比;{   如果(处理)   共享(回复、处理、indexesKey cb);//共享监听套接字。   其他的   rr(回复,indexesKey cb);//循环。   });   …   

node . js中集群的模块深入解读