2017-04-26 7 views
0

私は、https://github.com/gorilla/muxにあるゴリラマルチプレクサライブラリを使用してgoでサーバを構築しています。 問題は、Ctrl + Cを使用しているとき、または特定のAPI呼び出し(たとえば「/ shutdown」)があるときに正常にシャットダウンすることです。正常にシャットダウンするゴリラサーバ

Go 1.8では、正常なシャットダウンが既に実装されていることはすでに知っています。しかし、それをゴリラ・マルチプレクサと組み合わせる方法は?また、SIGINTシグナルと組み合わせる方法は?

どのようにすればいいのですか?

答えて

4

チャネルは、API呼び出し(/shutdown)または割り込み信号(Ctrl+C)によってシャットダウン要求を取得するために使用できます。

カスタム構造体への
  1. 埋め込みhttp.Serverので、我々は、APIの呼び出しからgorilla/muxのルータで/shutdown含む/shutdown
  2. 登録のHTTPハンドラをシャットダウン要求を通すためのチャネルフィールド(shutdownReq)を追加し、後で
  3. http Server.Shutdownを呼び出すことができますその後、SHUTDをキャプチャするhttp.Server.Handler
  4. 登録os.Interrupt/syscall.SIGINT, syscall.SIGTERMハンドラ
  5. 使用selectにルータを割り当てます

    package main 
    
    import (
        "context" 
        "log" 
        "net/http" 
        "sync/atomic" 
        "syscall" 
        "time" 
    
        "os" 
        "os/signal" 
    
        "github.com/gorilla/mux" 
    ) 
    
    type myServer struct { 
        http.Server 
        shutdownReq chan bool 
        reqCount uint32 
    } 
    
    func NewServer() *myServer { 
        //create server 
        s := &myServer{ 
         Server: http.Server{ 
          Addr:   ":8080", 
          ReadTimeout: 10 * time.Second, 
          WriteTimeout: 10 * time.Second, 
         }, 
         shutdownReq: make(chan bool), 
        } 
    
        router := mux.NewRouter() 
    
        //register handlers 
        router.HandleFunc("/", s.RootHandler) 
        router.HandleFunc("/shutdown", s.ShutdownHandler) 
    
        //set http server handler 
        s.Handler = router 
    
        return s 
    } 
    
    func (s *myServer) WaitShutdown() { 
        irqSig := make(chan os.Signal, 1) 
        signal.Notify(irqSig, syscall.SIGINT, syscall.SIGTERM) 
    
        //Wait interrupt or shutdown request through /shutdown 
        select { 
        case sig := <-irqSig: 
         log.Printf("Shutdown request (signal: %v)", sig) 
        case sig := <-s.shutdownReq: 
         log.Printf("Shutdown request (/shutdown %v)", sig) 
        } 
    
        log.Printf("Stoping http server ...") 
    
        //Create shutdown context with 10 second timeout 
        ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) 
        defer cancel() 
    
        //shutdown the server 
        err := s.Shutdown(ctx) 
        if err != nil { 
         log.Printf("Shutdown request error: %v", err) 
        } 
    } 
    
    func (s *myServer) RootHandler(w http.ResponseWriter, r *http.Request) { 
        w.Write([]byte("Hello Gorilla MUX!\n")) 
    } 
    
    func (s *myServer) ShutdownHandler(w http.ResponseWriter, r *http.Request) { 
        w.Write([]byte("Shutdown server")) 
    
        //Do nothing if shutdown request already issued 
        //if s.reqCount == 0 then set to 1, return true otherwise false 
        if !atomic.CompareAndSwapUint32(&s.reqCount, 0, 1) { 
         log.Printf("Shutdown through API call in progress...") 
         return 
        } 
    
        go func() { 
         s.shutdownReq <- true 
        }() 
    } 
    
    func main() { 
        //Start the server 
        server := NewServer() 
    
        done := make(chan bool) 
        go func() { 
         err := server.ListenAndServe() 
         if err != nil { 
          log.Printf("Listen and serve: %v", err) 
         } 
         done <- true 
        }() 
    
        //wait shutdown 
        server.WaitShutdown() 
    
        <-done 
        log.Printf("DONE!") 
    } 
    

    :API呼び出しまたはinterrupt信号を通して自身の要求が

  6. Server.Shutdown

を呼び出すことにより、クリーンシャットダウンを実行以下のコード例でシャットダウンをgracefullに関連するthis issueを見てください。

関連する問題