欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

使用golang如何優(yōu)雅的關(guān)機(jī)或重啟操作示例

 更新時(shí)間:2022年04月16日 12:23:38   作者:Jeff的技術(shù)棧  
這篇文章主要為大家介紹了使用golang如何優(yōu)雅的關(guān)機(jī)或重啟操作示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪

前言

我們編寫的Web項(xiàng)目部署之后,經(jīng)常會(huì)因?yàn)樾枰M(jìn)行配置變更或功能迭代而重啟服務(wù),單純的kill -9 pid的方式會(huì)強(qiáng)制關(guān)閉進(jìn)程,這樣就會(huì)導(dǎo)致服務(wù)端當(dāng)前正在處理的請(qǐng)求失敗,那有沒有更優(yōu)雅的方式來實(shí)現(xiàn)關(guān)機(jī)或重啟呢?

閱讀本文需要了解一些UNIX系統(tǒng)中信號(hào)的概念,請(qǐng)?zhí)崆安殚嗁Y料預(yù)習(xí)。

優(yōu)雅地關(guān)機(jī)

什么是優(yōu)雅關(guān)機(jī)?

優(yōu)雅關(guān)機(jī)就是服務(wù)端關(guān)機(jī)命令發(fā)出后不是立即關(guān)機(jī),而是等待當(dāng)前還在處理的請(qǐng)求全部處理完畢后再退出程序,是一種對(duì)客戶端友好的關(guān)機(jī)方式。而執(zhí)行Ctrl+C關(guān)閉服務(wù)端時(shí),會(huì)強(qiáng)制結(jié)束進(jìn)程導(dǎo)致正在訪問的請(qǐng)求出現(xiàn)問題。

如何實(shí)現(xiàn)優(yōu)雅關(guān)機(jī)?

Go 1.8版本之后, http.Server 內(nèi)置的 Shutdown() 方法就支持優(yōu)雅地關(guān)機(jī),具體示例如下:

// +build go1.8
package main
import (
	"context"
	"log"
	"net/http"
	"os"
	"os/signal"
	"syscall"
	"time"
	"github.com/gin-gonic/gin"
)
func main() {
	router := gin.Default()
	router.GET("/", func(c *gin.Context) {
		time.Sleep(5 * time.Second)
		c.String(http.StatusOK, "Welcome Gin Server")
	})
	srv := &http.Server{
		Addr:    ":8080",
		Handler: router,
	}
	go func() {
		// 開啟一個(gè)goroutine啟動(dòng)服務(wù)
		if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
			log.Fatalf("listen: %s\n", err)
		}
	}()
	// 等待中斷信號(hào)來優(yōu)雅地關(guān)閉服務(wù)器,為關(guān)閉服務(wù)器操作設(shè)置一個(gè)5秒的超時(shí)
	quit := make(chan os.Signal, 1) // 創(chuàng)建一個(gè)接收信號(hào)的通道
	// kill 默認(rèn)會(huì)發(fā)送 syscall.SIGTERM 信號(hào)
	// kill -2 發(fā)送 syscall.SIGINT 信號(hào),我們常用的Ctrl+C就是觸發(fā)系統(tǒng)SIGINT信號(hào)
	// kill -9 發(fā)送 syscall.SIGKILL 信號(hào),但是不能被捕獲,所以不需要添加它
	// signal.Notify把收到的 syscall.SIGINT或syscall.SIGTERM 信號(hào)轉(zhuǎn)發(fā)給quit
	signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)  // 此處不會(huì)阻塞
	<-quit  // 阻塞在此,當(dāng)接收到上述兩種信號(hào)時(shí)才會(huì)往下執(zhí)行
	log.Println("Shutdown Server ...")
	// 創(chuàng)建一個(gè)5秒超時(shí)的context
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()
	// 5秒內(nèi)優(yōu)雅關(guān)閉服務(wù)(將未處理完的請(qǐng)求處理完再關(guān)閉服務(wù)),超過5秒就超時(shí)退出
	if err := srv.Shutdown(ctx); err != nil {
		log.Fatal("Server Shutdown: ", err)
	}
	log.Println("Server exiting")
}

如何驗(yàn)證優(yōu)雅關(guān)機(jī)的效果呢?

