精华内容
下载资源
问答
  • 2021-10-11 22:32:18

    一、多核CPU可以同时执行多个进程。

    扩展了说,单核CPU就可以“同时”执行多个进程。先普及两个概念,并发和并行。

    二、并发

    当有多个线程在操作时,如果系统只有一个CPU,则它根本不可能真正同时进行一个以上的线程,它只能把CPU运行时间划分成若干个时间段,再将时间 段分配给各个线程执行,在一个时间段的线程代码运行时,其它线程处于挂起状。.这种方式我们称之为并发(Concurrent)。

    三、并行

    当系统有一个以上CPU时,则线程的操作有可能非并发。当一个CPU执行一个线程时,另一个CPU可以执行另一个线程,两个线程互不抢占CPU资源,可以同时进行,这种方式我们称之为并行(Parallel)。

    三、区别

    并发和并行是即相似又有区别的两个概念,并行是指两个或者多个事件在同一时刻发生;而并发是指两个或多个事件在同一时间间隔内发生。在多道程序环境下,并发性是指在一段时间内宏观上有多个程序在同时运行,但在单处理机系统中,每一时刻却仅能有一道程序执行,故微观上这些程序只能是分时地交替执行。倘若在计算机系统中有多个处理机,则这些可以并发执行的程序便可被分配到多个处理机上,实现并行执行,即利用每个处理机来处理一个可并发执行的程序,这样,多个程序便可以同时执行。所以微观上说,多核CPU可以同时执行多个进程,进程数与CPU核数相当。但宏观上说,由于CPU会分时间片执行多个进程,所以实际执行进程个数会远多于CPU核数。

    更多相关内容
  • 多个进程监听同一个端口(multiple processes listen on same port) 方式1:通过 fork 创建子进程的方式可以实现,其他情况下不行。 当连接到来时,子进程、父进程都可以 accept, 这就是著名的“惊群”问题...

    单个进程监听多个端口

    单个进程创建多个 socket 绑定不同的端口,TCP, UDP 都行

    多个进程监听同一个端口(multiple processes listen on same port)

    方式1:通过 fork 创建子进程的方式可以实现,其他情况下不行。

    当连接到来时,子进程、父进程都可以 accept, 这就是著名的“惊群”问题(thundering herd problem)。

    NGINX 的 master/work 处理方法:

    Flow of an NGINX worker process

    可以设置 ffd 的 close-on-exec flag 避免子进程继承 fd.

    方式2:我们都知道socket是网络上两个进程之间的双向通信链路, 即

    socket = 《A进程的IP地址:端口号,B进程的IP地址:端口号》

    那么有个问题就很有意思了,不同的进程可以监听在同一个IP地址:端口号么?

    根据Unix网络编程中的知识可知,服务端监听一个端口会经历:

    1、根据套接字类型(Ipv4,Ipv6等)创建套接字socket

    2、将套接字bind绑定到具体的网络地址和端口号

    3、调用listen开始在这个套接字上进行监听。

    Unix提供了一个接口setsockopt()可以在bind之前设置套接字选项,其中就包括REUSEADDR这个选项,表明可以多个进程复用bind函数中指定的地址和端口号。

    由此可知多个应用(进程),包括同一个应用多次,都是可以绑定到同一个端口进行监听的。对应地C++、NET等高级语言也都提供了对应的接口。

    从一些例子也可以看出,比如有时候你在服务器上执行netstat -ano可能会发现同一个应用程序在同一个端口上有多个监听,这是因为一些服务端应用程序可能会异常退出或者没有完全释放套接字,但是需要在重新启动时还能够再次监听同一个端口,所以需要能够具备重复监听同一个端口的能力,因此也出现上述情形。

    在这总结一下多进程端口冲突问题的解决方法:
    1、更换端口号,适用于不受设备端口号限制的场景;
    2、父进程派生子进程,共享端口资源,适用于linux服务器端;
    3、端口复用,根据五元组的唯一性,可以实现,适用于任何场景,但需要绑定不同的IP地址;
    4、多进程共享socket,适用于主动发送报文的情况,对于主动接受报文的情景不适用;
    5、端口管理进程,由一个端口对该端口的数据收发进行管理,别的进程要使用的话,需要实现本地多进程之间通信;
    6、手动管理占用端口的进程(可操作性太差)

    展开全文
  • python使用多进程高效处理任务

    万次阅读 2022-05-05 14:21:59
    通常我们使用的程序都是单进程的,就好比我们只有一个工人在搬运货物,一次一次地来回搬运,多线程则是多个工人同时在搬运货物。而我们的电脑很多都是八核甚至是十六核的,平时我们写的程序就只是单进程在运行,其余...

    通常我们使用的程序都是单进程的,就好比我们只有一个工人在搬运货物,一次一次地来回搬运,多线程则是多个工人同时在搬运货物。而我们的电脑很多都是八核甚至是十六核的,平时我们写的程序就只是单进程在运行,其余的都会处于闲置状态。低效不说,程序跑起来也会特别慢。

    今天我们来学习一下多进程的一种简单用法,让你摆脱低效办公

    首先我们先导入multiprocessing库中的pool进程池,如下:

    from multiprocessing import Pool

    初始化线程池:

    pool = Pool()

    使用map()方法:

    pool.map(main, list)

    main为运行的函数,list是一个列表,向main函数传递参数

    关闭进程:

    pool.close()

    完整代码:

    from multiprocessing import Pool#导入方法
    pool = Pool()#初始化
    pool.map(main,list)#main为运行的函数,list是一个列表,向main函数传递参数
    pool.close()#关闭进程

    展开全文
  • 阅读目录 一:nodejs进程进化及多进程架构原理 ...NodeJS是基于chrome浏览器的V8引擎构建的,它是单线程单进程模式,nodeJS的单线程指js的引擎只有一实列。且是在主线程执行的,这样的优点是:可以减少线程间切换...

    阅读目录

    回到顶部

    一:nodejs进程进化及多进程架构原理

    NodeJS是基于chrome浏览器的V8引擎构建的,它是单线程单进程模式,nodeJS的单线程指js的引擎只有一个实列。且是在主线程执行的,这样的
    优点是:可以减少线程间切换的开销。并且不用考虑锁和线程池的问题。

    那么nodejs是单线程吗?如果严格的来讲,node存在着多种线程。比如包括:js引擎执行的线程、定时器线程、异步http线程等等这样的。

    nodejs是在主线程执行的,其他的异步IO和事件驱动相关的线程是通过libuv来实现内部的线程池和线程调度的。libuv存在着一个Event Loop,通过 Event Loop(事件循环)来切换实现类似多线程的效果。Event Loop 是维持一个执行栈和一个事件队列,在执行栈中,如果有异步IO及定时器等函数的话,就把这些异步回调函数放入到事件队列中。等执行栈执行完成后,会从事件队列中,按照一定的顺序执行事件队列中的异步回调函数。
    nodeJS中的单线程是指js引擎只在唯一的主线程上运行的。其他的异步操作是有独立的线程去执行。通过libuv的Event Loop实现了类似多线程的上下文切换以及线程池的调度。线程是最小的进程,因此node也是单进程的。

    理解服务器进程进化

    1. 同步单进程服务器

    该服务器是最早出现的,执行模型是同步的。它的服务模式是一次只能处理一个请求。其他的请求需要按照顺序依次等待处理执行。也就是说如果当前的请求正在处理的话,那么其他的请求都处于阻塞等待的状态。因此这样的服务器处理速度是不好的。

    2. 同步多进程服务器

    为了解决上面同步单进程服务器无法处理并发的问题,我们就出来一个同步多进程服务器,它的功能是一个请求需要一个进程来服务,也就是说如果有100个请求就需要100个进程来进行服务。那么这样就会有很大进程的开销问题了。并且相同的状态在内存中会有多种,这样就会造成资源浪费。

    3. 同步多进程多线程服务器

    为了解决上面多进程中资源浪费的问题,我们就引入了多进程多线程服务器模式,从我们之前一个进程处理一个请求,现在我们改成为一个线程来处理一个请求,线程相对于进程来说开销会少很多,并且线程之间还可以共享数据。并且我们还可以使用线程池来减少创建和销毁线程的开销。
    但是多线程也有缺点,比如多个请求需要使用多个线程来服务,但是每个线程需要一定的内存来存放自己的堆和栈的。这样就会导致占用太多的内存。第二就是:CPU核心只能处理一件事情,系统是通过将CPU切分为时间片的方法来让线程可以均匀地使用CPU的资源的。在系统切换线程的过程中也会进行线程上下文切换,当线程数量过多时进行上下文切换会非常耗费时间的。因此在很大的并发量下,多线程还是无法做到很好的伸缩性。Apache服务器就是这样架构的。

    4. 单进程单线程基于事件驱动的服务器

    为了解决上面的问题,我们出现了单进程单线程基于事件驱动的模式出现了,使用单线程的优点是:避免内存开销和上下文切换的开销。
    所有的请求都在单线程上执行的,其他的异步IO和事件驱动相关的线程是通过libuv中的事件循环来实现内部的线程池和线程调度的。可伸缩性比之前的都好,但是影响事件驱动服务模型性能的只有CPU的计算能力,但是只能使用单核的CPU来处理事件驱动,但是我们的计算机目前都是多核的,我们要如何使用多核CPU呢?如果我们使用多核CPU的话,那么CPU的计算能力就会得到一个很大的提升。

    5. NodeJS的实现多进程架构

    如上第四点,面对单线程单进程对多核使用率不好的问题,因此我们使用多进程,每个进程使用一个cpu,因此我们就可以实现多核cpu的利用。
    Node提供了child_process模块和cluster模块来实现多进程以及进程的管理。也就是我们常说的 Master-Worker模式。也就是说进程分为Master(主)进程 和 worker(工作)进程。master进程负责调度或管理worker进程,那么worker进程负责具体的业务处理。在服务器层面来讲,worker可以是一个服务进程,负责出来自于客户端的请求,多个worker就相当于多个服务器,因此就构成了一个服务器群。master进程则负责创建worker,接收客户端的请求,然后分配到各个服务器上去处理,并且监控worker进程的运行状态及进行管理操作。

    如下图所示:

    回到顶部

    二:node中child_process模块实现多进程

    nodejs 是单进程的,因此无法使用多核cpu,node提供了child_process模块来实现子进程。从而会实现一个广义上的多进程模式,通过child_process模块,可以实现一个主进程,多个子进程模式,主进程叫做master进程,子进程叫做worker(工作)进程,在子进程中不仅可以调用其他node程序,我们还可以调用非node程序及shell命令等。执行完子进程后,我们可以以流或回调形式返回给主进程。

    child_process提供了4个方法,用于创建子进程,这四个方法分别为 spawn, execFile, exec 和 fork. 所有的方法都是异步的。

    该如上4个方法的区别是什么?

    spawn: 子进程中执行的是非node程序,提供一组参数后,执行的结果以流的形式返回。
    execFile: 子进程中执行的是非node程序, 提供一组参数后,执行的结果以回调的形式返回。
    exec: 子进程执行的是非node程序,提供一串shell命令,执行结果后以回调的形式返回,它与 execFile不同的是,exec可以直接执行一串
    shell命令。

    fork: 子进程执行的是node程序,提供一组参数后,执行的结果以流的形式返回,它与spawn不同的是,fork生成的子进程只能执行node应用。

    2.1 execFile 和 exec

    该两个方法的相同点和不同点如下:

    相同点:执行的都是非node应用,且执行的结果以回调函数的形式返回。
    不同点:execFile执行的是一个应用,exec执行的是一段shell命令。

    比如来说:echo是Unix系统的一个自带命令,我们可以直接在命令行中执行如下命令:

    echo hello world

    如下所示:

    如上可以看到,我们在命令行中会打印 hello world. 因此这个我们可以使用 exec 来实现。

    1)通过exec来实现:

    exec执行shell命令代码如下:

    const cp = require('child_process');
    console.log(cp);
    cp.exec('echo hello world', function(err, res) {
      console.log(res);
    });

    执行如下图所示:

    如上我们可以看到,我们的 child_process模块有如下属性:

    复制代码

    { ChildProcess: [Function: ChildProcess],
      fork: [Function: fork],
      _forkChild: [Function: _forkChild],
      exec: [Function: exec],
      execFile: [Function: execFile],
      spawn: [Function: spawn],
      spawnSync: [Function: spawnSync],
      execFileSync: [Function: execFileSync],
      execSync: [Function: execSync] }

    复制代码

    执行如上exec命令后,结果输出为 hello world.

    2) 通过execFile实现

    const cp = require('child_process');
    cp.execFile('echo', ['hello', 'world'], function(err, res) {
      console.log(res);
    });

    如上结果也是为 "hello world".

    2.2 spawn

    spawn是用于执行非node应用的,并且是不能直接执行shell。spawn执行的结果是以流的形式输出的,通过流的方式可以节约内存的。

    2.3 fork

    在node中提供了fork方法,通过使用fork方法在单独的进程中执行node程序,通过使用fork新建worker进程,上下文都复制主进程。并且通过父子之间的通信,子进程接收父进程的信息,并执行子进程后结果信息返回给父进程。降低了大数据运行的压力。

    现在我们来理解下使用fork()方法来创建子进程,fork()方法只需要指定要执行的javascript文件模块,即可创建Node的子进程。下面我们是简单的hello world的demo,master进程根据cpu的数量来创建出相应数量的worker进程,worker进程利用进程ID来标记。

    |------ 项目
    |  |--- master.js
    |  |--- worker.js
    |  |--- package.json
    |  |--- node_modules

    如上是我们的简单项目结构,其中 worker.js 代码如下:

    console.log('Worker-' + process.pid + ': Hello world.');

    master.js 代码如下:

    复制代码

    const childProcess = require('child_process');
    const cpuNum = require('os').cpus().length;
    
    for (let i = 0; i < cpuNum; ++i) {
      childProcess.fork('./worker.js');
    }
    
    console.log('Master: xxxx');

    复制代码

    然后我们进入项目中的根目录,执行 node master.js 命令即可看到打印信息如下:

    如上图可以看到,我们的master创建了4个worker进程后输出 hello world信息。如上就是根据cpu的数量创建了4个工作进程。

    回到顶部

    三:父子进程间如何通信?

    如上创建了4个worker进程后,现在我们需要考虑的是如何实现 master进程与worker进程通信的问题。

    在NodeJS中父子进程之间通信可以通过 on('message') 和 send()方法来实现通信,on('message') 是监听message事件的。
    当该进程收到其他进程发送的消息时候,便会触发message事件。send()方法则是用于向其他进程发送消息的。

    具体如何做呢?

    master进程中可以调用 child_process的fork()方法后会得到一个子进程的实列,通过该实列我们可以监听到来自子进程的消息或向子进程发送消息。而worker进程则通过process对象接口来监听父进程的消息或向父进程发送消息。现在我们把master.js 代码改成如下:

    复制代码

    const childProcess = require('child_process');
    const worker = childProcess.fork('./worker.js');
    
    // 主进程向子进程发送消息
    worker.send('Hello World');
    
    // 监听子进程发送过来的消息
    worker.on('message', (msg) => {
      console.log('Received message from worker:' + msg);
    });

    复制代码

    worker.js 代码如下:

    复制代码

    // 接收主进程发来的消息
    process.on('message', (msg) => {
      console.log('Received message from master:' + msg);
      // 子进程向主进程发送消息
      process.send('Hi master.');
    });

    复制代码

    我们继续在命令中执行 node master.js 命令后,看到如下信息被打印了 

    3.2 Master实现对Worker的请求进行分发

    如上只是简单的父进程和子进程进行通信的demo实列,现在我们继续来看一个更复杂一点的demo。我们知道master进程最主要是创建子进程,及对子进程进行管理和分配,而子进程最主要做的事情是处理具体的请求及业务。

    进程通信除了使用到上面的send()方法,发送一些普通对象以外,我们还可以发送句柄,什么是句柄呢,句柄是一种引用,可以用来标识资源。
    比如通过句柄可以标识一个socket对象等。我们可以利用该句柄实现请求的分发。

    现在我们通过master进程来创建一个TCP服务器来监听一些特定的端口,master进程会收到客户端的请求,我们会得到一个socket对象,通过这个socket对象就可以和客户端进行通信,从而我们可以处理客户端的请求。

    比如如下demo实列,master创建TCP服务器并且监听8989端口,收到该请求后会将请求分发给worker处理,worker收到master发来的socket以后,通过socket对客户端的响应。

    复制代码

    |------ 项目
    |  |--- master.js
    |  |--- worker.js
    |  |--- tcp_client.js
    |  |--- package.json
    |  |--- node_modules

    复制代码

    master.js 代码如下:

    复制代码

    const childProcess = require('child_process');
    const net = require('net');
    
    // 获取cpu的数量
    const cpuNum = require('os').cpus().length;
    
    let workers = [];
    let cur = 0;
    
    for (let i = 0; i < cpuNum; ++i) {
      workers.push(childProcess.fork('./worker.js'));
      console.log('worker process-' + workers[i].pid);
    }
    
    // 创建TCP服务器
    const tcpServer = net.createServer();
    
    /*
     服务器收到请求后分发给工作进程去处理
    */
    tcpServer.on('connection', (socket) => {
      workers[cur].send('socket', socket);
      cur = Number.parseInt((cur + 1) % cpuNum);
    });
    
    tcpServer.listen(8989, () => {
      console.log('Tcp Server: 127.0.0.8989');
    });

    复制代码

    worker.js 代码如下:

    复制代码

    // 接收主进程发来的消息
    process.on('message', (msg, socket) => {
      if (msg === 'socket' && socket) {
        // 利用setTimeout 模拟异步请求
        setTimeout(() => {
          socket.end('Request handled by worker-' + process.pid);
        },100);
      }
    });

    复制代码

    tcp.client.js 代码如下:

    复制代码

    const net = require('net');
    const maxConnectCount = 10;
    
    for (let i = 0; i < maxConnectCount; ++i) {
      net.createConnection({
        port: 8989,
        host: '127.0.0.1'
      }).on('data', (d) => {
        console.log(d.toString());
      })
    }

    复制代码

    如上代码,tcp_client.js 负责创建10个本地请求,master.js 首先根据cpu的数量,创建多个worker进程,然后创建一个tcp服务器,使用connection来监听net中 createConnection 方法创建事件,当有事件来的时候,就使用worker子进程依次进行分发事件,最后我们通过worker.js 来使用 process中message事件对事件进行监听。如果收到消息的话,就打印消息出来,比如如下代码:

    复制代码

    // 接收主进程发来的消息
    process.on('message', (msg, socket) => {
      if (msg === 'socket' && socket) {
        // 利用setTimeout 模拟异步请求
        setTimeout(() => {
          socket.end('Request handled by worker-' + process.pid);
        },100);
      }
    });

    复制代码

    为了查看效果,我们可以在项目的根目录下 运行 命令 node master.js 启动服务器,然后我们打开另一个命令行,执行 node tcp_client.js 启动客户端,然后我们会看到我们的10个请求被分发到不同的服务器上进行处理,如下所示:

    3.3 Worker监听同一个端口

    我们之前已经实现了句柄可以发送普通对象及socket对象外,我们还可以通过句柄的方式发送一个server对象。我们在master进程中创建一个TCP服务器,将服务器对象直接发送给worker进程,让worker进程去监听端口并处理请求。因此master进程和worker进程就会监听了相同的端口了。当我们的客户端发送请求时候,我们的master进程和worker进程都可以监听到,我们知道我们的master进程它是不会处理具体的业务的。
    因此需要使用worker进程去处理具体的事情了。因此请求都会被worker进程处理了。

    那么在这种模式下,主进程和worker进程都可以监听到相同的端口,当网络请求到来的时候,会进行抢占式调度,只有一个worker进程会抢到链接然后进行服务,由于是抢占式调度,可以理解为谁先来谁先处理的模式,因此就不能保证每个worker进程都能负载均衡的问题。下面是一个demo如下:

    master.js 代码如下:

    复制代码

    const childProcess = require('child_process');
    const net = require('net');
    
    // 获取cpu的数量
    const cpuNum = require('os').cpus().length;
    
    let workers = [];
    let cur = 0;
    
    for (let i = 0; i < cpuNum; ++i) {
      workers.push(childProcess.fork('./worker.js'));
      console.log('worker process-' + workers[i].pid);
    }
    
    // 创建TCP服务器
    const tcpServer = net.createServer();
    
    tcpServer.listen(8989, () => {
      console.log('Tcp Server: 127.0.0.8989');
      // 监听端口后将服务器句柄发送给worker进程
      for (let i = 0; i < cpuNum; ++i) {
        workers[i].send('tcpServer', tcpServer);
      }
      // 关闭master线程的端口监听
      tcpServer.close();
    });

    复制代码

    worker.js 代码如下:

    复制代码

    // 接收主进程发来的消息
    process.on('message', (msg, tcpServer) => {
      if (msg === 'tcpServer' && tcpServer) {
        tcpServer.on('connection', (socket) => {
          setTimeout(() => {
            socket.end('Request handled by worker-' + process.pid);
          }, 100);
        })
      }
    });

    复制代码

    tcp_client.js 代码如下:

    复制代码

    const net = require('net');
    const maxConnectCount = 10;
    
    for (let i = 0; i < maxConnectCount; ++i) {
      net.createConnection({
        port: 8989,
        host: '127.0.0.1'
      }).on('data', (d) => {
        console.log(d.toString());
      })
    }

    复制代码

    如上代码,我们运行 node master.js 代码后,运行结果如下所示:

    然后我们进行 运行 node tcp_client.js 命令后,运行结果如下所示:

    如上我们可以看到 进程id为 37660 调度的比较多。

    3.4 实现进程重启

    worker进程可能会因为其他的原因导致异常而退出,为了提高集群的稳定性,我们的master进程需要监听每个worker进程的存活状态,当我们的任何一个worker进程退出之后,master进程能监听到并且能够重启新的子进程。在我们的Node中,子进程退出时候,我们可以在父进程中使用exit事件就能监听到。如果触发了该事件,就可以断定为子进程已经退出了,因此我们就可以在该事件内部做出对应的处理,比如说重启子进程等操作。

    下面是我们上面监听同一个端口模式下的代码demo,但是我们增加了进程重启的功能。进程重启时,我们的master进程需要重新传递tcpServer对象给新的worker进程。但是master进程是不能被关闭的。否则的话,句柄将为空,无法正常传递。

    master.js 代码如下:

    复制代码

    const childProcess = require('child_process');
    const net = require('net');
    
    // 获取cpu的数量
    const cpuNum = require('os').cpus().length;
    
    let workers = [];
    let cur = 0;
    
    for (let i = 0; i < cpuNum; ++i) {
      workers.push(childProcess.fork('./worker.js'));
      console.log('worker process-' + workers[i].pid);
    }
    
    // 创建TCP服务器
    const tcpServer = net.createServer();
    
    /*
     服务器收到请求后分发给工作进程去处理
    */
    tcpServer.on('connection', (socket) => {
      workers[cur].send('socket', socket);
      cur = Number.parseInt((cur + 1) % cpuNum);
    });
    
    tcpServer.listen(8989, () => {
      console.log('Tcp Server: 127.0.0.8989');
      // 监听端口后将服务器句柄发送给worker进程
      for (let i = 0; i < cpuNum; ++i) {
        workers[i].send('tcpServer', tcpServer);
        // 监听工作进程退出事件
        workers[i].on('exit', ((i) => {
          return () => {
            console.log('worker-' + workers[i].pid + ' exited');
            workers[i] = childProcess.fork('./worker.js');
            console.log('Create worker-' + workers[i].pid);
            workers[i].send('tcpServer', tcpServer);
          }
        })(i));
      }
      // 不能关闭master线程的,否则的话,句柄将为空,无法正常传递。
      // tcpServer.close();
    });

    复制代码

    worker.js 代码如下:

    复制代码

    // 接收主进程发来的消息
    process.on('message', (msg, tcpServer) => {
      if (msg === 'tcpServer' && tcpServer) {
        tcpServer.on('connection', (socket) => {
          setTimeout(() => {
            socket.end('Request handled by worker-' + process.pid);
          }, 100);
        })
      }
    });

    复制代码

    tcp_client.js 代码如下:

    复制代码

    const net = require('net');
    const maxConnectCount = 10;
    
    for (let i = 0; i < maxConnectCount; ++i) {
      net.createConnection({
        port: 8989,
        host: '127.0.0.1'
      }).on('data', (d) => {
        console.log(d.toString());
      })
    }

    复制代码

    当我们在命令中 运行 node master.js  和 node tcp_client.js 执行后,如下图所示:

    然后我们进入我们的电脑后台(我这边是mac电脑),进入活动监视器页面,结束某一个进程,如下图所示:

    结束完成后,我们再来看下我们的 node master.js 命令可以看到,先打印 某某工作进程被退出了,然后某某工作进程被创建了,如下图所示

    然后我们再到我们的 活动监视器可以看到新的 进程号被加进来了,如下图所示:

    回到顶部

    四:理解cluster集群

    如上我们了解了使用 child_process实现node集群操作,现在我们来学习使用cluster模块实现多进程服务充分利用我们的cpu资源以外,还能够帮我们更好地进行进程管理。我们使用cluster模块来实现我们上面同样的功能,代码如下:

    master.js 代码如下:

    复制代码

    const cluster = require('cluster');
    if (cluster.isMaster) {
      const cpuNum = require('os').cpus().length;
      for (let i = 0; i < cpuNum; ++i) {
        cluster.fork();
      }
    
      // 创建进程完成后输出信息
      cluster.on('online', (worker) => {
        console.log('Create worker-' + worker.process.pid);
      });
    
      // 监听子进程退出后重启事件
      cluster.on('exit', (worker, code, signal) => {
        console.log('[Master] worker ' + worker.process.pid + ' died with code:' + code + ', and' + signal);
        cluster.fork(); // 重启子进程
      });
    } else {
      const net = require('net');
      net.createServer().on('connection', (socket) => {
        setTimeout(() => {
          socket.end('Request handled by worker-' + process.pid);
        }, 10)
      }).listen(8989)
    }

    复制代码

    如上代码,我们可以使用 cluster.isMaster 来判断是主进程还是子进程,如果是主进程的话,我们使用cluster创建了和cpu数量相同的worker进程,并且通过监听 cluster中的online事件来判断worker是否创建成功。并且使用了 cluster监听了 exit事件,当worker进程退出后,会触发master进程中cluster的online事件来判断worker是否创建成功。如下图我们在命令行中运行命令:

    如下所示:

    我们现在同样的道理,我们去 活动监视器去吧 47575这个端口号结束掉。在看看我们的命令行如下所示:

    从上图我们也可以看到 47575 进程结束掉,并且47898进程重启了。如上代码使用 cluster模块实现了child_process集群的操作。

    有关更多的cluster中的API可以看这篇文章(http://wiki.jikexueyuan.com/project/nodejs/cluster.html)

    我们在下一篇文章会深入学习使用cluster的应用场景demo。 基本原理先到这里。

    展开全文
  • 大家都知道电脑使用的时间过长之后,那么就会出现卡顿或者速度变慢的现象,这时候我们就可以将比较占CPU系统资源较无用进程给关闭。那么多余进程关闭的方法是什么?具体操作方法:方法一:1、电脑进程电脑上...
  • 进程和线程在多核cpu,cpu中的运行关系 cpu架构和工作原理 计算机有5大基本组成部分,运算器,控制器,存储器,输入和输出。运算器和控制器封装到一起,加上寄存器组和cpu内部总线构成中央处理器(CPU)。cpu...
  • 下面,小编给大家介绍电脑结束进程快捷键的步骤。有时我们会遇到程序无响应或者其他别的原因想要结束程序,那么我们这时候就可以结束进程电脑用户,在操作电脑的时候,遇到程序无响应,就一直在哪...
  • IDL多进程批处理遥感数据

    千次阅读 2020-12-29 13:14:14
    文章目录遥感数据处理系列前言一、IDL线程1. 原理简介2. 代码二、文件夹场景1. 二级目录2. 三级目录总结 前言 遥感常用的IDL语言?如何节约数据处理的计算时间?如何跑满CPU充分利用PC算力?那么,一NB的...
  • 有网友问小编电脑上京进程那么,到底哪些是可以关闭的,哪些是不能关闭掉呢?说到这里就了,电脑运行的程序不同,进程也是不同的。当然一般不是系统进程都是可以将其关闭的。特色进程除外。那么电脑中哪些进程...
  • c++多进程编程

    万次阅读 2020-04-16 10:12:52
    c++多进程编程 介绍 进程进程是一正在执行的程序...线程:线程是任务处理的一种特殊形式,任务处理允许让电脑同时运行两或两以上的程序。一般情况下,两种类型的任务处理:基于进程和基于线程。...
  • 线程是什么?要理解这个概念,须要先了解一下操作系统的一些相关概念。大部分操作系统(如...这样每个任务都能得到执行,由于CPU的执行效率非常高,时间片非常短,在各个任务之间快速地切换,给人的感觉就是多个
  • 我们打开任务管理器,就会发现其实一个系统中运行了多个程序,这就给我们造成了一个假象,就是我们电脑可以同时运行很多很多程序,其实不是的。在某一时刻,只有一个程序在运行!我们的电脑运行多个程序,但是他们并...
  • 操作系统(1)-进程与线程

    千次阅读 多人点赞 2019-10-11 20:54:09
    一、进程和线程的定义 ...进程是一具有一定独立功能的程序在一数据集上的一次动态执行的过程,是操作系统进行资源分配和调度的一独立单位,是应用,程序运行的载体。进程是一种抽象的概念,从来...
  • 进程和线程是计算机软件领域里很重要的概念,进程和线程有区别,也有着密切的联系,先来辨析一下这两概念: 1.定义 进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和...
  • C#/.NET 如何结束掉一个进程

    千次阅读 2019-04-28 09:27:39
    本文介绍如何结束掉一个进程。 本文内容结束掉特定名字的进程结束掉自己 结束掉特定名字的进程 ProcessInfo 中有 Kill 实例方法可以调用,也就是说如果我们能够拿到一个进程的信息,并且对这个进程拥有访问权限,...
  • Python多进程线程(跑满CPU)

    万次阅读 多人点赞 2019-05-07 15:06:16
    Python多进程线程(跑满CPU) 概念 任务可以理解为进程(process),如打开一word就是启动一word进程。在一word进程之中不只是进行打字输入,还需要拼写检查、打印等子任务,我们可以把进程中的这些子...
  • 手机后台程序太怎么关闭手机后台程序太怎么关闭 相信有看5月5日晚7点中央电视台新闻联播的朋友会留意到,第一条是题为"消费新动向:指尖的力量"的手机类新闻.新闻中指出,手机及其相关产业带动的消费正在成为成为...
  • Linux多进程编程(典藏、含代码)

    千次阅读 多人点赞 2020-02-03 21:44:40
    1.2、多进程(任务)并行的实现 1.3、重要指令 1.4、父子进程进程ID 二、多进程编程 2.1创建子进程 (fork/vfork 叉子) 2.1.1 fork 2.1.2vfork 2.2进程结束 2.2.1正常退出 2.2.2异常退出 2.3等待进程结束并...
  • Firefox关闭多进程或减少进程

    万次阅读 2017-11-21 13:03:54
    最近,Firefox升级到57版本后,就由单进程变成了进程... 通过实践,操作如下,可缩小到2个进程,不能再缩小到一个进程(不知哪位知道怎么做?),但据官方资料,应该是一个UI渲染进程,一个内容进程。可避免当单个
  • [904]python多进程之间共享数据

    千次阅读 2020-10-23 18:49:01
    另外一种称之为server process , 即有一服务器进程负责维护所有的对象,而其他进程连接到该进程,通过代理对象操作服务器进程当中的对象; 最后一种在mp文档当中没有单独提出,但是在其 中次提到,而且是mp库...
  • Python的多进程并行计算库与多进程爬虫

    万次阅读 多人点赞 2021-07-14 00:13:40
    前面在《单线程、多线程和协程的爬虫性能对比》一文中已经介绍过,...比如你的电脑是 6 核处理器,那么同时开 6 个进程执行程序就可以加快运行速度。 适用场景: 并发通常应用于 I/O 操作频繁的场景,比如下载多个
  • 在windows环境下的IDE/Pycharm,无法运行多进程的问题 解决: 在CMD下运行既可. 原因: 待解决 cookies: 两方法一起进行的办法: def test(): pritn("1") def test2(): print("2") if __name__...
  • Python 爬虫提速:【多进程线程、协程+异步】对比测试概念介绍测试环境开始测试测试【单线程单进程】测试【多进程 并行】测试【线程 并发】测试【协程 + 异步】结果对比 Python 爬虫提速:【多进程线程、...
  • python多进程并行的简单实现

    千次阅读 2019-10-29 22:37:43
      这两天在跑一个文件处理程序的时候想着利用多核并行处理实现节省时间,然后例程里用了...这样的结果就是即使利用了多线程,多个线程仍旧是在单核上执行的,执行某一个线程的时候,余下的所有线程都吃瓜。 ...
  • python分布式多进程框架 Ray

    万次阅读 多人点赞 2019-03-13 19:49:27
    我们需要利用多个核心或多台机器来加速应用程序或大规模运行它们。网络爬虫和搜索所使用的基础设施并不是在某人笔记本电脑上运行的单线程程序,而是相互通信和交互的服务的集合。 ray的api接口教程:...
  • 【Linux系统编程】进程概述和进程

    千次阅读 2019-11-03 21:31:48
    我们平时写的 C 语言代码,通过编译器编译,最终它会成为一个可执行程序,当这个可执行程序运行起来后(没有结束之前),它就成为了一个进程。 程序是存放在存储介质上的一个可执行文件,而进程是程序执行的过程。...
  • 10.线程,多进程

    千次阅读 2018-07-23 16:22:37
    线程 线程锁 ThreadLocal 1.系统差异 在Linux和Unix系统上,os模块有fork调用方式来创建子进程,在windows上可用multiprocessing模块来操作进程。 fork方式: import os print('Process (%s...
  • Linux进程概念

    千次阅读 多人点赞 2022-03-03 08:54:33
    Linux进程概念零、前言一、冯诺依曼体系结构二、操作系统三、进程1、描述进程-PCB2、查看进程3、获取进程标示符4、创建进程-fork()5、进程状态6、僵尸进程7、孤儿进程8、进程优先级9、环境变量1)测试PATH2)测试HOME3...
  • 个进程在其执行的过程中可以产生多个线程。与进程不同的是同类的多个线程共享同一块内存空间和一组系统资源,所以系统在产生一个线程,或是在各个线程之间作切换工作时,负担要比进程小得多,也正因为如此,线程也...
  • Python使用multiprocessing实现多进程

    万次阅读 多人点赞 2019-06-05 22:14:11
    Python使用multiprocessing实现多进程 进程是操作系统进行资源分配和调度的一基本单位。 一、进程任务介绍 程序:程序是一静态的概念。在一台电脑上,我们安装了很程序,这些程序是可以运行的。比如...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 107,530
精华内容 43,012
关键字:

如何让电脑处理多个进程