golang http server重启过程中如何继续提供服务(优雅重启)

架构是这样的:
nginx做反向代理,将http请求proxy pass到后端的golang http server

 nginx==>httpserver

可否这样实现优雅重启
1.启动一个新的golang http server监听其他端口
2.修改nginx配置文件,将之前的代理端口改为新启动的server监听的端口
3.reload nginx
4.并行一段时间老的http server没有请求处理,则kill掉

整体实现优雅重启?这个是否可行,还有什么更好的方案?

阅读 3.4k
1 个回答

想到两个方法:

方法一:
如果是比较新的内核版本3.9以上,支持SO_REUSEPORT,那么你可以:

  1. 启动一个新的进程,也监听相同的端口。
  2. 新的进程启动后给老的进程发个信号。
  3. 老的进程收到后停止接收新的连接请求(停止Accept,关闭Listen Socket),
    等所有已经存在的连接处理完自动退出。

如果不支持SO_REUSEPORT,不同进程无法同时监听同一个端口,则需要在老的进程内fork一个子进程,并且把负责监听的文件描述符传给新进程。
这个方法可以实现你的需求,但需要比较多的修改Golang封装的net/http等系统库,技术复杂度比较高。
好处是不需要nginx参与,对它透明。

方法二:
可以同时运行两个或更多个http server,同时提供服务,让nginx做负载均衡,其中有一个需要升级重启时,就发个信号,收到信号后停止接收新请求,已有请求处理完毕正常退出就可以了。这个过程不需要修改nginx配置,也不需要reload nginx。
这个方法也需要改Golang封装的net/http,但修改量相比方法一会小很多。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题