上面的代碼運(yùn)行后會(huì)在本地的8080端口開啟一個(gè)web服務(wù),它只注冊(cè)了一條路由/,后端服務(wù)會(huì)先sleep 5秒鐘然后才返回響應(yīng)信息。

我們按下Ctrl+C時(shí)會(huì)發(fā)送syscall.SIGINT來通知程序優(yōu)雅關(guān)機(jī),具體做法如下:

  • 打開終端,編譯并執(zhí)行上面的代碼
  • 打開一個(gè)瀏覽器,訪問127.0.0.1:8080/,此時(shí)瀏覽器白屏等待服務(wù)端返回響應(yīng)。
  • 在終端迅速執(zhí)行Ctrl+C命令給程序發(fā)送syscall.SIGINT信號(hào)
  • 此時(shí)程序并不立即退出而是等我們第2步的響應(yīng)返回之后再退出,從而實(shí)現(xiàn)優(yōu)雅關(guān)機(jī)。

優(yōu)雅地重啟

優(yōu)雅關(guān)機(jī)實(shí)現(xiàn)了,那么該如何實(shí)現(xiàn)優(yōu)雅重啟呢?

我們可以使用 fvbock/endless 來替換默認(rèn)的 ListenAndServe啟動(dòng)服務(wù)來實(shí)現(xiàn), 示例代碼如下:

package main
import (
	"log"
	"net/http"
	"time"

	"github.com/fvbock/endless"
	"github.com/gin-gonic/gin"
)
func main() {
	router := gin.Default()
	router.GET("/", func(c *gin.Context) {
		time.Sleep(5 * time.Second)
		c.String(http.StatusOK, "hello gin!")
	})
	// 默認(rèn)endless服務(wù)器會(huì)監(jiān)聽下列信號(hào):
	// syscall.SIGHUP,syscall.SIGUSR1,syscall.SIGUSR2,syscall.SIGINT,syscall.SIGTERM和syscall.SIGTSTP
	// 接收到 SIGHUP 信號(hào)將觸發(fā)`fork/restart` 實(shí)現(xiàn)優(yōu)雅重啟(kill -1 pid會(huì)發(fā)送SIGHUP信號(hào))
	// 接收到 syscall.SIGINT或syscall.SIGTERM 信號(hào)將觸發(fā)優(yōu)雅關(guān)機(jī)
	// 接收到 SIGUSR2 信號(hào)將觸發(fā)HammerTime
	// SIGUSR1 和 SIGTSTP 被用來觸發(fā)一些用戶自定義的hook函數(shù)
	if err := endless.ListenAndServe(":8080", router); err!=nil{
		log.Fatalf("listen: %s\n", err)
	}
	log.Println("Server exiting")
}

如何驗(yàn)證優(yōu)雅重啟的效果呢?

我們通過執(zhí)行kill -1 pid命令發(fā)送syscall.SIGINT來通知程序優(yōu)雅重啟,具體做法如下:

  • 打開終端,go build -o graceful_restart編譯并執(zhí)行./graceful_restart,終端輸出當(dāng)前pid(假設(shè)為43682)
  • 將代碼中處理請(qǐng)求函數(shù)返回的hello gin!修改為hello q1mi!,再次編譯go build -o graceful_restart
  • 打開一個(gè)瀏覽器,訪問127.0.0.1:8080/,此時(shí)瀏覽器白屏等待服務(wù)端返回響應(yīng)。
  • 在終端迅速執(zhí)行kill -1 43682命令給程序發(fā)送syscall.SIGHUP信號(hào)
  • 等第3步瀏覽器收到響應(yīng)信息hello gin!后再次訪問127.0.0.1:8080/會(huì)收到hello q1mi!的響應(yīng)。
  • 在不影響當(dāng)前未處理完請(qǐng)求的同時(shí)完成了程序代碼的替換,實(shí)現(xiàn)了優(yōu)雅重啟。

但是需要注意的是,此時(shí)程序的PID變化了,因?yàn)?code>endless 是通過fork子進(jìn)程處理新請(qǐng)求,待原進(jìn)程處理完當(dāng)前請(qǐng)求后再退出的方式實(shí)現(xiàn)優(yōu)雅重啟的。所以當(dāng)你的項(xiàng)目是使用類似supervisor的軟件管理進(jìn)程時(shí)就不適用這種方式了。

