平滑重啟mysql go平滑重啟調研選型和專案實踐

2021-10-19 23:48:17 字數 2083 閱讀 8339

什麼是平滑重啟

當線上**需要更新時,我們平時一般的做法需要先關閉服務然後再重啟服務. 這時線上可能存在大量正在處理的請求, 這時如果我們直接關閉服務會造成請求全部 中斷, 影響使用者體驗; 在重啟重新提供服務之前, 新請求進來也會502. 這時就出現兩個需要解決的問題:

老服務正在處理的請求必須處理完才能退出(優雅退出)

新進來的請求需要正常處理,服務不能中斷(平滑重啟)

優雅退出

在實現優雅重啟之前首先需要解決的乙個問題是如何優雅退出:

我們知道在go 1.8.x後,golang在http裡加入了shutdown方法,用來控制優雅退出。

社群裡不少http graceful動態重啟,平滑重啟的庫,大多是基於http.shutdown做的。

http shutdown 原始碼分析

先來看下http shutdown的主方法實現邏輯。用atomic來做退出標記的狀態,然後關閉各種的資源,然後一直阻塞的等待無空閒連線,每500ms輪詢一次。

var shutdownpollinterval = 500 * time.millisecond

func (srv *server) shutdown(ctx context.context) error

return err

複製**

這麼一系列的操作後,server.go的serv主監聽方法也就退出了。

if c.hijacked() .go我這裡是macos的原始碼實現參考原始碼)

// dup2(i, i) won't clear close-on-exec flag on linux,

// probably not elsewhere either.

_, _, err1 = rawsyscall(funcpc(libc_fcntl_trampoline), uintptr(fd[i]), f_setfd, 0)

if err1 != 0 複製**

結合supervisor時的問題

實際專案中, 線上服務一般是被supervisor啟動的, 如上所說的我們如果通過父子程序, 子程序啟動後退出父程序這種方式的話存在的問題就是子程序會被1號程序接管, 導致supervisor 認為服務掛掉重啟服務,為了避免這種問題我們可以使用master, worker的方式。

這種方式基本思路就是: 專案啟動的時候程式作為master啟動並監聽埠建立socket描述符但是不對外提供服務, 然後通過os.command建立子程序通過stdin, stdout, stderr,extrafiles和env傳遞標椎輸入輸出錯誤和檔案描述符以及環境變數. 通過環境變數子程序可以知道自己是子程序並通過os.newfile將fd註冊到epoll中, 通過fd建立tcplistener物件, 繫結handle處理器之後accept接受請求並處理, 參考偽**:

f := os.newfile(uintptr(3+i), "")

l, err := net.filelistener(f)

if err != nil

server.serve(l)

複製**

上述過程只是啟動了worker程序並提供服務, 真正的優雅重啟, 可以通過介面(由於線上環境發布機器可能沒有許可權,只能曲線救國)或者傳送訊號給worker程序,worker 傳送訊號給master, master程序收到訊號後起乙個新worker, 新worker啟動並正常提供服務後傳送乙個訊號給master,master傳送退出訊號給老worker,老worker退出.

日誌收集的問題, 如果專案本身日誌是直接打到檔案,可能會存在fd滾動等問題(目前沒有研究透徹). 目前的解決方案是專案log全部輸出到stdout由supervisor來收集到日誌檔案, 建立worker的時候stdout, stderr是可以繼承過去的,這就解決了日誌的問題, 如果有更好的方式環境一起**。

參考文章

nginx重啟 平滑重啟

進入 ngiinx sbin目錄下 nginx c usr local nginx conf nginx.conf c引數指定了要載入的nginx配置檔案路徑 停止操作 停止操作是通過向nginx程序傳送訊號來進行的 步驟1 查詢nginx主程序號 ps ef grep nginx在程序列表裡 面找...

nginx重啟 平滑重啟

進入 ngiinx sbin目錄下 nginx c usr local nginx conf nginx.conf c引數指定了要載入的nginx配置檔案路徑 停止操作 停止操作是通過向nginx程序傳送訊號來進行的 步驟1 查詢nginx主程序號 ps ef grep nginx 在程序列表裡 面...

mysql平滑重啟 nginx平滑重啟和公升級

平滑重啟 kill hup cat usr local www nginx logs nginx.pid 平滑公升級nginx 這步是要得到編譯引數 用上面這段編譯 然後make,千萬別make install make完了 在objs目錄下就多了個nginx,這個就是新版本的程式了 mv usr ...