GoFrame gproc-信號(hào)注冊(cè)監(jiān)聽(tīng)

2022-04-11 09:46 更新

基本介紹

?gproc?組件提供了統(tǒng)一的信號(hào)監(jiān)聽(tīng)和回調(diào)處理功能,目的是解決在程序中多個(gè)不同組件冗余的信號(hào)處理邏輯,以及接收退出信號(hào)后無(wú)法平滑析構(gòu)的痛點(diǎn)。在沒(méi)有統(tǒng)一退出信號(hào)監(jiān)聽(tīng)的組件下,當(dāng)多個(gè)組件通過(guò)?goroutine?異步監(jiān)聽(tīng)信號(hào),主?goroutine?接收到退出信號(hào)往往會(huì)直接退出,或者等待一段無(wú)法預(yù)測(cè)的時(shí)間退出,造成程序其實(shí)無(wú)法平滑退出,可能引起一些不可預(yù)料的問(wèn)題。?gproc?通過(guò)統(tǒng)一的信號(hào)注冊(cè)和回調(diào)處理,使得各個(gè)組件能夠有效地接收到退出信號(hào)并做相應(yīng)析構(gòu)處理,使得程序的信號(hào)處理邏輯更加嚴(yán)謹(jǐn)。

相關(guān)方法:

// AddSigHandler adds custom signal handler for custom one or more signals.
func AddSigHandler(handler SigHandler, signals ...os.Signal)

// AddSigHandlerShutdown adds custom signal handler for shutdown signals:
// syscall.SIGINT,
// syscall.SIGQUIT,
// syscall.SIGKILL,
// syscall.SIGTERM,
// syscall.SIGABRT.
func AddSigHandlerShutdown(handler ...SigHandler)

// Listen blocks and does signal listening and handling.
func Listen()

簡(jiǎn)要介紹:

  • ?AddSigHanlder?方法用于添加對(duì)指定信號(hào)的監(jiān)聽(tīng)和對(duì)應(yīng)回調(diào)函數(shù)注冊(cè)。
  • ?AddSigHandlerShutdown?方法用于添加對(duì)常見(jiàn)進(jìn)程退出信號(hào)的監(jiān)聽(tīng)和對(duì)應(yīng)回調(diào)函數(shù)注冊(cè)。
  • ?Listen?方法用于阻塞監(jiān)聽(tīng)信號(hào)并自動(dòng)執(zhí)行回調(diào)函數(shù)調(diào)用。

我們來(lái)看兩個(gè)示例。

示例1,使用標(biāo)準(zhǔn)庫(kù)信號(hào)監(jiān)聽(tīng)

package main

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

func signalHandlerForMQ() {
	var (
		sig          os.Signal
		receivedChan = make(chan os.Signal)
	)
	signal.Notify(
		receivedChan,
		syscall.SIGINT,
		syscall.SIGQUIT,
		syscall.SIGKILL,
		syscall.SIGTERM,
		syscall.SIGABRT,
	)
	for {
		sig = <-receivedChan
		fmt.Println("MQ is shutting down due to signal:", sig.String())
		time.Sleep(time.Second)
		fmt.Println("MQ is shut down smoothly")
		return
	}
}

func main() {
	fmt.Println("Process start, pid:", os.Getpid())
	go signalHandlerForMQ()

	var (
		sig          os.Signal
		receivedChan = make(chan os.Signal)
	)
	signal.Notify(
		receivedChan,
		syscall.SIGINT,
		syscall.SIGQUIT,
		syscall.SIGKILL,
		syscall.SIGTERM,
		syscall.SIGABRT,
	)
	for {
		sig = <-receivedChan
		fmt.Println("MainProcess is shutting down due to signal:", sig.String())
		return
	}
}

我們通過(guò)?go run?命令來(lái)執(zhí)行一下,隨后通過(guò)?Ctrl+C?快捷鍵退出(Mac用戶(hù)通過(guò)?Command+C?)。

$ go run signal_handler.go
Process start, pid: 21928
^CMainProcess is shutting down due to signal: interrupt
MQ is shutting down due to signal: interrupt

可以看到,好可惜,那個(gè)?MQ?的?goroutine?還沒(méi)完全退出進(jìn)程即被強(qiáng)行關(guān)閉。

示例2,使用gproc信號(hào)監(jiān)聽(tīng)

package main

import (
	"fmt"
	"github.com/gogf/gf/v2/os/gproc"
	"os"
	"time"
)

func signalHandlerForMQ(sig os.Signal) {
	fmt.Println("MQ is shutting down due to signal:", sig.String())
	time.Sleep(time.Second)
	fmt.Println("MQ is shut down smoothly")
}

func signalHandlerForMain(sig os.Signal) {
	fmt.Println("MainProcess is shutting down due to signal:", sig.String())
}

func main() {
	fmt.Println("Process start, pid:", os.Getpid())
	gproc.AddSigHandlerShutdown(
		signalHandlerForMQ,
		signalHandlerForMain,
	)
	gproc.Listen()
}

我們通過(guò)?go run?命令來(lái)執(zhí)行一下,隨后通過(guò)?Ctrl+C?快捷鍵退出(Mac用戶(hù)通過(guò)?Command+C?)。

$ go run signal_handler_gproc.go
Process start, pid: 22876
^CMQ is shutting down due to signal: interrupt
MainProcess is shutting down due to signal: interrupt
MQ is shut down smoothly

看到差別了吧,所有的信號(hào)監(jiān)聽(tīng)函數(shù)都正常結(jié)束后,隨后進(jìn)程退出。


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)