目前我们有以下设置。
- 硬件负载均衡器 (LB)
- 盒子 A 在 8080(TA)上运行 Tomcat
- 盒子 B 在 8080 (TB) 上运行 Tomcat
TA 和 TB 在 LB 后面跑动。
目前,将 Box A 或 Box B 从 LB 中取出以实现零停机部署是一项相当复杂且手动的工作。
我正在考虑做这样的事情:
- 硬件负载均衡器 (LB)
- 盒子 A 在 8080 上运行 Nginx(NA)
- 盒子 A 在 8081(TA1)上运行 Tomcat
- 盒子 A 在 8082(TA2)上运行 Tomcat
- 盒子 B 在 8080 上运行 Nginx(NB)
- 盒子 B 在 8081 上运行 Tomcat(TB1)
- 盒子 B 在 8082 上运行 Tomcat(TB2)
基本上,LB 现在将在 NA 和 NB 之间引导流量。在每个 Nginx 上,我们将 TA1、TA2 和 TB1、TB2 配置为上游服务器。一旦上游的健康检查页面之一无响应(关闭),流量就会转到另一个页面(Nginx 上的 HttpHealthcheckModule 模块)。
所以部署过程很简单。
假设 TA1 处于活动状态,应用程序版本为 0.1。TA1 上的健康检查正常。我们启动 TA2,其健康检查显示为 ERROR。因此 Nginx 未与其通信。我们将应用程序版本 0.2 部署到 TA2。确保它正常工作。现在,我们将 TA2 上的健康检查切换为 OK,将 TA1 上的健康检查切换为 ERROR。Nginx 将开始为 TA2 提供服务,并将 TA1 从轮换中移除。完成!现在对另一个框执行相同的操作。
虽然听起来很酷很棒,但我们如何“饿死” Nginx?假设我们有待处理的连接,一些用户在 TA1 上。如果我们关闭它,会话就会中断(我们有基于 cookie 的会话)。不好。有没有办法用 Nginx 饿死上游服务器之一的流量?
谢谢!
答案1
我的观点是,如果您愿意进行如此复杂的设置只是为了实现零停机时间,那么您应该花时间获得更好的负载平衡器。按照您建议的方式,您将牺牲简单性来换取边际成本节约,最终花费的成本总是超出您的预期。
您需要停机时间来实施您提出的零停机解决方案。利用停机时间来了解如何使用现有的负载平衡器,或将其替换为更好的负载平衡器。
答案2
我通过使用 HAProxy 作为负载均衡器并让其频繁检查“健康检查”html 页面,基本上实现了您的要求。在后端 Web 服务器上的 nginx 配置中,此页面实际上并不存在。在部署期间,我在后端服务器上创建了一个名为“offline.html”的文件。在 nginx 中,如果请求“check.html”时此文件存在,则它会提供该文件,否则它会提供真正的健康检查页面。
在部署期间,我触摸 offline.html 文件,等待几秒钟让负载均衡器踢出服务器,进行部署,然后删除该文件。
站点重新启动,负载平衡器将服务器重新添加到池中,一切都运行正常......
附注:如果可以的话,我会尝试消除对会话亲和性的依赖......
答案3
你不能在节点 A 和 B 上实现由复制的 redis 集群支持的 Spring Session 吗?
如果您随后将两个 nginx 实例配置为在所有 4 个 tomcat 实例上进行负载平衡,那么您可以随时关闭或崩溃任何 tomcat 服务器,而 nginx 将只使用下一个服务器来满足您的请求?这是假设节点 A 和 B 可以连接到所有 4 个 tomcat 实例。