首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >优雅地关闭Gorilla服务器

优雅地关闭Gorilla服务器
EN

Stack Overflow用户
提问于 2017-04-26 10:39:47
回答 1查看 4.5K关注 0票数 2

我正在使用https://github.com/gorilla/mux中的大猩猩复用器库在go中构建一个服务器。问题是,当我使用Ctrl+C时,或者当有一个特定的API调用时,例如"/shutdown“时,我希望它能够优雅地关闭。

我已经知道,在Go 1.8中,优雅的关闭已经实现了。但如何与大猩猩复用器相结合呢?另外,如何将它与SIGINT信号相结合?

有人能教我怎么做吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-04-26 16:19:32

通道可以通过API调用(/shutdown)或中断信号(Ctrl+C)捕获关闭请求。

  1. http.Server嵌入自定义结构中,以便稍后调用http Server.Shutdown
  2. 添加通道字段(shutdownReq),用于从API调用/shutdown传递关闭请求
  3. gorilla/mux的路由器中注册http处理程序,包括gorilla/mux,然后将路由器分配给http.Server.Handler
  4. 寄存器os.Interrupt/syscall.SIGINT, syscall.SIGTERM处理程序
  5. 使用select通过API调用或interrupt信号捕获关闭请求
  6. 通过调用Server.Shutdown执行干净关闭

下面是示例代码:

代码语言:javascript
复制
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!")
}

备注:请注意与优雅关闭相关的本期

票数 9
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43631854

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档