Tip #43 优雅关闭你的应用程序
当我们讨论优雅地关闭应用程序时,有几个关键保证是我们力求实现的:
- 不接收新请求:服务器停止接受新的请求。
- 完成正在进行的任务:等待当前处理的任务达到逻辑上的停止点。
- 资源清理:释放诸如数据库连接、打开文件、网络连接等资源。
虽然存在一些不同的实现方式,但为了简化起见,我尝试给出最简短的方法:
首先,我们创建一个(主)上下文,当接收到中断信号(Ctrl+C
)或SIGTERM
时将其取消。
接着我们创建两个goroutine,均由errgroup
协调(如果您还不了解它,请考虑阅读 https://blog.devtrovert.com/p/go-errgroup-you-havent-used-goroutines):
第一个直接启动服务器,但要记住,ListenAndServe
始终返回非空错误。
第二个更有趣,这是我们放置优雅清理代码的地方。这个goroutine等待gCtx.Done()
关闭,该关闭状态由我们的主ctx传播而来。
如果您的服务运行在Kubernetes上,应考虑在接收到SIGTERM后不立即终止新请求。
您的应用程序不应立即终止,而应完成所有活跃请求,并继续监听Pod关闭开始后到达的传入连接。
Kubernetes可能需要一段时间来更新所有kube-proxy和负载均衡器。
这是简化版,您可能需要考虑为服务器配置添加超时、检查错误是否关闭、为关闭过程添加超时等。