Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

单机上搭建Node集群 #175

Open
wuxianqiang opened this issue Jun 26, 2019 · 0 comments
Open

单机上搭建Node集群 #175

wuxianqiang opened this issue Jun 26, 2019 · 0 comments

Comments

@wuxianqiang
Copy link
Owner

wuxianqiang commented Jun 26, 2019

配置Node集群需要复制进程,而且通过主从模式并行处理业务。主进程不负责具体的业务处理,而是负责调度或管理工作进程,它是趋向于稳定的。工作进程负责具体的业务处理。

关于本 Node 进程的介绍请看Node.js 中文网

复制进程

child_process.fork() 方法是专门用于衍生新的 Node.js 进程。

重要的是要记住,衍生的 Node.js 子进程独立于父进程,但两者之间建立的 IPC 通信通道除外。 每个进程都有自己的内存,带有自己的 V8 实例。 由于需要额外的资源分配,因此不建议衍生大量的 Node.js 子进程。

// master.js 文件
const fork = require('child_process').fork;
const cpus = require('os').cpus();
const net = require('net')

const list = []
for (let i = 0; i < cpus.length; i++) {
  const child = fork('./worker.js')
  list.push(child)
}

const server = net.createServer()

server.listen(8080, () => {
  list.forEach(child => {
    child.send('server', server)
  })
  server.close()
})

如果Node.js进程是通过进程间通信产生的,那么,process.send() 方法可以用来给父进程发送消息。 接收到的消息被视为父进程的 ChildProcess 对象上的一个 'message' 事件。

// worker.js 文件
const http = require('http')
const process = require('process')

const server = http.createServer(
  (req, res) => {
    res.writeHead(200, {
      'Content-Type': 'text/plain',
    })
    res.end(`handle by child ${process.pid}`)
  }
)


process.on('message', (m, tcp) => {
  if (m === 'server') {
    // 建立新的 TCP 流时会触发此事件
    tcp.on('connection', socket => {
      // 让工作进程去处理连接请求
      server.emit('connection', socket)
    })
  }
})

'connection' 事件,建立新的 TCP 流时会触发此事件。用户也可以显式触发此事件,以将连接注入 HTTP 服务器。

通过 node master 启动主进程文件,主进程发送完句柄并关闭监听。多个子进程可以同时监听相同
端口。这个服务器端套接字可以被不同的进程复用。

我们独立启动的进程中,TCP 服务器端socket套接字的文件描述符并不相同,导致监听到相同的端口时会抛出异常。

由于独立启动的进程互相之间并不知道文件描述符,所以监听相同端口时就会失败。但对于 send() 发送的句柄还原出来的服务而言,它们的文件描述符是相同的,所以监听相同端口不会引起异常。

多个应用监听相同端口时,文件描述符同一时间只能被某个进程所用。换言之就是网络请求向服务器端发送时,只有一个幸运的进程能够抢到连接,也就是说只有它能为这个请求进行服务。这些进程服务是抢占式的。

句柄

句柄是一种可以用来标识资源的引用,它的内部包含了指向对象的文件描述符。

套接字

TCP用主机的IP地址加上主机上的端口号作为TCP连接的端点,这种端点就叫做套接字(socket)或插口。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant