熱升級如何不斷開舊連線

keepeye發表於2018-02-09

現在有一個 tcp 長連線伺服器,單機,想實現熱升級

網上有方法可以將 server 的 fd 檔案控制程式碼通過環境變數傳遞給新啟動的子程式。

但是有個問題,新程式啟動後,新連線沒問題,舊連線怎麼轉移?只能斷開重連嗎?

參考的這篇文章:

https://www.oschina.net/translate/graceful-server-restart-with-go

使用的這個現成的庫:

github.com/facebookgo/grace/gracenet

然後這是我的測試程式碼,老程式退出後客戶端就斷開連線了:

package main

import (
    "github.com/facebookgo/grace/gracenet"
    "os"
    "os/signal"
    "syscall"
    "fmt"
    "net"
    "time"
)

func main() {
    net := gracenet.Net{}
    l,err := net.Listen("tcp",":12345")
    if err != nil {
        panic(err)
    }
    go func() {
        for {
            conn,err := l.Accept()
            if err != nil {
                fmt.Println("accept 失敗",err)
                return
            }
            go handleConn(conn)
        }
    }()

    fmt.Println("程式啟動..")

    ch := make(chan os.Signal, 10)
    signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM, syscall.SIGUSR2)
    for {
        sig := <-ch
        switch sig {
        case syscall.SIGINT, syscall.SIGTERM:
            os.Exit(0)
        case syscall.SIGUSR2:
            //啟動新執行緒,超時關閉當前執行緒
            pid,err := net.StartProcess()
            if err != nil {
                fmt.Println("新程式啟動失敗",err)
                os.Exit(1)
            }
            fmt.Println("啟動新程式...,pid=",pid)
            //停止accept
            l.Close()
            time.Sleep(15*time.Second)
            fmt.Println("老程式退出")
            os.Exit(0)
        }
    }
}

func handleConn(conn net.Conn) {
    buf := make([]byte, 1024)
    fmt.Println("client connected")
    for {
        n,err := conn.Read(buf)
        if err != nil {
            fmt.Println("client disconnected")
            return
        }
        conn.Write(buf[0:n])
        conn.Write([]byte("ok"))
    }
}
更多原創文章乾貨分享,請關注公眾號
  • 熱升級如何不斷開舊連線
  • 加微信實戰群請加微信(註明:實戰群):gocnio

相關文章