>  기사  >  웹 프론트엔드  >  노드 다중 프로세스 모델 및 프로젝트 배포에 대해 이야기하는 기사

노드 다중 프로세스 모델 및 프로젝트 배포에 대해 이야기하는 기사

青灯夜游
青灯夜游원래의
2022-12-23 19:10:192274검색

node다중 프로세스를 구현하는 방법은 무엇입니까? 노드 프로젝트를 배포하는 방법은 무엇입니까? 다음 기사는 Node.js 다중 프로세스 모델 및 프로젝트 배포에 대한 관련 지식을 습득하는 데 도움이 될 것입니다.

노드 다중 프로세스 모델 및 프로젝트 배포에 대해 이야기하는 기사

어제 친구가 Express 프로젝트 배포 방법을 물었습니다. 그래서 도움이 필요한 친구들을 위해 nodejs를 기반으로 개발된 서버 프로그램을 배포하는 방법을 주로 다룬 이 글을 정리했습니다.

이 기사에는 여러 부분이 포함되어 있습니다.

  • 스레드 및 프로세스
  • 다중 프로세스 구현을 위한 node.js
  • 서버 설치 Node.js 환경
  • PM2를 사용하여 Node.js 프로젝트 관리
  • Nginx를 사용하여 프록시 전달 구현 인터페이스 서비스

Process VS Thread

Process

프로세스는 컴퓨터 운영체제에서 작업을 할당하고 예약하는 기본 단위입니다. 작업 관리자를 열면 컴퓨터 백그라운드에서 실제로 많은 프로그램이 실행되고 있으며 각 프로그램이 하나의 프로세스임을 알 수 있습니다. [관련 튜토리얼 추천: nodejs 비디오 튜토리얼, 프로그래밍 교육]

노드 다중 프로세스 모델 및 프로젝트 배포에 대해 이야기하는 기사

최신 브라우저는 기본적으로 다중 프로세스 아키텍처입니다. Chrome 브라우저를 예로 들어 "추가 도구" - "작업 관리자"를 엽니다. 현재 브라우저의 프로세스 정보를 볼 수 있습니다. 그 외에도 네트워크 프로세스, GPU 프로세스 등이 있습니다.

노드 다중 프로세스 모델 및 프로젝트 배포에 대해 이야기하는 기사

다중 프로세스 아키텍처는 애플리케이션의 보다 안정적인 작동을 보장합니다. 브라우저를 예로 들면, 모든 프로그램이 하나의 프로세스에서 실행되는 경우, 네트워크 오류나 페이지 렌더링 오류가 발생하면 전체 브라우저가 중단될 수 있습니다. 다중 프로세스 아키텍처를 통해 네트워크 프로세스가 충돌하더라도 기존 페이지 표시에는 영향을 미치지 않으며 최악의 경우 일시적으로 네트워크에 액세스할 수 없습니다.

Thread

스레드는 운영 체제가 계산 스케줄링을 수행할 수 있는 가장 작은 단위입니다. 프로세스에 포함되며 프로세스에서 실제 작동하는 단위입니다. 예를 들어, 프로그램은 여러 프로세스로 구성된 여러 부서가 있는 회사와 같습니다. 각 부서의 협력을 통해 회사가 정상적으로 운영될 수 있으며 스레드는 특정 작업을 수행하는 직원입니다.

우리 모두는 JavaScript가 단일 스레드 언어라는 것을 알고 있습니다. 이런 디자인은 초기에는 JS가 주로 스크립트 작성에 사용되었고, 페이지의 인터랙티브 효과를 구현하는 역할을 담당했기 때문입니다. 멀티 스레드 언어로 설계하면 첫째로 필요하지 않고 둘째로 여러 스레드가 공동으로 DOM 노드를 운영한다면 브라우저는 누구의 조언을 들어야 할까요? 물론 기술의 발전으로 JS는 이제 멀티스레딩도 지원하지만 DOM 작업과 관련 없는 일부 로직을 처리하는 데에만 사용됩니다.

단일 프로세스의 문제

