14

我正在尝试为 Java 应用程序的零停机部署构建非常轻量级的解决方案。为了简单起见,假设我们有两台服务器。我的解决方案是使用:

  1. 在“前面”——一些负载平衡器(软件)——我在这里考虑HAProxy。

  2. 在“后面” - 两台服务器,都运行 Tomcat 和部署的应用程序。

当我们即将部署新版本时

  1. 我们使用 HAProxy 禁用其中一台服务器,因此只有一台服务器(我们称之为服务器 A,它正在运行旧版本)可用。

  2. 在其他服务器上部署新版本(我们称之为服务器 B),运行生产单元测试(如果我们有它们:-) 并使用 HAProxy 启用服务器 B,同时禁用服务器 A。

  3. 现在我们再次只有一台服务器处于活动状态(服务器 B,带有新版本)。在服务器 B 上部署新版本,然后重新启用它。

任何建议如何改进?自动化程度如何?

任何现成的解决方案还是我必须使用自己的自定义脚本?

谢谢!

4

5 回答 5

6

我从这篇文章中找到了一些关于零停机时间的有趣解决方案。我想在那篇文章中只强调几个解决方案。

1、A/B切换:(滚动升级+Fallback机制

我们应该有一组处于待机模式的节点。我们会将新版本部署到这些节点并立即将流量切换到它们。如果我们将旧节点保持在原始状态,我们也可以进行即时回滚。负载均衡器位于应用程序前面,并根据请求负责此切换。

缺点:如果您需要X 服务器来运行您的应用程序,那么使用这种方法需要2X 服务器。

2. 零停机

使用这种方法,我们不需要保留一组机器;相反,我们延迟了端口绑定。共享资源获取会延迟到应用程序启动。应用程序启动后切换端口,旧版本也保持运行(没有接入点),以便在需要时立即回滚。

3. 并行部署 – Apache Tomcat:(仅适用于 Web 应用程序)

Apache Tomcat 在其版本 7 中添加了并行部署功能。他们让应用程序的两个版本同时运行,并将最新版本作为默认值。

4.延迟端口绑定:

我们在这里建议的是能够在不绑定端口且基本上不启动连接器的情况下启动服务器。稍后,一个单独的命令将启动并绑定连接器。当版本 1 正在运行并且已经绑定时,可以部署该软件的版本 2。稍后启动版本 2 时,我们可以取消绑定版本 1 和绑定版本 2。使用这种方法,节点实际上仅离线几秒钟。

5.高级端口绑定:

通过打破神话:'<code>Address already in use',*旧进程和新进程都将绑定到同一个端口。ON 模式下的SO_REUSEPORT选项允许两个(或更多)进程绑定到同一个端口。一旦新进程绑定到端口,就杀死旧进程。

SO_REUSEPORT选项解决了两个问题:

  1. 应用程序版本切换之间的小故障:节点可以一直服务流量,有效地给我们零停机时间。

  2. 改进的调度:

在此处输入图像描述

总之:

通过结合后期绑定端口复用,我们可以有效地实现零停机。如果我们保留备用进程,我们也将能够进行即时回滚。

于 2015-12-23T12:33:56.190 回答
5

滚动升级确实是一个很好的解决方案,前提是您的负载均衡器支持此选项(服务器饥饿)。另一种解决方案是使用支持 OSGi 的应用程序服务器来热替换部分或整个应用程序。

我会推荐第一个。SpringSource 的 AMS 监督控制台可以关闭一个 tcServer 集群(类固醇上的自定义 tomcat),IIRC 自动进行滚动升级(但请查看文档)。

于 2010-12-16T15:10:48.653 回答
3

LiveRebel提供滚动重启的功能,提供 CLI API 和 Hudson/Jenkins 插件以实现自动化。

于 2012-05-05T18:35:06.580 回答
3

如果您可以容纳 OSGi 容器,请查看 OSGi 技术,因为它为 OSGi 包提供了良好的隔离和热部署。如果您使用的是 Spring 框架,则可以使用Spring OSGi

于 2010-12-16T15:12:57.633 回答
2

有一个easy-deploy可以完全使用 Docker 容器。

部署版本 1

easy-deploy -p 80:80 -v some/path:other/path my-image:1

要部署新版本,只需使用更新的标签名称运行命令

easy-deploy -p 80:80 -v some/path:other/path my-image:2

披露:我构建了这个工具。我构建它正是因为我找不到解决这个问题的简单方法。

于 2017-10-07T17:22:50.837 回答