總結(jié)

無論是優(yōu)雅關(guān)機(jī)還是優(yōu)雅重啟歸根結(jié)底都是通過監(jiān)聽特定系統(tǒng)信號(hào),然后執(zhí)行一定的邏輯處理保障當(dāng)前系統(tǒng)正在處理的請(qǐng)求被正常處理后再關(guān)閉當(dāng)前進(jìn)程。使用優(yōu)雅關(guān)機(jī)還是使用優(yōu)雅重啟以及怎么實(shí)現(xiàn),這就需要根據(jù)項(xiàng)目實(shí)際情況來決定了。

以上就是使用golang如何優(yōu)雅的關(guān)機(jī)或重啟 的詳細(xì)內(nèi)容,更多關(guān)于golang關(guān)機(jī)重啟 的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 深入理解Golang中WebSocket和WSS的支持

    深入理解Golang中WebSocket和WSS的支持

    本文主要介紹了深入理解Golang中WebSocket和WSS的支持,實(shí)現(xiàn)了Golang構(gòu)建WebSocket服務(wù)器和客戶端,并使用自簽名證書實(shí)現(xiàn)WSS的功能,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-03-03
  • Go開源項(xiàng)目分布式唯一ID生成系統(tǒng)

    Go開源項(xiàng)目分布式唯一ID生成系統(tǒng)

    這篇文章主要為大家介紹了Go開源項(xiàng)目分布式唯一ID生成系統(tǒng)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-06-06
  • Go使用Weighted實(shí)現(xiàn)資源管理

    Go使用Weighted實(shí)現(xiàn)資源管理

    這篇文章主要介紹了Go?語言中的?Weighted?并發(fā)原語,包括?Weighted?的基本使用方法、實(shí)現(xiàn)原理、使用注意事項(xiàng)等內(nèi)容,感興趣的小伙伴可以了解一下
    2023-06-06
  • Golang Printf,Sprintf,Fprintf 格式化詳解

    Golang Printf,Sprintf,Fprintf 格式化詳解

    這篇文章主要介紹了Golang Printf,Sprintf,Fprintf 格式化詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2021-03-03
  • Go調(diào)用opencv實(shí)現(xiàn)圖片矯正的代碼示例

    Go調(diào)用opencv實(shí)現(xiàn)圖片矯正的代碼示例

    這篇文章主要為大家詳細(xì)介紹了Go調(diào)用opencv實(shí)現(xiàn)圖片矯正的代碼示例,文中的示例代碼簡(jiǎn)潔易懂,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-09-09
  • Golang使用http協(xié)議實(shí)現(xiàn)心跳檢測(cè)程序過程詳解

    Golang使用http協(xié)議實(shí)現(xiàn)心跳檢測(cè)程序過程詳解

    這篇文章主要介紹了Golang使用http協(xié)議實(shí)現(xiàn)心跳檢測(cè)程序過程,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧
    2023-03-03
  • go 讀取BMP文件頭二進(jìn)制讀取方式

    go 讀取BMP文件頭二進(jìn)制讀取方式

    這篇文章主要介紹了go 讀取BMP文件頭二進(jìn)制讀取方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • Go語言中make和new函數(shù)的用法與區(qū)別

    Go語言中make和new函數(shù)的用法與區(qū)別

    這篇文章介紹了Go語言中make和new函數(shù)的用法與區(qū)別,文中通過示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-07-07
  • golang 調(diào)用c語言動(dòng)態(tài)庫(kù)方式實(shí)現(xiàn)

    golang 調(diào)用c語言動(dòng)態(tài)庫(kù)方式實(shí)現(xiàn)

    本文主要介紹了golang 調(diào)用c語言動(dòng)態(tài)庫(kù)方式實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-12-12
  • go語言開發(fā)中如何優(yōu)雅得關(guān)閉協(xié)程方法

    go語言開發(fā)中如何優(yōu)雅得關(guān)閉協(xié)程方法

    這篇文章主要為大家介紹了go語言開發(fā)中如何優(yōu)雅得關(guān)閉協(xié)程方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-05-05

最新評(píng)論