主頁(yè) > 知識(shí)庫(kù) > golang 監(jiān)聽(tīng)服務(wù)的信號(hào),實(shí)現(xiàn)平滑啟動(dòng),linux信號(hào)說(shuō)明詳解

golang 監(jiān)聽(tīng)服務(wù)的信號(hào),實(shí)現(xiàn)平滑啟動(dòng),linux信號(hào)說(shuō)明詳解

熱門(mén)標(biāo)簽:評(píng)價(jià)高的400電話辦理 百度地圖標(biāo)注后傳給手機(jī) 外呼系統(tǒng)顯本地手機(jī)號(hào) 涿州代理外呼系統(tǒng) excel地圖標(biāo)注分布數(shù)據(jù) 壽光微信地圖標(biāo)注 外呼系統(tǒng)用什么卡 電話機(jī)器人軟件免費(fèi) 阿克蘇地圖標(biāo)注

監(jiān)聽(tīng)服務(wù)的信號(hào),實(shí)現(xiàn)平滑啟動(dòng),linux信號(hào)說(shuō)明

package main 
import (
	"context"
	"fmt"
	"golang.org/x/sync/errgroup"
	"net/http"
	"os"
	"os/signal"
	"syscall"
) 
 
func main() { 
	g, ctx := errgroup.WithContext(context.Background())
	fmt.Println("服務(wù)啟動(dòng)start!")
	addr := ":9091"
	s :=http.Server{
		Addr: addr,
		Handler:http.DefaultServeMux,
	}
	g.Go(func() error {
		http.HandleFunc("/test1", func(writer http.ResponseWriter, request *http.Request) {
			fmt.Println("tes1")
			writer.Write([]byte("tes1"))
		})
		return s.ListenAndServe()
	})
	g.Go(func() error {
		exit := make(chan os.Signal)
		//監(jiān)聽(tīng) Ctrl+C 信號(hào)
		signal.Notify(exit, syscall.SIGINT, syscall.SIGTERM)
		select {
		case -exit:
			fmt.Println("進(jìn)程已被取消~")
			return s.Shutdown(ctx)
		}
	})
	err := g.Wait()
	if err != nil {
		fmt.Println(err)
	}
	fmt.Println("服務(wù)啟動(dòng)成功!")
	if ctx.Err() !=nil {
		fmt.Println(ctx.Err())
		fmt.Println("服務(wù)關(guān)閉成功!")
		os.Exit(0)
	}
 
}

補(bǔ)充:golang http服務(wù)實(shí)現(xiàn)平滑重啟

看代碼吧~

package main 
import (
    "context"
    "encoding/json"
    "fmt"
    "math/rand"
    "net/http"
    "os"
    "os/signal"
    "time"
)
 
var logChan  = make(chan map[string]interface{}) 
var requestStatusMap = map[int]bool{}  
var done = make(chan bool, 1)
var quit = make(chan os.Signal, 1) 
 
//為什么這樣可以平滑重啟?
// 正常情況下是server.ListenAndServe() 這個(gè)位置hang住整個(gè)進(jìn)程的
// 可以把這個(gè)程序看成兩部分,1個(gè)是web服務(wù)的監(jiān)聽(tīng)部分,一個(gè)是處理部分, 如果web服務(wù)器不開(kāi)啟了,那么就不能處理新進(jìn)來(lái)的請(qǐng)求了(可以理解為一個(gè)帶路的)
// 真正讓這個(gè)請(qǐng)求斷掉  是因?yàn)橹鬟M(jìn)程(main)被kill
// 所以平滑重啟的原理就是,先kill掉web服務(wù)器,不讓新的請(qǐng)求進(jìn)來(lái),等現(xiàn)有的全部請(qǐng)求完了,然后結(jié)束當(dāng)前進(jìn)程
func main() {
    server := newServer()
    signal.Notify(quit, os.Interrupt)
    go monitorKill(server, quit)
    server.ListenAndServe()
    -done
} 
 
func newServer() *http.Server {
    router := http.NewServeMux()
    router.HandleFunc("/hello", sayHello)
    return http.Server{
        Addr:         ":8262",
        Handler:      router,
    }
}
 
