如何在 PM2 中实现 Node.js 应用程序的零停机部署

阅读时长 11 分钟读完

随着 Node.js 的广泛应用,越来越多的开发者开始使用 PM2(一个 Node.js 进程管理器)来管理和监控 Node.js 应用程序的运行。PM2 提供了许多功能,其中一个非常有用的功能是“零停机部署”。

本文将介绍如何在 PM2 中实现 Node.js 应用程序的零停机部署。本文假设你已经熟悉 PM2 的基本使用方法,如果不了解 PM2,可以参考官方文档。

实现细节

在介绍具体实现细节之前,我们先来了解一下零停机部署的具体含义。所谓“零停机部署”,指的是在不影响现有用户使用的情况下,对 Node.js 应用程序进行更新。也就是说,当你发布新版本的应用程序时,旧版本的应用程序仍然可以正常运行,同时新版本的应用程序也会逐渐启动。

那么,如何实现这一点呢?下面是具体的步骤:

  1. 发布新的代码到服务器上。
  2. 启动一个新的进程,运行新版本的应用程序。
  3. 将新的进程添加到现有进程组(process group)中。
  4. 逐步向新的进程转移流量,直到所有流量都转移到新的进程上。
  5. 关闭旧版本的应用程序。

可以看出,这个过程是非常复杂的,需要使用一些技巧才能实现。下面我们来了解一些具体的实现细节。

1. 双进程部署

为了实现零停机部署,我们需要一种方法来同时运行旧版本和新版本的应用程序。为此,我们可以使用“双进程部署”模式,即同时启动两个进程,一个是旧版本的进程,一个是新版本的进程。

在 PM2 中,我们可以用以下命令启动两个进程:

这样就同时启动了两个进程,一个是名为 my-app-old 的进程,一个是名为 my-app-new 的进程。可以通过 pm2 ls 命令来查看当前进程状态。

2. 动态流量转移

一旦有了两个进程,我们就需要一种方法来迅速地将流量从旧版本的进程转移到新版本的进程。这里使用了“动态流量转移”模式,即根据实时流量情况来给新的进程动态地分配更多的流量。

具体实现的方式,可以使用 PM2 的“流量重载”功能来实现。以下是示例代码:

-- -------------------- ---- -------
-- --- ------- ----------
--------------------- ---------- -
  -- --------
  ---------------------- ----- -
    -- ----- ----- ----

    -- ---- ---------- ---
    --- ----------- - ----------------- -- ------------ --- --------------

    -- ---- ---------- ---
    --- ----------- - ----------------- -- ------------ --- --------------

    -- ---------------
    -- ------------- -- -------------------------- --- --------- -
      ---------------- ------- -- --- -----------
      -------
    -

    -- ------------------------------
    -- ------------- -- -------------------------- --- --------- -
      ---------------- ------- -- --- -------- --- ------- ---- -- -------- -- --- --- -----------
      ------------------------------------- - --
      ----------------------------------------- ----------
    - ---- -
      -- --------------------
      --- ------------- - ------------------------------------------------- - --
      ------------------------------------- - --------------
      ------------------------------------- - - - --------------
      -------------------- ------ ---------------------------------------- -- -------------------------------------------
      ----------------------------------------- ----------
    -
  ---
---

上面的代码监听了 SIGUSR2 信号,在接收到该信号时会触发相应逻辑。逻辑的核心是通过 pm2.list 命令获取当前所有进程的信息,然后根据流量情况动态地为新旧两个进程分配流量。最后,通过 SIGINT 信号来关闭不需要的进程。

需要注意的是,在上面的代码中,为了方便起见,我们使用了一个环境变量 TRAFFIC_RATIO 来表示当前进程的流量占比。实际应用中,需要根据具体情况进行修改。

3. 最终版本发布

最后一个问题是,在动态流量转移完成后,如何彻底关闭旧版本的进程。这个问题的解决方法很简单:当流量全部转移到新版本的进程上后,关闭旧版本的进程即可。

