生產環境的api服務我們都會部署在linux伺服器上,為了不受終端狀態的影響,啟動服務的時候會讓服務在後台執行。那麼如何讓服務在後台執行呢,目前有2種常見的方法。
表示忽略sighup
(結束通話)訊號,終端退出的時候所發起的結束通話訊號會被忽略。nohup
一般會結合&
引數執行程式,&
表示將程式設定為後台執行的程式。兩者結合就變成了啟動乙個不受終端狀態影響的後台服務。
nohup gin-ips >> gin-api.out 2>&1 &
守護程序是乙個在後台執行並且不受任何終端控制的程序。使用守護程序的好處是該程序永遠以後臺方式啟動,生命週期一般都是和系統的啟動關閉狀態保持一致。
守護程序和nohup
+&
啟動的後台程序區別並不大,都是脫離終端的。但在程序組、檔案掩碼、工作目錄、標準/錯誤輸出輸入等會有不同。對於gin-ips來說,用守護程序可以一鍵後台啟動,並將日誌輸出到指定檔案,非常方便。
1、建立子程序,停止父程序2、在子程序中建立新會話
3、改變工作目錄
4、重設檔案建立掩碼
5、重定向檔案描述符
/*
linux mac 下執行
守護程序是生存期長的一種程序。它們獨立於控制終端並且週期性的執行某種任務或等待處理某些發生的事件。
守護程序必須與其執行前的環境隔離開來。這些環境包括未關閉的檔案描述符、控制終端、會話和程序組、工作目錄以及檔案建立掩碼等。這些環境通常是守護程序從執行它的父程序(特別是shell)中繼承下來的。
本程式只fork一次子程序,fork第二次主要目的是防止程序再次開啟乙個控制終端(不是必要的)。因為開啟乙個控制終端的前台條件是該程序必須是會話組長,再fork一次,子程序id != sid(sid是程序父程序的sid),所以也無法開啟新的控制終端
*/package daemon
import (
"fmt"
"os"
"os/exec"
"syscall"
"time"
)func initprocess()
syscall.umask(0) // todo test
return
} fmt.println("go daemon!!!")
if err != nil
defer func() ()
cmd := exec.command(os.args[0], os.args[1:]...)
cmd.stdout = fp
cmd.stderr = fp
cmd.stdin = nil
cmd.sysprocattr = &syscall.sysprocattr // todo test
if err := cmd.start(); err != nil
_, _ = fp.writestring(fmt.sprintf(
"[pid] %d start at %s\n", cmd.process.pid, time.now().format("2006-01-02 15:04:05")))
os.exit(0)
}
func main()
建立守護程序之後,我們的程式已經能夠在後台正常跑通了,但這樣還有個問題,那就是在重啟服務時候怎麼保證服務不中斷?
例如nginx這種7*24小時接收請求的服務,在程式公升級、配置檔案更新、或者外掛程式載入的時候就需要重啟,為保證重啟過程不中斷服務,我們會使用平滑重啟
gin-api
服務作為協程啟動,做相應的處理並返回資料給客戶端;主程序負責監聽訊號,根據訊號進行關閉、重啟操作
1、主程序(原程序中的主程序)啟動協程處理http請求,主程序開始監聽終端訊號2、使用
kill -usr2 $pid
發起停止主程序的動作3、主程序接收到訊號量
12 (sigusr2)
後, 啟動新的子程序,子程序接管父程序的標準輸出、錯誤輸出和socket
描述符4、子程序同樣啟動協程處理請求,子程序中的主程序繼續監聽終端訊號
5、父程序中的主程序發起關閉協程的動作,該協程處理完所有請求後自動關閉(平滑關閉)
6、父程序中的主程序退出
由於gin
庫函式缺少上下文管理功能,所以我們需要使用http.server
來包裹gin
服務,支援對服務的平滑關閉功能
func (server *server) listen(graceful bool) error
// 判斷是否為 reload
// 重啟服務
server.logger.info("reload api server")
// 先啟動新服務
if err := server.reload(); err != nil
// 關閉舊服務
// 命令列啟動新程式
args := string
cmd := exec.command(os.args[0], args...)
cmd.stdout = os.stdout // 1
cmd.stderr = os.stderr // 2
cmd.extrafiles = *os.file // 3
if err := cmd.start(); err != nil
server.logger.infof("forked new pid %v: \n", cmd.process.pid)
return nil
}
守護程序和平滑重啟的功能在生產環境上經常被使用,但要注意的是只能執行在unix環境下。使用了這2個功能之後,程式在部署架構的時候就能發揮高可用的功能。
下一章,我們將介紹如何在生產環境部署服務。
Gin API系列 部署和監控(九)
本文是 gin api系列 的最後一篇文章,簡單介紹如何在生產環境的部署架構和監控手段。使用nginx加keepalived的方式搭建,可以達到高可用的效果,並可以橫向擴容 nginx負載均衡配置增加健康檢查機制,在停掉任何乙個gin ips服務後並不影響請求,所以可以逐漸替換公升級。使用zabbi...
守護執行緒和守護程序
守護程序隨著主程序的 的執行結束而結束 守護執行緒會在主線程結束之後等待其他子執行緒的結束才結束 如有其他子執行緒,沒有其他子執行緒就是主線程結束守護執行緒隨之結束 主程序在執行玩完自己的 後不會立即結束,而是等待子程序結束之後,子程序的資源 import time from threading i...
linux程序系列 6 守護程序與孤兒程序
守護程序是生存期長的一種程序,它們常常在系統引導裝入時啟動,系統關閉時終止。守護程序有如下幾個特點 1.所有的守護程序都是以超級使用者 使用者id為0的root使用者 的優先權執行 2.守護程序沒有控制終端,一直在後台執行 3.守護程序的父程序都是init程序 1號程序 什麼是孤兒程序呢?父程序結束...