基於Nginx dyups模塊的站點動態上下線並實現簡單服務治理


今天主要討論一下,對於分布式服務,站點如何平滑的上下線問題。 

在分布式服務下,我們會用nginx做負載均衡, 業務站點訪問某服務站點的時候, 統一走nginx, 然后nginx根據一定的輪詢策略,將請求路由到后端一台指定的服務器上。 
 
這樣的架構是沒有問題的, 但是我們這里考慮幾個問題, 
1. 網站上下線問題:我們網站平時更新站點的時候是直接覆蓋文件,然后重啟, 那這樣會造成一些請求中斷,如果是非核心邏輯那還好, 如果是核心邏輯,那請求中斷,會影響一些數據一致性,比如資金, 交易,訂單等。  
 2. 動態加減機器,比如某個站點訪問量大,要新增機器,那就需要修改nginx的配置,然后reload, 這樣會中斷連接。 雖然reload很快,但是還是會有一瞬間的請求中斷。 
 
對於第一個問題,我們可以在請求量少的時候去更新, 但是這種在一些服務穩定的公司可用, 對於互聯網企業,可能2-3天就一個版本, 而且需要立刻上線, 如果每次都要等到凌晨4點去更新, 可能整個的開發節奏都被帶慢了。 
對於第二個問題, 對於可以預見的流量,比如大促來臨,可以提前3天放在請求量少的時候更新。 
 
最近幾年,隨着SOA的普及和微服務的出現,特別是dubbo的出現,服務治理的概念被提出來。 服務治理是一個很宏大的概念,包括 服務注冊,服務自動發現,服務路由,服務依賴,集群容錯,服務降級,服務監測,服務審批等,當然不是每個服務中心都必須實現這些東西, 公司可以根據自己的實際需求來定制實現。 
基於以上這些情況, 我計划實現一個工具,這個工具首先解決站點上下線和動態擴容問題,也就是說在不需要重啟nginx的情況下,並且在保證請求不丟失的情況下來更新站點。 同時帶有部分服務治理功能。 
 
 
服務上線
1. 在一個新服務上線的時候,一般會提前申請幾台機器, 運維會在nginx上新增server,並新增server對應的upstream ,正常情況下upstream應該配置是后端服務器的IP,但是這里不配置(如果允許,甚至這一步都可以省略)。 
2. 服務部署好並啟動,在啟動的時候,向注冊中心注冊自身的服務信息,包括IP和端口。 
3. 注冊中心收到請求后,會對服務進行健康檢測,確保提供的服務沒有問題,則將服務狀態標示為 預上線狀態。 
4. 在后台管理中心,就可以將 預上線的服務設置為 上線,服務管理中心會調用nginx的上線接口,將服務IP新增或者更新到upstream中,服務就可以提供訪問。   
 
服務更新
假如我們現在有一個服務需要更新,則執行以下步驟:
1. 在后台管理中心,將一個服務設為 下線,此時服務中心會調用nginx的下線接口,將指定服務器的IP設置為下線。 
2. 在等待1分鍾后,確保沒有新連接連過來,則可以開始更新服務站點。
3. 更新完畢后,再手動設為 上線,此時服務中心會調用nginx的上線接口,將指定服務器的IP設置為上線。當然對於成熟的服務,這些都可以自動化,有些公司會有一些自動化發布工具, 與自動化發布工具集成,可以一鍵下線,更新並上線。 
 
服務運行期間
在服務運行過程中,會有一個健康檢測的服務對所有提供服務的站點進行健康檢測,一旦檢測到有問題,就執行 下線邏輯。 直到問題被解決,最后執行 上線流程。 
 
動態加減機器
在服務運行過程中,可能因為某些原因,服務請求飆高(前提是這些請求都是合法的),超過了當前集群的承載能力,當系統檢測到這些情況后,可以動態擴充機器,比如現在流行的docker,在啟動容器的時候,同時啟動應用,應用在啟動的時候,將自身信息注冊給注冊中心,注冊中心再將這些信息同步到nginx,應用就可以提供訪問,整體上就可以實現彈性計算。 
 
為什么不實現服務動態發現?
   這里可以看到圖中已經有一個服務注冊中心。 既然有了服務注冊中心了, 那可以讓業務站點連接服務注冊中心來獲取真實的服務IP,然后繞過nginx來連接服務,這里之所以沒有這樣做,是因為:
    1.  實現服務動態發現,這個需要和RPC框架配合,而且需要做服務的軟負載,失敗重連,限流等,整個項目設計就上升了一個復雜度, 考慮到有些項目還未使用RPC,並且不想對原有的項目有過多的侵入, 所以這里不做實現。 但是並不意味沒有這些功能,服務的負載, 失敗重連, 限流,其實這些功能在nginx中同樣也有,可以直接使用,所以沒有必要重新再開發。 
    2.  實現服務動態發現,獲取到真實的服務IP,然后直連,這些一般是在流量特別大,nginx上出現短板的時候使用,但實際情況,一般很少會耗盡nginx的性能,即使有,也可以通過ngxin水平擴展來實現,所以這里依然使用nginx作為負載均衡。 
 
這里講一下這個項目的關鍵點:
1. 服務的注冊和健康檢測這個沒有技術難點,這里不做解釋。
2. 關於操作nginx上下線,這里的確是一個難點,因為nginx本身並沒有提供這些上下線API,需要openresty並配合一些第三方擴展來實現。 這里主要用到了兩個擴展模塊: ngx_http_dyups_module  lua-upstream-nginx-module
   ngx_http_dyups_module( https://github.com/yzprofile/ngx_http_dyups_module)提供了粗粒度的upstream管理方法,可以對整個upstream進行新增,刪除。 
  lua-upstream-nginx-module( https://github.com/openresty/lua-upstream-nginx-module) ,則提供了細粒度的管理方式,可以對某一個服務IP進行管理,其中提供的set_peer_down方法,可以對upstream中的某個ip進行上下線。
3. 也可以使用 ngx_dynamic_upstream( https://github.com/cubicdaiya/ngx_dynamic_upstream)
這些插件有一個共同點,那就是在不需要重啟nginx的基礎上, 動態修改nginx的配置。 
1. 最后我想請大伙討論一下,你們公司是怎么上下線的, 是直接覆蓋,還是有其他策略。 歡迎在評論區討論。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM