更新Go Web应用程序的最佳实践

时间:2015-01-03 16:03:44

标签: go webserver updates

我想知道将更新部署到(MVC)Go Web应用程序的最佳做法是什么。想象一下以下场景:

1)为我的Go Web应用程序编写代码并测试一些更改

2)部署更新,目前没有任何人使用以前的版本被中断。

我不知道如何确保第2点可以被覆盖 - 当有人向服务器发送请求并且我在此刻重建/重启它时,他会收到错误 - 即使请求只使用我没有触摸的代码的一部分或者向后兼容的代码,或者我刚刚添加了一个新的Request-handler。

也许我错过了一些微不足道或众所周知的模式,因为我正处于学习过程中,而我之前的Web应用程序是ASP.NET或php应用程序,这些都没有问题,因为我做了不需要在代码更改时重新启动Web服务器。

1 个答案:

答案 0 :(得分:1)

Go不仅仅是一个问题,但总的来说我们可以将问题分成两个独立的问题:

  1. 确保当前请求不会被终止并影响用户体验。

  2. 确保没有无法处理新请求的停机时间。

  3. 第一个更容易解决:你只是不要猛烈地杀死你的服务器,而是告诉它退出,导致“Drain阶段”,它不接受新的请求,只完成当前正在运行的请求,并退出。这可以通过例如监听信号并将应用程序输入特殊状态来完成。

    使用Go并不简单,因为默认的http服务器不支持关闭它,但你可以启动一个net.Listener的服务器,然后保持对它的引用,当它到期时关闭它

    现在,只进行一次然后再次启动服务将导致在此过程中不接受新请求,并且我们都知道在极端情况下这可能需要几秒钟。

    所以我们需要的是已经使用新代码运行的服务器的另一个实例,即旧代码没有响应新请求的那一刻,对吧?这可以通过几种方式完成:

    1. 拥有多个服务器,并且在它们之上有一个负载均衡器,允许一个(或多个)服务器在我们重新启动另一个服务器时承担负载。这是最简单的方式,也是大多数人这样做的方式。如果您需要N台服务器来承担用户的负担,只需保留N + 1并一次重新启动一台。

    2. 使用套接字共享技巧。在较新的Linux内核中,许多进程可以在同一端口上侦听和接受。你所做的只是启动新实例,然后告诉旧实例完成并退出。这样就没有停顿了。这可以通过在侦听套接字上设置SO_REUSEPORT来完成。

    3. 上述内容可以通过随时发布的解决方案自动完成,例如Einhorn,它可以为您处理所有细节,请参阅https://github.com/stripe/einhorn

    4. 此博客文章中记录了另一种方法:http://blog.nella.org/?p=879