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