1 回答
TA贡献1816条经验 获得超6个赞
这不仅仅是 Go 的问题,但总的来说,我们可以将问题分为两个独立的问题:
确保当前请求不会被终止并影响用户体验。
确保没有无法处理新请求的停机时间。
第一个更容易解决:你只是不要猛烈地杀死你的服务器,而是告诉它退出,导致“排水阶段”,在这个阶段它不接受新请求,只完成当前正在运行的请求,然后退出。例如,这可以通过侦听信号并将应用程序进入特殊状态来完成。
Go 并不简单,因为默认的 http 服务器不支持关闭它,但是您可以使用 启动服务器net.Listener
,然后保留对它的引用并在时间到期时关闭它。
现在,只执行一种方法然后再次启动服务将导致在此过程中不接受新请求,我们都知道在极端情况下这可能需要几秒钟。
所以我们需要的是另一个已经运行新代码的服务器实例,在旧代码没有响应新请求的那一刻,对吧?这可以通过多种方式完成:
拥有多个服务器,并且在它们之上有一个负载平衡器,允许一个(或多个)服务器在我们重新启动另一台服务器时承担负载。这是最简单的方法,也是大多数人的做法。如果您需要 N 个服务器来承担您的用户的负载,只需保留 N+1 并一次重新启动一个。
使用套接字共享技巧。在较新的 Linux 内核中,许多进程可以在同一个端口上侦听和接受。您所做的只是启动新实例,然后告诉旧实例完成并退出。这样就没有停顿。这是通过设置
SO_REUSEPORT
侦听套接字来完成的。以上可以通过准备交付的解决方案自动化,例如 Einhorn,为您处理所有细节,请参阅https://github.com/stripe/einhorn
这篇博文中记录了另一种方法:http : //blog.nella.org/?p=879
- 1 回答
- 0 关注
- 259 浏览
添加回答
举报