日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Egg.js 多机平滑重启实践

發布時間:2023/12/20 编程问答 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Egg.js 多机平滑重启实践 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前提:

首先要聲明的是,我們的應用都是在阿里云上多機部署的。當然這里不是安利文,而是給有相同問題的朋友一個實踐的參考。

背景:

我在公司處在一個側重 js 技術方向的團隊,后端項目也較多基于 node.js 開發。項目幾經更迭也經歷了 koa1 --> koa2 --> egg.js 的框架變更。

在早期項目依賴 koa 的時候,部署方案就是依賴 gitlab-ci + pm2 的方式做自動化部署和進程管理。pm2 可以管理進程的啟動和監控,也可以在進程意外終止的時候重新拉起新的進程保證項目持續運作。但缺點也很明顯,首先 pm2 本身會需要資源,這個資源與項目進程的負載是成線性關系的,也就是當我們的并發量大的時候,進程需要更多的資源來處理請求,而 pm2 作為資源的分配者,也需要更多的資源來管理請求和進程的資源調度。甚至出現 god deamon 進程占用了1個多g內存😖。這本身來講是額外的資源消耗,并不是我們所希望的。另一方面我們也遇到了在高并發的情況下,pm2 并不能實現 100% 的平滑重啟。每當有新的代碼被部署的時候,還是會出現一定的請求失敗的情況。這與 pm2 本身有關,相關的問題不是單一的,這里不一一展開🙍?♂?。

切換到 egg.js 之后,請求的調度任務由項目本身的 master 進程來管理,可以盡可能讓項目最大化的利用硬件資源。而且少了 pm2 作為媒介,不用去理會 pm2 造成的影響,可以更加關注項目本身的問題。

但是 egg.js 提供的啟動方案只有簡單的 start 和 stop。也就是當我要更新項目的時候,一定要關閉所有進程然后再啟動項目。這樣會造成服務的短暫不可用的情況,顯然不是我們希望看見的。

所以,我們通過各種嘗試來完善 egg.js 的重啟問題😁。

嘗試:編寫熱重啟腳本

在簡單了解 pm2 的重啟原理后,我們知道,pm2 先 fork 出一個新的進程,然后通過 ipc 通知一個進程關閉,當進程關閉后,pm2 再 fork 新的進程,這樣逐個重啟過去的,可以理解為串行。

通過 pm2 的這個方案,結合 egg-scripts 的源碼,我們修改出了一個可以逐個啟動進程的啟動腳本?egg-cluster-script?😄

起初在請求量低的時候,這個方案看似是可行的(因為錯誤少,沒發現)。但是當我們把服務對接給公司其他業務方后,請求量激增,這個方案的問題就暴露出來了😓:

  • 每當我們 kill 一個進程的時候,在這個進程在真正退出之前依然會被 master 分配請求,這些請求并不能被消化,所以在重啟的時候永遠有一個不能處理請求的進程被分配了請求,造成大量的請求錯誤
  • 當有新的 schedule 腳本上線的時候,無法添加到 master 進程中進行調度,你最后還是不得不重啟整個項目
  • 如果要深入到請求調度上的問題,這個改動的成本就相對較高了。最終,我們放棄了這個方案。轉而尋求通過外部手段的方式來達到平滑重啟的目的😖。

    新的方向:SLB 的利用

    首先我們前提中提到我司的服務都是部署在阿里云上的,基本的部署情況差不多如圖:

    通常我們的服務是部署在多臺 ecs 上的,每臺 ecs 上部署多個進程的應用。通過 SLB 做負載均衡,把請求根據權重適當的分配給每個 ecs🤔。

    在 SLB 中,定時的健康檢查判斷每個 ecs 上的服務是不是可用的,當不健康的檢查超出了給定的閾值,SLB 就會將 ecs 摘除,不會再將請求分發給這個 ecs,直到這臺 ecs 的健康檢查恢復正常。

    通過這個健康檢查的原理,當 ecs 被摘除的時候,我們就可以任意去擺布這臺 ecs 上的進程了。

    有了思路后,接下來就是指定實現的方案🧾:

  • 給 app 添加健康狀態的屬性,例如:app.running = true,當 process 接收到特定的信號量的時候,會改變健康狀態。不掛在 app 上也行,只要能保證全局找得到這個唯一的狀態值;
  • // app.js module.exports = class AppBook {/**** @param {Egg.Application} app*/constructor(app) {this.app = app;app.running = true;process.on('SIGINT', () => {app.running = false;});} }

    2. 項目提供一個健康檢查的接口 /devops/health ,通常情況下我們采取 head 請求直接返回 狀態碼,當 app.running = true 的時候返回 204,否則返回 500;

    const { Controller } = require('egg');module.exports = class DevopsController extends Controller {healthCheck() {const { ctx } = this;if(this.app.runnint === true) {ctx.body = null;}else {ctx.status = 500;ctx.body = '';}} }

    3. 編寫信號發送腳本改變 app 的健康狀態;

    // scripts/health-down.js // 這里的 findNodeProcess,appWorkerPath,titleTemplate 都可以從 egg-script 中找到 async function run () {const processList = await findNodeProcess(item => {const cmd = item.cmd;const title = 'your-app-name'return cmd.includes(appWorkerPath) && cmd.includes(util.format(titleTemplate, title));});for(const pro of processList) {const pid = pro.pid;process.kill(pid,'SIGINT');}// 健康狀態修改之后暫定 5s 讓 slb 摘除 ecs 后再進行進程處理await new Promise(resolve => setTimeout(resolve, 5000)); }run();

    4. 給 package.json 添加 scripts: "health:down": ''node scripts/health-down.js", 我們是使用 pm2-depoly 執行的部署。所以在 ecosystem.config.js 中,應用的 deploy 做修改;

    // ecosystem.config.js module.exports = {deploy: {production: {user: 'your-deploy-user',host: [...'your-ecs-hosts'],ref: 'deploy-ref',repo: 'project-repo',ssh_options: ['StrictHostKeyChecking=no'],path: 'deploy-path-on-ecs','pre-deploy': 'git fetch && npm run health:down','post-deploy': 'npm install --production --no-save && npm stop && npm start'}} };

    5. 設置健康檢查策略,讓 slb 可以動態摘除/添加 ecs;

    我這里健康檢查的頻率設置的相對頻繁,可以根據自己的需要修改這里的配置。大體的意思就是只要 2 次檢查不通過就會把 ecs 摘除,之后只要連續兩次檢查正常就會把 ecs 重新添加回來。

    之后就是結合自己的 ci 來自動部署了。通過這個方式,我們的項目可以在任何時候實現項目的平滑重啟,經驗證即使在高峰時段也沒有出現異常。

    當前已經應用的項目是日訪問量在 2億😺 左右的服務,正在逐步推廣到其他服務中去。這個實踐也并非針對 eggjs 項目,應該是具有相對通用性的方案,可以在任意語言和框架中采用😁。

    結尾:

    一定有人問為什么一開始不直接采用 SLB 的方案而要繞這么大個彎子。其實原因挺多的

  • 首先,我一開始是真的沒想到這個方案😳
  • 作為一個一線代碼搬運工,什么事都希望能通過編碼來解決,這是一種執著💊
  • eggjs 在項目中也是第一次實踐,多動手能更為理解其整個生態😂
  • 轉自?https://zhuanlan.zhihu.com/p/84632879

    總結

    以上是生活随笔為你收集整理的Egg.js 多机平滑重启实践的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。