服務端架構中的“閘道器伺服器”
這麼一個場景:一個要承載高併發、具有高效能的後臺服務,往往會有多個不同的應用服務。問題來了,你會怎樣設計架構呢?
如下圖所示,為了共用一個穩定高效的網路處理功能,把所有服務寫在一個程序裡。
接下來悲劇一幕幕就要上演了,如果各個模組是多人協作開發,網路庫的作者得想辦法設計個外掛機制供各個應用掛載,開發時無論是人員或者程式碼都耦合非常嚴重,大大影響協作、開發效率,後期要增減一個應用也得大動手腳。好吧,這還可以忍受,問題是寫應用的人技術水準還可能層次不齊,一個短板就可能造成整個服務崩潰。
彼此的依賴太嚴重,效率低下,責任推諉讓各個協作者們苦不堪言,各個應用服務的作者決定在自己的服務裡單獨提供網路模組。就有了如下圖的情況,每個應用服務的提供者自己還要提供網路功能模組
接下來悲劇又一幕幕上演了,要知道高效能網路服務模組需要的技術含量之高不是人人都可以寫好的,即使咱都能寫好或者統一使用了一個牛X的網路庫,你對客戶端暴露那麼多服務地址不討人嫌嘛,甚至在我身邊還有采用專門寫一個集中服務來供客戶端獲取各應用服務的地址的設計......。
通過對上面兩種設計的批判,大家是不是會想,這架構缺陷很明顯,肯定採用的人很少吧,但是說實在的我已經遇到多次這種設計了,也許是觀點不同吧,我對以上兩種設計在上述場景下持否定態度。
那我們應該採用怎樣的設計適應這種場景呢?
如下圖,這是騰訊和微信的部分後臺設計架構圖
可以看到都會有個接入服務,然後把不同的請求分發給不同的應用服務。其實這個接入服務就是“閘道器服務”,這種設計在nginx的負載均衡和反向代理功能中都有體現,另外在網遊伺服器中也大量採用了這種設計思路,由閘道器伺服器將不同的請求分發到不同的應用服務上,等應用伺服器處理完後再通過閘道器伺服器轉發給客戶。
那這種設計的優點在哪呢?
借用知乎王明雨知友的一個比喻:
-
這樣可以把要承載高併發,高效能任務的網路服務獨立出來專門做好,做強(對於http協議的場景,可以直接用nginx做閘道器伺服器)。這樣各個應用只需把重點放在對業務邏輯的處理即可。從技術架構和專案協作上都做到了解耦。
-
增強了系統的健壯性,一個應用出現故障並不會對其他應用產生影響。後期運維也好做灰度更迭。
-
有應用叢集的情況下,可以通過閘道器伺服器做負載均衡,把請求分發在負載低的伺服器上。
再引用一個遊戲公司對閘道器伺服器的評價: