服務端 node服務的監控預警系統架構

2021-09-17 02:15:49 字數 3447 閱讀 2320

本文由尚妝前端開發工程師欲休撰寫

目前node端的服務逐漸成熟,在不少公司內部也開始承擔業務處理或者檢視渲染工作。不同於個人開發的簡單伺服器,企業級的node服務要求更為苛刻:

高穩定性、高可靠性、魯棒性以及直觀的監控和報警

想象下乙個存在安全隱患且沒有監控預警系統的node服務在生產環境下執行的場景,當某個node例項掛掉的情況下,運維人員或者對應開發維護人員無法立即知曉,直到客戶或者測試人員報告bugs才開始解決問題。在這段無人處理的時間內,損失的訂單數和使用者的忠誠度和信任度將是以後無法彌補的,因此對於node程式的業務開發者而言,這就要求**嚴謹、異常處理完備;對於node框架的維護者而言,則需要提供完善的監控預警系統

當乙個服務程序在後端執行時(daemon),作為開發者我們關注的資訊主要有以下幾點:

可以看出,不管是針對主機還是程序進行監控,我們的關注點大多數是資源使用率和業務量處理能力,因此我們的監控預警系統也著重實現這些功能。

目前生產環境下的node服務大多採用多程序或者cluster模式,而且為了響應突發流量往往採用多機部署,因此監控和預警的目標實體就是多物理(虛擬)機下的多個子程序

在這裡,筆者採用了分布式資料一致系統zookeeper(下文簡寫為zk)實現資料的存和讀。之所以沒有採用傳統的資料庫是由於讀寫表的效能,如為了防止多個程序同時寫表造成衝突必須進行鎖表等操作,而且讀寫硬碟的效能相對記憶體讀寫較低;之所以沒有採用ipc+事件機制實現多程序通訊,主要是由於node提供的ipc通訊機制僅限於父子程序,對於不同主機的程序無法進行通訊或者實現複雜度較高,因此也並未採用該種方式。

採用zk來實現多節點下的資料同步,可在保證集群可靠性的基礎上達到資料的最終一致性,對於監控系統而言,不需要時刻都精確的資料,因此資料的最終一致性完全滿足系統的需求。zk服務集群通過paxos演算法實現選舉,並採用zk獨特的演算法實現資料在各個集群節點的同步,最終抽象為乙個資料層。這樣zk客戶端就可以通過訪問zk集群的任意乙個服務節點獲取或讀寫相同的資料,用通俗的語言來形容,就是zk客戶端看到的所有zk服務節點都有相同的資料。

另外,zk提供了一種臨時節點,即ephemeral。該節點與客戶端的會話session相繫結,一旦會話超時或者連線斷開,該節點就會消失,並觸發對應事件,因此利用該種特性可以設定node服務的isalive(是否存活)功能。不過,目前node社群針對zk的客戶端還不是很完善(主要是文件),筆者採用node-zookeeper-client模組並且針對所有介面promise化,這樣在進行多級znode開發時更可讀。

上圖是筆者設計的監控預警系統的架構圖,這裡需要著重關注一下幾點:

下面著重詳述以上幾點。

上節已提到,zookeeper抽象為乙個資料一致層,它是由多個節點組成的儲存集群,因此在具體的線上環境下,zk集群是由多個線上主機搭建而成,所有的資料都是儲存在記憶體中,每當對應工作程序的資料發生變化時則修改對應znode節點的資料,在具體實現中每個znode節點儲存的是json資料,便於node端直接解析。

在具體的**中,我們需要注意的是zk客戶端會話超時和網路斷開重連的問題。預設,zk客戶端會幫助我們完成網路斷開後重連過程的簡歷,而且在重新連線的過程中會攜帶上次斷開連線的session id,這樣在session未超時的前提下仍會繫結之前的資料;但是當session超時的情況下,對應session id的資料將會被清空,這就需要我們的自己處理這種情況,又稱作現場恢復。其實,在監控系統中,由於需要實時查詢對應節點資料,需要始終保持session,在設定session expire時間的情況下終究會出現zk客戶端會話超時的情況,因此需要我們實現現場恢復,需要注意。

