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
)然後在程式的開始處:
varlistener
*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。然後我們啟動這個程...