杜松子酒服务器优雅停止

问题描述 投票:0回答:2

我正在尝试使用传递给我的类的父上下文来实现一种干净的方式来优雅地停止我的杜松子酒服务器。 这是我当前的代码

有没有更干净的方法来做到这一点?感觉像是很多样板代码并且不必要,例如使用无限循环来完成如此简单的任务。

func (instance *MyListener) Listen(ctx context.Context) error {
    ctx, cancel := context.WithCancel(ctx)
    defer cancel()
    
    engine := gin.Default()
    engine.POST("/doStuff", func(c *gin.Context) {          
        instance.doStuff()
        c.Status(200)
    })

    instance.httpSrv = &http.Server {
        Addr:    ":8080",
        Handler: engine,
    }

    // Initializing the server in a goroutine so that
    // it won't block the graceful shutdown handling below
    go func() {
        if err := instance.httpSrv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
            logging.Log.Error("Could not start listener", zap.Error(err))
        }
    }()

    loop:
    for {
        select {
            case <- ctx.Done():
                break loop
            default:
                time.Sleep(1000)
        }
    }

    ctx, cancel = context.WithTimeout(ctx, 2 * time.Second)
    if err := instance.httpSrv.Shutdown(ctx); err != nil {
        logging.Log.Error("Server forced to shutdown:", err)
    }

    return nil
}
go webserver
2个回答
3
投票

这个:

loop:
for {
    select {
        case <- ctx.Done():
            break loop
        default:
            time.Sleep(1000)
    }
}

可以用这个代替:

<- ctx.Done()

而且它同样有效并且“更高效”。除此之外,您的解决方案看起来干净、清晰且正确。


0
投票

func (instance *MyListener) Listen(ctx context.Context) error { engine := gin.Default() engine.POST("/doStuff", func(c *gin.Context) { instance.doStuff() c.Status(200) }) instance.httpSrv = &http.Server { Addr: ":8080", Handler: engine, } ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM) defer stop() go func() { if err := instance.httpSrv.ListenAndServe(); err != nil && err != http.ErrServerClosed { logging.Log.Error("Could not start listener", zap.Error(err)) } }() <-ctx.Done() stop() log.Printf("Gracefully shutting down the server...\nPress CTRL + C again to force") ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) defer cancel() if err := instance.httpSrv.Shutdown(ctx); err != nil { logging.Log.Error("Server forced to shutdown:", err) } return nil }

这样它会非常有趣:

首次尝试关闭服务器后,它将等待给定的超时时间来正常关闭,如果请求花费的时间超过超时时间,服务器将强制关闭。
  1. 第二次尝试后,即使有未处理的请求,服务器也会立即强制停止
© www.soinside.com 2019 - 2024. All rights reserved.