大多數開發者為了提高node程式的並行處理能力,往往採用乙個主程序+多個工作程序的方式處理請求,這在不需要監控預警系統的前提下是可以滿足要求的。但是,隨著監控預警功能的加入,有很多人估計會把這些功能加入到主程序,這首先不說主程序工作職能的混亂,最主要的是額外增加了風險性(預警系統的職能之一就是打點堆快照,並提醒開發者。因此主程序內執行查詢、打點系統資源、傳送郵件等工作存在可能的風險)。因此為了主程序的功能單一性和可靠性,建立了乙個precaution程序,該程序與主程序同級。

採用1+n+1模型並不會影響請求處理效率,工作程序的職能仍是處理請求,因此新的程序模型完全相容之前的**,需要做的就是在主程序和precaution程序執行的**中新增業務部分**。

在監控預警系統中,需要實現precaution程序master程序、master程序worker程序、precaution程序worker程序的雙向通訊,如打點記憶體,需要由precaution程序通知對應worker程序,worker進行打點完成後傳送訊息給precaution程序,precaution進行處理後傳送郵件通知。

首先,worker與master的通訊走的是node提供的ipc通道,需要注意的是ipc通道只能傳輸字串和可結構化的物件。可結構化的物件可以用乙個公式簡易表述:

o = json.parse(json.stringify(o))
如regexp的例項就不是可結構化物件。

其次,worker和precaution的通訊是通過master作為橋梁實現的,因此其中的關節點就在於precaution與master的通訊。

最後,precaution與master的通訊採用domain socket機制實現,這兩個程序是只是兩個node例項而已,因此無法採用node提供的ipc機制,而程序間通訊可以採用其他方法如:命名管道、共享記憶體、訊號量和訊息佇列等,採用這些方法實現固然簡單,但是缺點在於兩個程序耦合度相對較高,如命名管道需要建立具體的管道檔案並且對管道檔案大小有限制。使用domain socket,最大的好處就是靈活制定通訊協議,且易於擴充套件。

node的net模組提供了domain socket的通訊方式,與網路伺服器類似,採用domain通訊的伺服器偵聽的不是埠而是sock檔案,採用這種方式實現全雙工通訊。

這裡提到的業務量,指的是監控預警系統所關注的資料業務,如記憶體和cpu利用率、吞吐量(request per minute)和響應時間。其中,記憶體和cpu利用率可以通過linux下的相關命令如top來查詢,響應時間和吞吐量則通過koa中介軟體實現粗略統計。不過為了方便開發者把精力集中到業務上去而非相容底層作業系統,建議使用pidusage模組完成資源利用率的測量,而針對吞吐量筆者並未找到相關的工具進行測量,僅在中介軟體中粗略計算得出。

在precaution程序中,設定了兩個閾值。乙個是warning值,當使用記憶體大小超過了該值則進行日誌打點,並開始週期性的node堆記憶體打點;另乙個是danger值,超過該值則進行記憶體打點並傳送郵件提醒,根據附件中的近三個快照分析記憶體。

採用上述監控預警架構,可以有效的實現多節點下多程序的監控,在確保程序可靠性的基礎上完成侵入性較小的、安全性較高的、可擴充套件性強的實現。以後不管是臨時擴張主機節點還是更改子程序數量,都可以瞬時在ui介面上直觀體現,如

node服務的監控預警系統架構

目前node端的服務逐漸成熟,在不少公司內部也開始承擔業務處理或者檢視渲染工作。不同於個人開發的簡單伺服器,企業級的node服務要求更為苛刻 高穩定性 高可靠性 魯棒性以及直觀的監控和報警 想象下乙個存在安全隱患且沒有監控預警系統的node服務在生產環境下執行的場景,當某個node例項掛掉的情況下,...

node服務的監控預警系統架構

目前node端的服務逐漸成熟,在不少公司內部也開始承擔業務處理或者檢視渲染工作。不同於個人開發的簡單伺服器,企業級的node服務要求更為苛刻 高穩定性 高可靠性 魯棒性以及直觀的監控和報警 想象下乙個存在安全隱患且沒有監控預警系統的node服務在生產環境下執行的場景,當某個node例項掛掉的情況下,...

draft js 服務端node 執行

draftjs 的繪製轉換本身是在 瀏覽器中執行的,如果希望服務端進行執行相關方法,需要模擬乙個dom 環境,如下demo 中使用了 jsdom 進行模擬 var react require react var reactdomserver require react dom var require...