Node.js的进程管理的深入理解(4)

下面我们通过curl连续请求 5 次服务。

for varible1 in {1..5}
do
 curl "localhost:3000"
done

可以看到,响应请求的可以是父进程,也可以是不同子进程,多个进程对同一个服务响应的连接事件监听,谁先抢占,就由谁进行响应。这里就会出现一个Linux网络编程中很常见的事件,当多个进程同时监听网络的连接事件,当这个有新的连接到达时,这些进程被同时唤醒,这被称为“惊群”。这样导致的情况就是,一旦事件到达,每个进程同时去响应这一个事件,而最终只有一个进程能处理事件成功,其他的进程在处理该事件失败后重新休眠,造成了系统资源的浪费。

ps:在windows系统上,永远都是最后定义的子进程抢占到句柄,这可能和libuv的实现机制有关,具体原因往有大佬能够指点。

出现这样的问题肯定是大家都不愿意的嘛,这个时候我们就想起了nginx的好了,这里有篇文章讲解了nginx是如何解决“惊群”的,利用nginx的反向代理可以有效地解决这个问题,毕竟nginx本来就很擅长这种问题。

http { 
 upstream node { 
   server 127.0.0.1:8000; 
   server 127.0.0.1:8001; 
   server 127.0.0.1:8002; 
   server 127.0.0.1:8003;
   keepalive 64;
 } 
 server { 
    listen 80; 
    server_name shenfq.com; 
    location / { 
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header Host $http_host;
      proxy_set_header X-Nginx-Proxy true;
      proxy_set_header Connection "";
      proxy_pass http://node; # 这里要和最上面upstream后的应用名一致,可以自定义
    } 
 }
}

小结

如果我们自己用Node原生来实现一个多进程模型,存在这样或者那样的问题,虽然最终我们借助了nginx达到了这个目的,但是使用nginx的话,我们需要另外维护一套nginx的配置,而且如果有一个Node服务挂了,nginx并不知道,还是会将请求转发到那个端口。

cluster模块

除了用nginx做反向代理,node本身也提供了一个cluster模块,用于多核CPU环境下多进程的负载均衡。cluster模块创建子进程本质上是通过child_procee.fork,利用该模块可以很容易的创建共享同一端口的子进程服务器。