func monitorKill(server *http.Server, quit -chan os.Signal)  {
    -quit
    go shutDown(server)
    for {
        if len(requestStatusMap) != 0 {
            fmt.Println("目前還有進(jìn)行中的請(qǐng)求,請(qǐng)稍等")
            time.Sleep(time.Second * 1)
            continue
        } else {
            close(done)
            break
        }
    }
}
 
func shutDown(server *http.Server) {
    if err := server.Shutdown(context.Background()); err != nil {
        fmt.Println(err)
    }
}
 
func sayHello(w http.ResponseWriter, r *http.Request) {
    go WriteInfo()//請(qǐng)求寫(xiě)日志
    var uniqueId = GenerateRangeNum(1, 1000)
    requestStatusMap[uniqueId] = false
    url := r.URL.Path
    query  := r.URL.RawQuery
    method := r.Method
    a := map[string] interface{}{
        "url" : url,
        "method" : method,
        "query" : query,
        "response": "hello world!",
    }
    logChan-a
    w.Write([]byte("hello world!"))
    time.Sleep(time.Second * 10)
    delete(requestStatusMap, uniqueId)
}
 
func WriteInfo() {
    info := -logChan
    fileName := "/tmp/weekhomework.log"
    _, err := os.Stat(fileName)
    if err != nil || os.IsNotExist(err) {
        _, _ = os.Create(fileName)
    }
    f,err := os.OpenFile(fileName, os.O_WRONLY, 0644)
    defer f.Close()
    if err !=nil {
        fmt.Println(err.Error())
    } else {
        //追加寫(xiě)入   為什么O_APPEND 模式無(wú)法寫(xiě)入? todo
        n, _ := f.Seek(0, 2)
        infostr, _ := json.Marshal(info)
        _,err=f.WriteAt([]byte(string(infostr) +"\n"), n)
    }
}
 
func GenerateRangeNum(min int, max int) int {
    if min == max {
        return min
    }
    rand.Seed(time.Now().Unix())
    randNum := rand.Intn(max-min) + min
    return randNum
}

主要思路:

對(duì)于每個(gè)請(qǐng)求都做記錄,處理完成之后做刪除。 用一個(gè)協(xié)程去監(jiān)控中斷信號(hào),有中斷信號(hào)先把http服務(wù)關(guān)閉。

如果這個(gè)時(shí)候還有請(qǐng)求沒(méi)有處理完,那么就輪訓(xùn)等待,等全部處理完那么就 發(fā)出終止信號(hào)結(jié)束main進(jìn)程的執(zhí)行

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教。

您可能感興趣的文章:
  • Linux進(jìn)程間通信--使用信號(hào)
  • 詳解Linux進(jìn)程間通信——使用信號(hào)量
  • 詳解Linux多線程使用信號(hào)量同步
  • Linux下的信號(hào)詳解及捕捉信號(hào)
  • linux下基于C語(yǔ)言的信號(hào)編程實(shí)例
  • Linux線程同步之信號(hào)C語(yǔ)言實(shí)例
  • linux多線程編程詳解教程(線程通過(guò)信號(hào)量實(shí)現(xiàn)通信代碼)
  • Linux下semop等待信號(hào)時(shí)出現(xiàn)Interrupted System Call錯(cuò)誤(EINTR)解決方法
  • 淺談Linux信號(hào)機(jī)制

標(biāo)簽:重慶 梅河口 汕頭 欽州 銅川 雞西 吐魯番 蘭州

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《golang 監(jiān)聽(tīng)服務(wù)的信號(hào),實(shí)現(xiàn)平滑啟動(dòng),linux信號(hào)說(shuō)明詳解》,本文關(guān)鍵詞  golang,監(jiān)聽(tīng),服務(wù),的,信號(hào),;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問(wèn)題,煩請(qǐng)?zhí)峁┫嚓P(guān)信息告之我們,我們將及時(shí)溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無(wú)關(guān)。
  • 相關(guān)文章
  • 下面列出與本文章《golang 監(jiān)聽(tīng)服務(wù)的信號(hào),實(shí)現(xiàn)平滑啟動(dòng),linux信號(hào)說(shuō)明詳解》相關(guān)的同類(lèi)信息!
  • 本頁(yè)收集關(guān)于golang 監(jiān)聽(tīng)服務(wù)的信號(hào),實(shí)現(xiàn)平滑啟動(dòng),linux信號(hào)說(shuō)明詳解的相關(guān)信息資訊供網(wǎng)民參考!
  • 推薦文章