首頁  >  文章  >  後端開發  >  聊聊golang的優雅關閉方式

聊聊golang的優雅關閉方式

PHPz
PHPz原創
2023-04-27 09:11:061205瀏覽

在開發使用golang的時候,一般都會遇到需要關閉或停止運作的情況。例如,程式運行結束或出現異常,這時需要優雅地關閉。

優雅關閉可以讓程式停止運作的同時,能夠讓已經啟動的任務處理完畢,避免資料遺失和資源外洩等問題,也不會對客戶端造成不必要的損失。本文就討論一下golang的優雅關閉方式。

優雅關閉方法

在golang中,優雅關閉的實作不難,我們可以透過設定訊號量或channel的方式進行,具體的實作方法如下:

透過信號量實現

package main

import (
    "log"
    "os"
    "os/signal"
    "syscall"
    "time"
)

func main() {
    stop := make(chan os.Signal, 1)
    signal.Notify(stop, syscall.SIGINT, syscall.SIGTERM)

    log.Println("Starting...")

    go func() {
        <-stop
        log.Println("Stopping...")

        // 处理关闭逻辑
        time.Sleep(3 * time.Second)

        log.Println("Graceful shutdown finished")
        os.Exit(0)
    }()

    // 处理业务逻辑
    for {
        log.Println("Running...")
        time.Sleep(1 * time.Second)
    }
}

這段程式碼中透過make建立了一個類型為os.Signal,長度為1的訊號緩衝channel,然後透過signal套件中的Notify函數告訴作業系統,我們想要監聽的訊號是SIGINT和SIGTERM,這兩個訊號都可以代表程式的關閉請求。

接著,我們啟動了一個goroutine,監聽stop這個channel,一旦接受到SIGINT或SIGTERM訊號,就會觸發這個goroutine的執行。在執行過程中,我們處理關閉邏輯,這裡用了time.Sleep模擬了一個比較耗時的操作,以便更好的測試我們的程式是否正常結束。最後透過os.Exit函數通知作業系統程式關閉請求已經處理完畢了。

在主goroutine中,我們處理了業務邏輯,每秒鐘打印一次"Running...",這裡只是一個簡單的示例;通常情況下,我們在處理業務邏輯時,需要定時保存數據和釋放資源等。

透過channel實現

package main

import (
    "log"
    "os"
    "time"
)

func main() {
    done := make(chan bool)

    log.Println("Starting...")

    go func() {
        osSignals := make(chan os.Signal, 1)
        signal.Notify(osSignals, syscall.SIGINT, syscall.SIGTERM)

        select {
        case <-osSignals:
            log.Println("Stopping...")

            // 处理关闭逻辑
            time.Sleep(3 * time.Second)

            log.Println("Graceful shutdown finished")
            done <- true
        }
    }()

    // 处理业务逻辑
    for {
        log.Println("Running...")
        time.Sleep(1 * time.Second)
        select {
        case <-done:
            return // 正常退出
        default:
            continue
        }
    }
}

這段程式碼中,我們創建了一個bool類型的done變量,表示我們的程式是否已經完成,然後在主goroutine中處理業務邏輯,定時列印"Running...",並透過select函數監聽done。如果done變數被設為true,程式就結束執行,回到main函數中,完成程式退出工作。

在另外一個goroutine中,我們透過make建立了一個類型為os.Signal,長度為1的訊號緩衝channel,然後透過signal套件中的Notify函數告訴作業系統,我們想要監聽的訊號是SIGINT和SIGTERM。接下來,透過select函式監聽osSignals,如果接收到SIGINT或SIGTERM訊號,就會觸發特定操作。

程式監聽的訊號

在Linux系統中,一般有以下幾個訊號:

##訊號名稱訊號描述SIGINT終端機中斷字符,通常透過Control C 發出SIGTERM 終止訊號,通常用來請求程式自行停止執行SIGHUP掛起訊號,通常表示某個終端連線已經中斷,需要重新讀取設定檔等SIGUSR1-31自訂訊號SIGKILL殺死進程訊號,無法被捕捉或忽略,只能暴力殺死進程SIGSTOP停止進程訊號,無法被捕捉或忽略,只能暴力停止進程SIGCONT#SIGPIPE##管道破裂訊號,通常表示讀取數據時對方已經關閉了連線SIGALRM鬧鐘訊號,用來定時觸發某個動作子程序結束訊號通常情況下,我們只需要監聽SIGINT和SIGTERM訊號。 優雅關閉的作用
##繼續執行進程
##SIGCHLD

透過優雅關閉,我們可以避免因未能處理完畢的請求和操作而導致的資料遺失、資源洩漏等問題,對於長時間運行的程式和提供服務的應用程式尤其重要。特別是在分散式系統和微服務架構中,優雅關閉能夠有效保證系統穩定性和效能,如果沒有針對性的問題處理函數,程式在接到停止訊號後,可能會武斷的結束或觸發崩潰,給客戶端造成困惑甚至不必要的損失。

總結

透過本文,我們學習到如何使用golang的channel和os/signal套件進行優雅關閉,以及透過監聽訊號來完成優雅關閉的操作。在實際開發中,應用程式的正常關閉是一項非常重要的任務,透過優雅關閉能夠有效提高程式的穩定性,避免資源浪費和資料遺失等問題。

以上是聊聊golang的優雅關閉方式的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn