美文网首页
Go语言HTTP服务生命周期

Go语言HTTP服务生命周期

作者: mklee | 来源:发表于2020-10-21 10:58 被阅读0次

    在 go 语言里启动一个 http 服务非常简单,只需要一行代码http.ListenAndServe()就可以搞定,这个方法会一直阻塞着直到进程关闭,如果这个时候来了些特殊的需求比如:

    • 监听服务启动
    • 手动关闭服务
    • 监听服务关闭

    在 go 中应该怎么实现呢?下面来一一举例。

    监听服务启动

    方法一(推荐)

    Listen步骤拆分出来,先监听端口,再绑定到server上,代码示例:

    l, _ := net.Listen("tcp", ":8080")
    // 服务启动成功,进行初始化
    doInit()
    // 绑定到server上
    http.Serve(l, nil)
    

    方法二

    通过一个协程去轮询监听服务启动状态,代码示例:

    go func() {
        for {
            if _, err := net.Dial("tcp", "127.0.0.1:8080"); err == nil {
                // 服务启动成功,进行初始化
                doInit()
                //退出协程
                break
            }
            // 每隔一秒检查一次服务是否启动成功
            time.Sleep(time.Second)
        }
    }()
    http.ListenAndServe(":8080", nil)
    

    手动关闭服务

    优雅关闭(推荐)

    http包中并没有暴露服务的关闭方法,通过http.ListenAndServe()方法启动的 http 服务默认帮我们创建了一个*http.Server对象,源码如下:

    func ListenAndServe(addr string, handler Handler) error {
        server := &Server{Addr: addr, Handler: handler}
        return server.ListenAndServe()
    }
    

    实际上在*http.Server中是有提供Shutdown方法的,所以我们只需要手动构造一个*http.Server对象,就可以进行优雅关闭了,代码示例:

    srv := &http.Server{Addr: ":8080"}
    go func(){
        // 10秒之后关闭服务
        time.Sleep(time.Second * 10)
        srv.Shutdown(context.TODO())
    }()
    // 启动服务
    srv.ListenAndServe()
    

    强制关闭

    强制关闭和上面步骤是一样的,只是调用的方法换成了srv.Close(),这会导致所有的请求立即中断,所以需要特别注意。

    监听服务关闭

    当我们手动将服务关闭之后,srv.ListenAndServe()方法就会立即返回,这里需要注意的是该方法会返回一个error,当然这个error是一个特殊的 error http.ErrServerClosed,帮助我们区分是否为正常的服务关闭,所以需要对它特殊处理下,代码示例:

    if err := server.ListenAndServe(); err != nil {
        // 服务关闭,进行处理
        doShutdown()
        if err != http.ErrServerClosed{
            // 异常宕机,打印错误信息
            log.Fatal(err)
        }
    }
    

    参考资料

    本文首发于我的博客:https://monkeywie.cn,欢迎收藏!不定期分享JAVAGolang前端dockerk8s等干货知识。

    相关文章

      网友评论

          本文标题:Go语言HTTP服务生命周期

          本文链接:https://www.haomeiwen.com/subject/oipsmktx.html