以下是示例代码:

-- -------------------- ---- -------
-- --- ------- ----------
--------------------- ---------- -
  -- --------
  ---------------------- ----- -
    -- ----- ----- ----

    -- ---- ---------- ---
    --- ----------- - ----------------- -- ------------ --- --------------

    -- ---------------
    -- ------------ -- -------------------------- --- --------- -
      --------------------- --- -------------
      --------------------------- ------------- -
        -- ----- ----- ----
        ---------------- ------- -----------
        ----------------
      ---
    - ---- -
      ---------------- ------- -- --- -----------
      ----------------
    -
  ---
---

上面的代码监听了 SIGTERM 信号,在接收到该信号时会触发相应逻辑。逻辑的核心是通过 pm2.list 命令获取当前所有进程的信息,然后根据情况关闭旧版本的进程。

示例代码

最后,为了方便起见,以下是一份完整的示例代码,供参考:

-- -------------------- ---- -------
-- -------
----- --- - ---------------
----- ---- - ----------------

-- ---- ---- ------ ---- --
------------------------------- ---- -
  ------------------ - --------------- ------------ ---
  -------------- ----------
--------------- ------------- -
  -- ----- ----- ----
  ------------------- ------- -- ------------------------
---

-- --- ------- ----------
--------------------- ---------- -
  -- --------
  ---------------------- ----- -
    -- ----- ----- ----

    -- ---- ---------- ---
    --- ----------- - ----------------- -- ------------ --- --------------

    -- ---- ---------- ---
    --- ----------- - ----------------- -- ------------ --- --------------

    -- ---------------
    -- ------------- -- -------------------------- --- --------- -
      ---------------- ------- -- --- -----------
      -------
    -

    -- ------------------------------
    -- ------------- -- -------------------------- --- --------- -
      ---------------- ------- -- --- -------- --- ------- ---- -- -------- -- --- --- -----------
      ------------------------------------- - --
      ----------------------------------------- ----------
    - ---- -
      -- --------------------
      --- ------------- - ------------------------------------------------- - --
      ------------------------------------- - --------------
      ------------------------------------- - - - --------------
      -------------------- ------ ---------------------------------------- -- -------------------------------------------
      ----------------------------------------- ----------
    -
  ---
---

-- --- ------- ----------
--------------------- ---------- -
  -- --------
  ---------------------- ----- -
    -- ----- ----- ----

    -- ---- ---------- ---
    --- ----------- - ----------------- -- ------------ --- --------------

    -- ---------------
    -- ------------ -- -------------------------- --- --------- -
      --------------------- --- -------------
      --------------------------- ------------- -
        -- ----- ----- ----
        ---------------- ------- -----------
        ----------------
      ---
    - ---- -
      ---------------- ------- -- --- -----------
      ----------------
    -
  ---
---

-- ---------- ------- ----- -
-----------
  ------- ---------
  ----- -------------
  ---- -
    -------------- -  -- ------------------
  -
-- ------------- ----- -
  -- ----- ----- ----
  ---------------- ------- ------- ---- -- ----------------
  -----------
    ------- ---------
    ----- -------------
    ---- -
      -------------- -  -- -------------------
    -
  -- ------------- ----- -
    -- ----- ----- ----
    ---------------- ------- ------- ---- -- ----------------
    ------------------------- ------------- -
      -- ----- ----- ----
      ---------------- ------- ----- -- ------- ---------
      ------------------ ------ -- --------
    ---
  ---
---

总结

本文介绍了如何在 PM2 中实现 Node.js 应用程序的零停机部署。通过使用双进程部署和动态流量转移模式,我们可以在不影响现有用户的情况下,对 Node.js 应用程序进行更新。同时,本文还提供了一份完整的示例代码,供参考使用。希望这篇文章能对你有所帮助,谢谢阅读!

来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/64f72d1df6b2d6eab3fb3e09

纠错
反馈