使用 Go 語言實現優雅的伺服器重啟

2021-09-23 16:56:09 字數 2467 閱讀 9563

go被設計為一種後台語言,它通常也被用於後端程式中。服務端程式是go語言最常見的軟體產品。在這我要解決的問題是:如何乾淨利落地公升級正在執行的服務端程式。

image

在基於unix的作業系統中,signal(訊號)是與長時間執行的程序互動的常用方法.

如果收到sighup訊號,優雅地重啟程序需要以下幾個步驟:

伺服器要拒絕新的連線請求,但要保持已有的連線。

啟用新版本的程序

將socket「交給」新程序,新程序開始接受新連線請求

舊程序處理完畢後立即停止。

伺服器程式的共同點:持有乙個死迴圈來接受連線請求:

for

跳出這個迴圈的最簡單方式是在socket***上設定乙個超時,當呼叫listener.settimeout(time.now())後,listener.accept()會立即返回乙個timeout err,你可以捕獲並處理: 

for}}

注意這個操作與關閉listener有所不同。這樣程序仍在監聽伺服器端口,但連線請求會被作業系統的網路棧排隊,等待乙個程序接受它們。 

go提供了乙個原始型別forkexec來產生新程序.你可以與這個新程序共享某些訊息,例如檔案描述符或環境引數。

execspec :=&

syscall

.procattr,}

fork

,err

:=syscall

.forkexec(os

.args[0

],os

.args

,execspec

)[…]

你會發現這個程序使用完全相同的引數os.args啟動了乙個新程序。 

正如你先前看到的,你可以將檔案描述符傳遞到新程序,這需要一些unix魔法(一切都是檔案),我們可以把socket傳送到新程序中,這樣新程序就能夠使用它並接收及等待新的連線。

但fork-execed程序需要知道它必須從檔案中得到socket而不是新建乙個(有些興許已經在使用了,因為我們還沒斷開已有的監聽)。你可以按任何你希望的方法來,最常見的是通過環境變數或命令列標誌。

listenerfile

,err

:=listener

.file

()if

err

!=nil

listenerfd

:=listenerfile.fd

()// set a flag for the new process start processos.

setenv

("_graceful_restart"

,"true"

)execspec :=&

syscall

.procattr,}

// fork exec the new version of your server

fork

,err

:=syscall

.forkexec(os

.args[0

],os

.args

,execspec

)然後在程式的開始處:

var

listener

*net

.tcplistener

ifos

.getenv

("_graceful_restart")==

"true"

varbool

oklistener

,ok

=listener

.(*net

.tcplistener)if

!ok

}else

檔案描述沒有被隨機的選擇為3,這是因為uintptr的切片已經傳送了fork,監聽獲取了索引3。留意隱式宣告問題。

到此為止,就這樣,我們已經將其傳到另乙個正在正確執行的程序,對於舊伺服器的最後操作是等其連線關閉。由於標準庫里提供了sync.waitgroup結構體,用go實現這個功能很簡單。

每次接收乙個連線,在waitgroup上加1,然後,我們在它完成時將計數器減一:

for()}

至於等待連線的結束,你僅需要wg.wait(),因為沒有新的連線,我們等待wg.done()已經被所有正在執行的handler呼叫。

timeout

:=time

.newtimer

(time

.minute

)wait

:=make

(chan

struct

{})go func

(){}

}()select

這篇文章中的**片段都是從這個完整的示例中提取的:

socket傳遞配合forkexec使用確實是一種無干擾更新程序的有效方式,在最大時間上,新的連線會等待幾毫秒——用於服務的啟動和恢復socket,但這個時間很短。

go語言實現聊天伺服器 多人聊天)

用go語言實現乙個server作中轉 訊息,多個客戶端聊天 1 伺服器開啟,等待來自客戶端的連線,把每乙個客戶端儲存在map中 2 客戶端連線伺服器,給自己取乙個別名,儲存在伺服器 4 客戶端發訊息,伺服器解析協議,給每乙個客戶端 5 客戶端下線 server server project main...

服務計算 Go語言實現selpg

3.程式測試 4.參考資料 使用golang開發linux命令列中的selpg io,實現了一系列非平台相關的 io 相關介面和實現,比如提供了對 os 中系統相關的 io 功能的封裝。我們在進行流式讀寫 比如讀寫檔案 時,通常會用到該包。os exec,執行外部命令,它包裝了 os.startpr...

用go語言實現乙個簡單的web伺服器

我們這個簡單的web伺服器,主要用到的就是http包,啥也不說了,先上 顯而易見,這裡並沒有很多 非常的簡潔,原因就是好多任務作都由包裡的 去實現了,我們做的只是傳個引數而已。雖然 並不多,也簡單的說一下。簡單的 我簡單的說 功能主要為建立乙個web服務程序,監聽的埠為 8000。然後我們啟動這個程...