1. 程式人生 > >Openrestry 平滑重啟(無reload,不重啟nginx)

Openrestry 平滑重啟(無reload,不重啟nginx)

在分散式服務下,我們會用nginx做負載均衡, 業務站點訪問某服務站點的時候, 統一走nginx, 然後nginx根據一定的輪詢策略,將請求路由到後端一臺指定的伺服器上。

這裡寫圖片描述

這樣的架構是沒有問題的, 但是我們這裡考慮幾個問題:
1) 業務頻繁上下線問題:我們APP、業務系統平時更新的時候是直接覆蓋檔案,然後重啟, 那這樣會造成一些請求中斷,如果是非核心邏輯那還好, 如果是核心邏輯,那請求中斷,會影響一些資料一致性,比如資金, 交易,訂單等。

2) 業務應用動態擴容與縮容,比如某個業務應用訪問量大,要新增機器進行水平擴容或者縮容,那就需要修改nginx的配置,然後reload, 這樣會中斷連線。 雖然reload很快,但是還是會有一瞬間的請求中斷。 如果某個應用配置了彈性伸縮策略,那麼可能在短時間內多次頻繁reload nginx,那麼對線上其他應用將會導致不可預知的風險。
對於第一個問題,我們可以在請求量少的時候去更新, 但是這種在一些服務穩定的公司可用, 對於網際網路企業,可能1-2天就一個版本, 2-3天就是一個大促, 如果每次都要等到凌晨1-2點去更新, 不太現實。
對於第二個問題,現有的方法和手段顯然是不太好解決的。網際網路公司運維的目標始終是自動化運維,不以自動化運維為目標的運維就不是網際網路運維。

解決方案與對策的思考
操作nginx上下線,這裡的確是一個難點,因為nginx本身並沒有提供這些上下線API,需要openresty並配合一些第三方擴充套件來實現。例如:ngx_http_dyups_module 、 lua-upstream-nginx-module、ngx_dynamic_upstream等等。
但是這些nginx擴充套件元件的問題是無法將upstream中配置的server進行持久化(呼叫API之後,這些擴充套件會重新整理nginx的記憶體,可以實現無reload、無重啟,平滑擴容和縮容)
例如,使用ngx_http_dyups_module的API:

curl -d "server 127.0.0.1:8089;server 127.0.0.1:8088;" 127.0.0.1:8081/upstream/ip.haiziwang.com

因為這些外掛無法持久化配置,所以我們還需要使用lua指令碼進行持久化,或者開發nginx 的WEB程式管理配置檔案。
核心步驟是:
1 修改nginx配置檔案,並持久化到資料庫
2 nginx -t 檢查配置檔案是否正確
3 呼叫ngx_http_dyups_module,在記憶體中重新整理域名

以上步驟因為操作一共有3個步驟,可能會有某一個步驟執行失敗。WEB管理程式需要保證以上步驟的冪等性。

$ git clone git://github.com/yzprofile/ngx_http_dyups_module.git
# 將下載的模組移動到openrestry的根目錄 $ mv ngx_http_dyups_module /opt/openresty1.9.xx #新增模組 $ ./configure --add-module=./ngx_http_dyups_module #重新編譯nginx $ make && make install

ok , 我們使用ngx_http_dyups_module的時候需要將proxy_pass配置成:http://$host(nginx記憶體中的一個變數)

server {
        listen       80;
        server_name  abc.haiziwang.com;
        location   / {
               #proxy_pass              http://abc.haiziwang.com;
               proxy_pass      http://$host;
               proxy_set_header        Host  abc.haiziwang.com;
               proxy_set_header        X-Real-IP $remote_addr;
               proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
        }  
}

server {
        listen 18080;
        location / {
            dyups_interface;
        }
    }

OK,然後我們呼叫API,就可以控制abc.haiziwang.com後端反向代理的伺服器IP地址了,例如:

curl -d "server 172.172.177.75:5050;" 127.0.0.1:18080/upstream/abc.haiziwang.com
curl -i -X DELETE 127.0.0.1:18080/upstream/abc.haiziwang.com