단일 스레드와 단일 프로세스는 심각한 문제를 가져옵니다. 실행 중인 node.js 프로그램의 메인 스레드가 중단되면 프로세스도 중단되고 전체 애플리케이션도 중단됩니다. 게다가 대부분의 최신 컴퓨터에는 4개의 코어와 8개의 스레드, 8개의 코어와 16개의 스레드가 있는 멀티 코어 CPU가 있으며 이는 매우 일반적인 장치입니다. 단일 프로세스 프로그램인 node.js는 멀티 코어 CPU의 성능을 낭비합니다.

이러한 상황을 고려하여 단일 프로세스 node.js 프로그램을 다중 프로세스 아키텍처로 변환하려면 적합한 다중 프로세스 모델이 필요합니다.

Node.js의 다중 프로세스 구현

Node.js에는 다중 프로세스 아키텍처를 구현하기 위한 두 가지 공통 솔루션이 있습니다. 둘 다 기본 모듈, 즉 child_process 모듈과 cluster 모듈. <code>child_process 模块和 cluster 模块。

child_process

child_process 是 node.js 的内置模块,看名字也能猜到它负责的是和子进程有关的事。

我们不再细说该模块的具体用法,实际上它大概只有六七个方法,还是非常容易理解的。我们使用其中的一个 fork 方法来演示如何实现多进程以及多进程之间的通信。

先看下准备好的演示案例的目录结构:

노드 다중 프로세스 모델 및 프로젝트 배포에 대해 이야기하는 기사

我们使用 http 模块创建了一个 http server,当有 /sum 请求进来时,会通过 child_process

child_process🎜child_process는 node.js에 내장된 모듈입니다. 이름에서 자식과 관련된 일을 담당한다는 것을 짐작할 수 있습니다. 프로세스. 🎜🎜이 모듈의 구체적인 사용법에 대해서는 자세히 설명하지 않겠습니다. 실제로는 6~7가지 메서드만 있으므로 여전히 이해하기 쉽습니다. fork 방법 중 하나를 사용하여 여러 프로세스와 여러 프로세스 간의 통신을 구현하는 방법을 보여줍니다. 🎜🎜먼저 준비된 데모 케이스의 디렉토리 구조를 살펴보세요: 🎜🎜 노드 다중 프로세스 모델 및 프로젝트 배포에 대해 이야기하는 기사🎜🎜 /sum이 있을 때 <code>http 모듈을 사용하여 http 서버를 생성합니다. 요청이 들어오면 child_process 모듈을 통해 하위 프로세스가 생성되고, 하위 프로세스에 계산 로직을 실행하라는 알림이 전달됩니다. 자식 프로세스가 보낸 메시지를 들어보세요: 🎜
// child_process.jsconst http = require('http')const { fork } = require('child_process')const server = http.createServer((req, res) => {
  if (req.url == '/sum') {
    // fork 方法接收一个模块路径,然后开启一个子进程,将模块在子进程中运行
    // childProcess 表示创建的子进程
    let childProcess = fork('./sum.js')

    // 发消息给子进程
    childProcess.send('子进程开始计算')

    // 父进程中监听子进程的消息
    childProcess.on('message', (data) => {
      res.end(data + '')
    })

    // 监听子进程的关闭事件
    childProcess.on('close', () => {
      // 子进程正常退出和报错挂掉,都会走到这里
      console.log('子进程关闭')
      childProcess.kill()
    })

    // 监听子进程的错误事件
    childProcess.on('error', () => {
      console.log('子进程报错')
      childProcess.kill()
    })
  }
    
  if (req.url == '/hello') {
    res.end('hello')
  }
  
  // 模拟父进程报错
  if (req.url == '/error') {
     throw new Error('父进程出错')
     res.end('hello')
   }
})

server.listen(3000, () => {
  console.log('Server is running on 3000')
})复制代码

sum.js는 하위 프로세스에서 수행할 작업을 시뮬레이션하는 데 사용됩니다. 하위 프로세스는 상위 프로세스에서 보낸 메시지를 수신하고 계산 작업을 처리한 다음 결과를 상위 프로세스로 보냅니다. sum.js 用来模拟子进程要执行的任务。子进程监听父进程发来的消息,处理计算任务,然后将结果发送给父进程:

// sum.jsfunction getSum() {
  let sum = 0
  for (let i = 0; i  {
  console.log('主进程的消息:', data)
    
  const result = getSum()
  // 将计算结果发送给父进程
  process.send(result)
})复制代码

打开终端,运行命令 node 1.child_process

노드 다중 프로세스 모델 및 프로젝트 배포에 대해 이야기하는 기사

访问浏览器:

노드 다중 프로세스 모델 및 프로젝트 배포에 대해 이야기하는 기사

接着来模拟子进程报错的情况:

// sum.jsfunction getSum() {
  // ....}// 子进程运行5s后,模拟进程挂掉
 setTimeout(() => {
   throw new Error('报错')
 }, 1000 * 5)

process.on('message', (data) => {
  // ...})复制代码

再次访问浏览器,5秒之后观察控制台:

노드 다중 프로세스 모델 및 프로젝트 배포에 대해 이야기하는 기사

子进程已经挂掉了,然后再访问另一个 url :/hello

노드 다중 프로세스 모델 및 프로젝트 배포에 대해 이야기하는 기사

可见,父进程依然能正确处理请求,说明子进程报错,并不会影响父进程的运行

接着我们来模拟父进程报错的场景,注释掉 sum.js 模块的模拟报错,然后重启服务,浏览器访问 /error

노드 다중 프로세스 모델 및 프로젝트 배포에 대해 이야기하는 기사

发现父进程挂掉后,整个 node.js 程序自动退出了,服务完全崩溃,没有挽回的余地。

可见,通过 child_processfork 方法实现 node.js 的多进程架构并不复杂。进程间的通信主要通过 sendon 方法,从这个命名上也能知道,其底层应该是一个发布订阅模式。

但是它存在一个严重的问题,虽然子进程不影响父进程,但是一旦父进程出错挂掉,所有的子进程会被”一锅端掉“ 。所以,这种方案适用于将一些复杂耗时的运算,fork 出一个单独的子进程去做。更准确的来说,这种用法是用来代替多线程的实现,而非多进程。

cluster

使用 child_process 模块实现多进程,貌似不堪大用。所以一般更推荐使用 cluster 模块来实现 node.js 的多进程模型。

cluster,集群的意思,这个名词相信大家都不陌生。打个比方,以前公司只有一个前台,有时候太忙就没办法及时接待访客。现在公司分配了4个前台,即使有三个都在忙,也还有一个能接待新来的访客。集群大致也就是这个意思,对于同一件事,合理的分配给不同的人去干,以此来保证这件事能做到最好。

cluster 模块的使用也比较简单。如果当前进程是主进程,则根据 CPU 的核数创建合适数量的子进程,同时监听子进程的 exit 事件,有子进程退出,就重新 fork 新的子进程。如果不是子进程,则进行实际业务的处理。

const http = require('http')const cluster = require('cluster')const cpus = require('os').cpus()if (cluster.isMaster) {
  // 程序启动时首先走到这里,根据 CPU 的核数,创建出多个子进程
  for (let i = 0; i  {
    cluster.fork()
  })
} else {
  // fork 方法执行创建子进程,同时会再次执行该模块,此时逻辑就会走到这里
  const server = http.createServer((req, res) => {
    console.log(process.pid)
    res.end('ok')
  })

  server.listen(3000, () => {
    console.log('Server is running on 3000', 'pid: ' + process.pid)
  })
}复制代码

启动服务:

노드 다중 프로세스 모델 및 프로젝트 배포에 대해 이야기하는 기사

可以看到,cluster 模块创建出了非常多的子进程,好像是每个子进程都运行着同一个web服务。

需要注意的是,此时并非是这些子进程共同监听同一个端口。端口的监听依然是由 createServer 方法创建的 server 去负责,将请求转发给各个子进程。

我们编写一个请求脚本,来请求上面的服务,看下效果。

// request.jsconst http = require('http')for (let i = 0; i <blockquote><p>http 模块不仅可以创建 http server,还能用来发送 http 请求。Axios支持浏览器和服务器环境,在服务器端就是使用 http 模块发送 http 请求。</p></blockquote><p>使用 <code>node</code> 命令执行该文件,再看下原来的控制台:</p><p style="text-align:center;"><img src="https://img.php.cn/upload/article/000/000/024/6acfb36f7a6b8401b888460a3a451efa-9.png" alt="노드 다중 프로세스 모델 및 프로젝트 배포에 대해 이야기하는 기사"    style="max-width:90%" loading="lazy"></p><p>打印出了具体处理请求的不同子进程的进程ID。</p><p>这就是通过 <code>cluster</code></p><pre class="brush:php;toolbar:false">const express = require('express')const Mock = require('mockjs')const app = express()

app.get("/api/users", (req, res) => {
  const userList = Mock.mock({
    'userList|10': [{
      'id|+1': 1,
      'name': '@cname',
      'email': '@email'
    }]
  })
  
  setTimeout(()=> {
      throw new Error('服务器故障')
  }, 5000)

  res.status(200)
  res.json(userList)
})

app.listen(3000, () => {
  console.log("服务启动: 3000")
})复制代码
터미널을 열고 node 1.child_process 명령을 실행합니다. 🎜

Snipaste_2022- 07-28_22-52-55.png🎜🎜브라우저 방문: 🎜

노드 다중 프로세스 모델 및 프로젝트 배포에 대해 이야기하는 기사🎜🎜다음으로 아이가 프로세스에서 오류 보고: 🎜

node server.js复制代码
🎜브라우저를 다시 방문하고 5초 후에 콘솔을 관찰하세요. 🎜

노드 다중 프로세스 모델 및 프로젝트 배포에 대해 이야기하는 기사🎜🎜하위 프로세스가 종료된 후 다른 URL에 액세스합니다. : /hello , 🎜

Snipaste_2022 -07-28_22-58-00.png🎜🎜부모 프로세스가 여전히 요청을 올바르게 처리할 수 있음을 알 수 있습니다. 이는 하위 프로세스에서 보고된 오류는 상위 프로세스의 작동에 영향을 미치지 않습니다. 🎜🎜그런 다음 상위 프로세스의 오류 시나리오를 시뮬레이션하고 sum.js 모듈의 시뮬레이션된 오류를 주석 처리한 다음 서비스를 다시 시작하고 브라우저: 🎜🎜노드 다중 프로세스 모델 및 프로젝트 배포에 대해 이야기하는 기사🎜🎜상위 프로세스가 중단된 후 전체 node.js 프로그램이 자동으로 종료되고 서비스가 완전히 붕괴되어 복구할 여지가 없는 것으로 나타났습니다. 🎜🎜child_processfork 메소드를 통해 node.js의 다중 프로세스 아키텍처를 구현하는 것이 복잡하지 않다는 것을 알 수 있습니다. 프로세스 간 통신은 주로 sendon 메서드를 통해 이루어집니다. 이 이름을 통해 맨 아래 레이어가 게시-구독 모델이어야 한다는 것도 알 수 있습니다. 🎜🎜하지만 심각한 문제가 있습니다. 비록 하위 프로세스가 상위 프로세스에 영향을 미치지 않더라도 상위 프로세스가 오류를 범하고 전화가 끊기면 모든 하위 프로세스가 "한 번에 종료"됩니다. . 따라서 이 솔루션은 일부 복잡하고 시간이 많이 걸리는 작업을 별도의 하위 프로세스로 분기하는 데 적합합니다. 더 정확하게 말하면, 이 사용법은 멀티 프로세싱이 아닌 멀티 스레딩 구현을 대체하는 데 사용됩니다. 🎜

클러스터

🎜child_process 모듈을 사용하여 여러 프로세스를 구현하는데 이는 쓸모없어 보입니다. 따라서 일반적으로 node.js의 다중 프로세스 모델을 구현하려면 cluster 모듈을 사용하는 것이 좋습니다. 🎜🎜cluster는 클러스터를 의미합니다. 이 용어는 모두가 익숙할 것입니다. 예를 들어, 과거에는 회사에 프런트 데스크가 하나뿐이었고 때로는 너무 바빠서 시간에 맞춰 방문객을 맞이할 수 없는 경우도 있었습니다. 이제 회사는 4개의 프런트 데스크를 할당했습니다. 3명이 바쁘더라도 새로운 방문객을 받을 수 있는 프런트 데스크는 여전히 있습니다. 클러스터링은 대략적으로 이것을 의미합니다. 동일한 일을 가장 잘 수행할 수 있도록 여러 사람에게 합리적으로 할당하는 것입니다. 🎜🎜cluster 모듈은 사용하기도 비교적 간단합니다. 현재 프로세스가 메인 프로세스인 경우 CPU 코어 수에 따라 적절한 수의 하위 프로세스를 생성하고, 하위 프로세스가 종료되면 하위 프로세스의 exit 이벤트를 수신합니다. , 새 하위 프로세스를 다시 포크합니다. 하위 프로세스가 아닌 경우 실제 비즈니스가 처리됩니다. 🎜
# curl -o- https://gitee.com/hsyq/nvm/raw/master/install.sh | bash复制代码
🎜서비스 시작: 🎜

노드 다중 프로세스 모델 및 프로젝트 배포에 대해 이야기하는 기사🎜🎜cluster 모듈이 많은 자식을 생성한 것을 볼 수 있습니다 프로세스의 경우 각 하위 프로세스가 동일한 웹 서비스를 실행하는 것 같습니다. 🎜🎜현재 이러한 하위 프로세스는 동일한 포트를 수신하지 않습니다. createServer 메소드로 생성된 서버는 여전히 포트 모니터링을 담당하고 각 하위 프로세스에 요청을 전달합니다. 🎜🎜위의 서비스를 요청하고 효과를 확인하기 위해 요청 스크립트를 작성합니다. 🎜

[root@ecs-221238 ~]# nvm -v0.39.1复制代码
🎜http 모듈은 http 서버를 생성할 수 있을 뿐만 아니라 http 요청을 보내는 데에도 사용할 수 있습니다. Axios는 브라우저 및 서버 환경을 지원합니다. 서버 측에서는 http 요청을 보내는 데 http 모듈이 사용됩니다. 🎜
🎜node 명령을 사용하여 파일을 실행하고 원본 콘솔을 확인하세요. 🎜

노드 다중 프로세스 모델 및 프로젝트 배포에 대해 이야기하는 기사🎜🎜요청을 구체적으로 처리하는 다양한 하위 프로세스의 프로세스 ID를 인쇄하세요. 🎜🎜cluster 모듈을 통해 구현된 nodd.js의 다중 프로세스 아키텍처입니다. 🎜

当然,我们在部署 node.js 项目时不会这么干巴巴的写和使用 cluster 模块。有一个非常好用的工具,叫做 PM2,它是一个基于 cluster 模块实现的进程管理工具。在后面的章节中会介绍它的基本用法。

小结

到此为止,我们花了一部分篇幅介绍 node.js 中多进程的知识,其实仅是想要交代下为什么需要使用 pm2 来管理 node.js 应用。本文由于篇幅有限,再加上描述不够准确/详尽,仅做简单介绍。如果是第一次接触这一块内容的朋友,可能没有太明白,也不打紧,后面会再出一篇更细节的文章。

部署实践

准备一个 express 项目

本文已经准备了一个使用 express 开发的示例程序,点此访问

它主要实现了一个接口服务,当访问 /api/users 时,使用 mockjs 模拟了10条用户数据,返回一个用户列表。同时会开启一个定时器,来模拟报错的情况:

const express = require('express')const Mock = require('mockjs')const app = express()

app.get("/api/users", (req, res) => {
  const userList = Mock.mock({
    'userList|10': [{
      'id|+1': 1,
      'name': '@cname',
      'email': '@email'
    }]
  })
  
  setTimeout(()=> {
      throw new Error('服务器故障')
  }, 5000)

  res.status(200)
  res.json(userList)
})

app.listen(3000, () => {
  console.log("服务启动: 3000")
})复制代码

本地测试一下,在终端中执行命令:

node server.js复制代码

打开浏览器,访问用户列表接口:

노드 다중 프로세스 모델 및 프로젝트 배포에 대해 이야기하는 기사

五秒钟后,服务器会挂掉:

노드 다중 프로세스 모델 및 프로젝트 배포에 대해 이야기하는 기사

后面我们使用 pm2 来管理应用后,就可以解决这个问题。

讨论:express 项目是否需要打包

通常完成一个 vue/react 项目后,我们都会先执行打包,再进行发布。其实前端项目要进行打包,主要是因为程序最终的运行环境是浏览器,而浏览器存在各种兼容性问题和性能问题,比如:

  • 高级语法的不支持,需要将 ES6+ 编译为 ES5 语法
  • 不能识别 .vue.jsx.ts 文件,需要编译
  • 减少代码体积,节省带宽资源,提高资源加载速度
  • ......

而使用 express.js 或者 koa.js 开发的项目,并不存在这些问题。并且,Node.js 采用 CommonJS 模块化规范,有缓存的机制;同时,只有当模块在被用到时,才会被导入。如果进行打包,打包成一个文件,其实就浪费了这个优势。所以针对 node.js 项目,并不需要打包。

服务器安装 Node.js

本文以 CentOS 系统为例进行演示。

NVM

为了方便切换 node 的版本,我们使用 nvm 来管理 node。

Nvm(Node Version Manager) ,就是 Node.js 的版本管理工具。通过它,可以让 node 在多个版本之间进行任意切换,避免了需要切换版本时反复的下载和安装的操作。

Nvm的官方仓库是 github.com/nvm-sh/nvm。因为它的安装脚本存放在 githubusercontent 站点上,经常访问不了。所以我在 gitee 上新建了它的镜像仓库,这样就能从 gitee 上访问到它的安装脚本了。

通过 curl 命令下载安装脚本,并使用 bash 执行脚本,会自动完成 nvm 的安装工作:

# curl -o- https://gitee.com/hsyq/nvm/raw/master/install.sh | bash复制代码

当安装完成之后,我们再打开一个新的窗口,来使用 nvm :

[root@ecs-221238 ~]# nvm -v0.39.1复制代码

可以正常打印版本号,说明 nvm 已经安装成功了。

安装 Node.js

现在就可以使用 nvm 来安装和管理 node 了。

查看可用的 node 版本:

# nvm ls-remote复制代码

安装 node:

# nvm install 18.0.0复制代码

查看已经安装的 node 版本:

[root@ecs-221238 ~]# nvm list->      v18.0.0default -> 18.0.0 (-> v18.0.0)
iojs -> N/A (default)
unstable -> N/A (default)
node -> stable (-> v18.0.0) (default)
stable -> 18.0 (-> v18.0.0) (default)复制代码

选择一个版本进行使用:

# nvm use 18.0.0复制代码

需要注意的一点,在 Windows 上使用 nvm 时,需要使用管理员权限执行 nvm 命令。在 CentOS 上,我默认使用 root 用户登录的,因而没有出现问题。大家在使用时遇到了未知错误,可以搜索一下解决方案,或者尝试下是否是权限导致的问题。

在安装 node 的时候,会自动安装 npm。查看 node 和 npm 的版本号:

[root@ecs-221238 ~]# node -vv18.0.0[root@ecs-221238 ~]# npm -v8.6.0复制代码

默认的 npm 镜像源是官方地址:

[root@ecs-221238 ~]# npm config get registryhttps://registry.npmjs.org/复制代码

切换为国内淘宝的镜像源:

[root@ecs-221238 ~]# npm config set registry https://registry.npmmirror.com复制代码

到此为止,服务器就已经安装好 node 环境和配置好 npm 了。

项目上传到服务器

方法有很多,或者从 Github / GitLab / Gitee 仓库中下载到服务器中,或者本地通过 ftp 工具上传。步骤很简单,不再演示。

演示项目放到了 /www 目录 下:

노드 다중 프로세스 모델 및 프로젝트 배포에 대해 이야기하는 기사

服务器开放端口

一般云服务器仅开放了 22 端口用于远程登录。而常用的80,443等端口并未开放。另外,我们准备好的 express 项目运行在3000端口上。所以需要先到云服务器的控制台中,找到安全组,添加几条规则,开放80和3000端口。

노드 다중 프로세스 모델 및 프로젝트 배포에 대해 이야기하는 기사

노드 다중 프로세스 모델 및 프로젝트 배포에 대해 이야기하는 기사

使用 PM2 管理应用

在开发阶段,我们可以使用 nodemon 来做实时监听和自动重启,提高开发效率。在生产环境,就需要祭出大杀器—PM2了。

基本使用

首先全局安装 pm2:

# npm i -g pm2复制代码

执行 pm2 -v 命令查看是否安装成功:

[root@ecs-221238 ~]# pm2 -v5.2.0复制代码

切换到项目目录,先把依赖装上:

cd /www/express-demo
npm install复制代码

然后使用 pm2 命令来启动应用。

pm2 start app.js -i max// 或者pm2 start server.js -i 2复制代码

PM2 管理应用有 fork 和 cluster 两种模式。在启动应用时,通过使用 -i 参数来指定实例的个数,会自动开启 cluster 模式。此时就具备了负载均衡的能力。

-i :instance,实例的个数。可以写具体的数字,也可以配置成 max,PM2会自动检查可用的CPU的数量,然后尽可能多地启动进程。

노드 다중 프로세스 모델 및 프로젝트 배포에 대해 이야기하는 기사

此时应用就启动好了。PM2 会以守护进程的形式管理应用,这个表格展示了应用运行的一些信息,比如运行状态,CPU使用率,内存使用率等。

在本地的浏览器中访问接口:

노드 다중 프로세스 모델 및 프로젝트 배포에 대해 이야기하는 기사

Cluster 模式是一个多进程多实例的模型,请求进来后会分配给其中一个进程处理。正如前面我们看过的 cluster 模块的用法一样,由于 pm2 的守护,即使某个进程挂掉了,也会立刻重启该进程。

回到服务器终端,执行 pm2 logs 命令,查看下 pm2 的日志:

노드 다중 프로세스 모델 및 프로젝트 배포에 대해 이야기하는 기사

可见,id 为1的应用实例挂掉了,pm2 会立刻重启该实例。注意,这里的 id 是应用实例的 id,并非进程 id。

到这里,一个 express 项目的简单部署就完成了。通过使用 pm2 工具,基本能保证我们的项目可以稳定可靠的运行。

PM2 常用命令小结

这里整理了一些 pm2 工具常用的命令,可供查询参考。

# Fork模式pm2 start app.js --name app # 设定应用的名字为 app# Cluster模式# 使用负载均衡启动4个进程pm2 start app.js -i 4     

# 将使用负载均衡启动4个进程,具体取决于可用的 CPUpm2 start app.js -i 0   

# 等同于上面命令的作用pm2 start app.js -i max 

 # 给 app 扩展额外的3个进程pm2 scale app +3# 将 app 扩展或者收缩到2个进程pm2 scale app 2              # 查看应用状态# 展示所有进程的状态pm2 list  # 用原始 JSON 格式打印所有进程列表pm2 jlist# 用美化的 JSON 打印所有进程列表pm2 prettylist  # 展示特定进程的所有信息pm2 describe 0# 使用仪表盘监控所有进程pm2 monit             

# 日志管理# 实时展示所有应用的日志pm2 logs          # 实时展示 app 应用的日志 pm2 logs app# 使用json格式实时展示日志,不输出旧日志,只输出新产生的日志pm2 logs --json# 应用管理# 停止所有进程pm2 stop all# 重启所有进程pm2 restart all       

# 停止指定id的进程pm2 stop 0     

# 重启指定id的进程pm2 restart 0         

# 删除id为0进程pm2 delete 0# 删除所有的进程pm2 delete all         
复制代码

每一条命令都可以亲自尝试一下,看看效果。

这里特别展示下 monit 命令,它可以在终端中启动一个面板,实时展示应用的运行状态,通过上下箭头可以切换 pm2 管理的所有应用:

노드 다중 프로세스 모델 및 프로젝트 배포에 대해 이야기하는 기사

进阶:使用 pm2 配置文件

PM2 的功能十分强大,远不止上面的这几个命令。在真实的项目部署中,可能还需要配置日志文件,watch 模式,环境变量等等。如果每次都手敲命令是十分繁琐的,所以 pm2 提供了配置文件来管理和部署应用。

可以通过以下命令来生成一份配置文件:

[root@ecs-221238 express-demo]# pm2 init simpleFile /www/express-demo/ecosystem.config.js generated复制代码

会生成一个ecosystem.config.js 文件:

module.exports = {
  apps : [{
    name   : "app1",
    script : "./app.js"
  }]
}复制代码

也可以自己创建一个配置文件,比如 app.config.js

const path = require('path')module.exports = {  // 一份配置文件可以同时管理多个 node.js 应用
  // apps 是一个数组,每一项都是一个应用的配置
  apps: [{
    // 应用名称
    name: "express-demo",

    // 应用入口文件
    script: "./server.js",

    // 启动应用的模式, 有两种:cluster和fork,默认是fork
    exec_mode: 'cluster',

    // 创建应用实例的数量
    instances: 'max',

    // 开启监听,当文件变化后自动重启应用
    watch: true,

    // 忽略掉一些目录文件的变化。
    // 由于把日志目录放到了项目路径下,一定要将其忽略,否则应用启动产生日志,pm2 监听到变化就会重启,重启又产生日志,就会进入死循环
    ignore_watch: [
      "node_modules",
      "logs"
    ],
    // 错误日志存放路径
    err_file: path.resolve(__dirname, 'logs/error.log'),

    // 打印日志存放路径
    out_file: path.resolve(__dirname, 'logs/out.log'),

    // 设置日志文件中每条日志前面的日期格式
    log_date_format: "YYYY-MM-DD HH:mm:ss",
  }]
}复制代码

让 pm2 使用配置文件来管理 node 应用:

pm2 start app.config.js复制代码

现在 pm2 管理的应用,会将日志放到项目目录下(默认是放到 pm2 的安装目录下),并且能监听文件的变化,自动重启服务。

노드 다중 프로세스 모델 및 프로젝트 배포에 대해 이야기하는 기사

更多有用的配置可以参考 PM2 官方文档,点此访问

Nginx 代理转发接口

上面我们直接将 nodejs 项目的3000端口暴露了出去。一般我们都会使用 nginx 做一个代理转发,只对外暴露 80 端口。

安装 Nginx

首先服务器中需要安装 nginx ,有三种方式:

  • 下载源码编译安装
  • 使用 docker 安装
  • 使用包管理工具安装

我这里的系统是 CentOS 8,已经更换了可用的 yum 源,可以直接安装 nginx。如果你的操作系统为 CentOS 7 或者其他发行版,可以搜索适合的安装方法。

使用 yum 安装:

# yum install -y nginx复制代码

然后启动 nginx:

# systemctl start nginx复制代码

打开浏览器访问服务器地址,可以看到 nginx 默认的主页:

노드 다중 프로세스 모델 및 프로젝트 배포에 대해 이야기하는 기사

配置接口转发

为项目新建一个配置文件:

# vim /etc/nginx/conf.d/express.conf复制代码

监听80端口,将所有请求转发给服务器本地的3000端口的程序处理:

server {
    listen       80;
    server_name  ironfan.site;
    location / {
          proxy_pass http://localhost:3000;
    }
}复制代码

conf 目录下的配置文件,会被主配置文件 /etc/nginx/nginx.conf 加载:

노드 다중 프로세스 모델 및 프로젝트 배포에 대해 이야기하는 기사

修改完配置文件,一定要重启服务:

# systemctl restart nginx复制代码

然后本地打开浏览器,去掉原来的3000端口号,直接访问完整的 url:

노드 다중 프로세스 모델 및 프로젝트 배포에 대해 이야기하는 기사

到这里,就完成了接口转发的配置。从用户的角度出发,这个也叫反向代理。

总结

首先我们比较系统的讲解了为何需要在 node.js 项目中开启多进程,以及两种实现方式:

  • child_process 模块的 fork 方法
  • cluster 模块fork 方法

之后,又讲解了如何在 Linux 服务器中安装 node 环境,以及部署一个 node.js 项目的大致流程,并着重介绍了 pm2 的使用:

  1. 上传项目到服务器中
  2. 安装项目依赖
  3. 使用 pm2 管理应用

最后,讲解了使用 nginx 实现接口的代理转发,将用户请求转发到本地的3000端口的服务。

至此,我们完成了本文的目标,将一个 express 项目部署到服务器,并能稳定可靠的运行

下篇文章,我们会使用 Github Actions 实现 CI/CD,让项目的部署更加便捷高效。

本文演示代码,已上传至 Github,点击访问

更多node相关知识,请访问:nodejs 教程

위 내용은 노드 다중 프로세스 모델 및 프로젝트 배포에 대해 이야기하는 기사의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.