当部署了大量的Java web应用(> 100 MB的.war)我目前使用下面的部署过程:
- 该应用程序的.war文件在开发计算机上本地展开。
- 扩展应用的rsync:从开发机版的实际环境。
- 在实际环境中的应用程序服务器rsync的重启。 这一步并不是必需的,但我发现,重新启动上部署应用服务器避免“java.lang.OutOfMemoryError:PermGen的空间”由于频繁的类加载。
对这种做法好东西:
- rsync的减少从开发机发送实时环境的数据量。 上传整个.war文件需要用10分钟时间,而一个rsync的需要几秒钟。
对这种做法不好的事情:
- 虽然rsync的运行应用程序上下文重新启动,因为文件被更新。 理想情况下,重启应该发生rsync的完成之后,而不是在它仍在运行。
- 该应用程序服务器重启导致大约两分钟的停工时间。
我想找到一个部署过程具有以下属性:
- 在部署过程中最少的停机时间。
- 最少花费的时间将数据上传。
- 如果部署过程是具体的应用服务器,然后应用程序服务器必须是开放源代码。
题:
Answer 1:
据指出,推动变为WAR文件时的rsync不能很好地工作。 这样做的原因是,WAR文件基本上是zip文件,并默认与压缩成员创建的文件。 小的变化对成员文件(压缩前)的结果在ZIP文件大规模的差异,呈现的rsync的增量传输算法无效。
一个可能的解决方案是使用jar -0 ...
创建原始WAR文件。 该-0
选项告诉jar
命令创建WAR文件时不压缩成员文件。 然后,当rsync
比较WAR文件的新版本和旧版本,增量转移算法应该能够创建小的diff。 然后安排该rsync的发送压缩形式的diff文件(或原始文件); 如用rsync -z ...
或压缩数据流/下运输。
编辑:根据WAR文件是如何构成的,它也可能需要使用jar -0 ...
创建组件JAR文件。 这将适用于JAR是经常会改变的(或者说只是重建)的文件,而不是稳定的第三方JAR文件。
从理论上讲,这个程序应在定期发送邮件WAR文件显著的改善。 在实践中我没有试过,所以我不能保证它会成功。
缺点是,部署的WAR文件将是显著更大。 这可能会导致更长的web应用程序的启动时间,但我怀疑其效果将是有限的。
一种不同的方法完全是看你的WAR文件,看看是否可以识别库JAR有可能(几乎)永远不会改变。 采取这些JAR出WAR文件,并单独部署他们到Tomcat服务器的common/lib
目录下; 例如利用rsync
。
Answer 2:
更新:
由于这个答案是第一次写,更好的方法来war文件零停机时间部署到Tomcat已经出现。 在最新版的Tomcat的您可以在你的战争文件名的版本号。 因此,例如,您可以部署文件ROOT##001.war
和ROOT##002.war
同时以相同的上下文。 在之后的所有##
由上下文路径的tomcat的,而不是部分解释为版本号。 Tomcat将让您的应用程序运行的所有版本和新服务请求和会话到完全处于正常的同时完成他们开始与旧版本的请求和会话的最新版本。 指定版本号也可以通过Tomcat的经理,甚至卡塔利娜Ant任务来完成。 更多信息这里 。
原来的答案:
Rsync的往往是在压缩文件上无效的,因为它是增量转移算法会在文件中的更改和变化小的未压缩的文件,可以极大地改变所产生的压缩版本。 出于这个原因,它可能使良好的意识,rsync的未压缩的战争文件,而不是压缩版本,如果网络带宽被证明是一个瓶颈。
什么是错误使用Tomcat管理应用程序做你的部署? 如果你不想直接从远程位置上传整个战争文件到Tomcat管理应用程序,你可以rsync的它(未压缩上面提到的原因),对生产框中占位符的位置,它重新包装的战争,然后把它交给经理在本地。 目前存在让你的脚本附带的Tomcat使用Tomcat管理应用程序部署的一个很好的Ant任务。
有一个在你没有提到你的做法附加缺陷:当你的应用程序部分部署(在rsync的操作过程中),您的应用程序可以在一个不一致的状态改变的接口可能是不同步的,新的/更新的依赖可能不可用,等等。此外,根据您的rsync的工作需要多长时间,你的应用程序实际上可能重新启动多次。 你知道,你可以和应该关闭Tomcat中的听力换改变,文件和文件重启行为? 它实际上是不建议在生产系统。 你总是可以做到使用Tomcat管理器应用程序的手动或蚂蚁脚本重新启动。
您的应用程序将无法对用户重新启动时,当然。 但是,如果你这么关心可用性,你一定有负载平衡器后面的冗余Web服务器。 在部署更新的WAR文件,你可以暂时有负载平衡器发送到其他Web服务器的所有请求,直到部署结束。 冲洗和重复你的其他Web服务器。
Answer 3:
在停机时间考虑任何环境,你一定运行某种服务器集群的冗余通过以增加可靠性。 我会带一台主机出群集,更新它,然后把它放回集群。 如果你不能在混合环境中运行(在数据库所需的不兼容的架构变化,例如)的更新,你将不得不采取整个网站下来,至少一会儿。 诀窍是下降的原件之前,弹出替换过程。
使用Tomcat作为一个例子 - 您可以使用CATALINA_BASE来定义的目录中的所有Tomcat的工作目录会发现,从可执行代码分开。 我每次部署的软件,我部署到新的根目录,这样我可以在磁盘旁边有旧代码新代码居民。 然后我就可以启动tomcat的另一个实例,它指向新的基本目录,让一切开始启动并运行,然后交换旧进程(端口号),在负载均衡的新的。
如果我关心整个交换机保存会话数据,我可以设置我的系统,使得每个主机有它复制会话数据的合作伙伴。 我可以删除这些主机之一,对其进行更新,以便它挑选的会话数据备份将其带回了起来,然后切换两台主机。 如果我已经在集群中得到了多对,我可以下降一半对,然后做一个质量切换,或者我可以在同一时间做他们一对,这取决于释放的要求,企业等行业的需求。就我个人而言,我更愿意只允许最终用户蒙受活动会话,而不是处理的非常偶然的损失,试图用完整的会话进行升级。
这是IT基础架构,释放过程的复杂性和开发人员的努力之间的所有的权衡。 如果群集是足够大,你的愿望足够强大,它是很容易的设计,可以在不停机的所有被交换出去的大多数更新的系统。 大模式变化往往迫使实际停机时间,因为更新的软件通常无法适应旧模式,你可能无法将数据复制到一个新的数据库实例,做架构更新,然后将服务器切换到新的数据库脱身,因为你将会错过写入旧的任何数据的新的数据库,从它克隆后。 当然,如果你有资源,你可以任务开发人员修改新的应用程序,为将要更新的所有表使用新的表名,你可以把触发器到位的现场分贝,将正确的数据作为更新新表它是由之前版本编写的旧表(或者使用视图来模拟从另外一个模式)。 把你的新的应用程序服务器并将其交换到集群。 有一吨的游戏,你可以为了如果你有开发资源,建设,尽量减少停机时间玩。
或许在软件升级减少停机时间的最有效的机制是,以确保您的应用程序可以在只读模式下运行。 这将提供一些必要的功能给用户,但留给你做需要数据库的修改和这样的系统范围变化的能力。 将您的应用程序为只读模式,然后克隆数据,更新的模式,带来了对新的数据库新的应用程序服务器,然后切换负载平衡器来使用新的应用服务器。 你唯一的停机时间是切换到只读模式并修改您的负载均衡器的配置所需要的时间(其中大部分可以处理它没有任何任何停机)所需的时间。
Answer 4:
我的建议是使用rsync具有分解版本,但部署war文件。
- 在这里您可以有爆炸的WebApp版本的现场环境中创建的临时文件夹。
- Rsync的爆炸版本。
- 全成rsync的后创建环境中生活该机在临时文件夹war文件。
- 用从临时文件夹中新的服务器部署目录老战。
更换新的一个老战在JBoss容器建议(这是基于Tomcat)的东阳it'a原子和运行速度快,这是确保当部署将启动整个应用程序将在部署状态。
Answer 5:
你不能让Web服务器,rsync的该目录在当前Web应用程序的本地副本,然后甚至使用符号链接,在一个“走出去”,指向Tomcat的一个新的部署,而无需多长时间的停机?
Answer 6:
你的方法进行rsync提取的战争是相当不错的,也重新启动,因为我相信,在生产服务器不应该启用热部署。 所以,唯一的缺点是停机时间,当你需要重新启动服务器,对不对?
我假设你的应用程序的所有状态是保持在数据库中,所以你必须有一些用户工作的一个应用服务器实例没有问题,而其他用户在另一个应用服务器实例。 如果是这样,
运行两个应用服务器 :启动第二应用服务器(侦听其他TCP端口),并有部署应用程序。 部署完成后,更新了Apache的httpd的配置(mod_jk的或mod_proxy的)指向第二个应用服务器。 优雅地重新启动Apache的httpd进程。 这样,你不会有任何的停机时间和新用户,并请求将自动重定向到新的应用服务器。
如果你可以使用应用程序服务器的集群和会话复制的支持,这将是其当前登录的用户甚至光滑,作为第二个应用服务器会尽快启动重新同步。 然后,当没有访问到的第一台服务器,关闭它。
Answer 7:
这取决于你的应用程序体系结构。
我的一个应用的背后坐着一个负载均衡的代理,我在那里进行交错部署 - 有效地消除停机时间。
Answer 8:
热部署Java EAR以减少或消除应用程序停机的服务器上或如何“热”使用JBoss的工具Eclipse插件在JBoss中部署战争的依赖可能对你有一些选择。
部署到没有停机集群是有趣了。
JavaRebel有热码deployement了。
Answer 9:
如果静态文件是你的大战争的重要组成部分(100Mo是相当大的),然后将它们的外战,并在你的应用服务器可能会加快事情的前一个web服务器(例如Apache)的上部署它们。 最重要的是,阿帕奇通常不会在服务比一个servlet引擎做(即使他们大多在做这方面的进展显著)静态文件一份更好的工作。
因此,而不是产生一个大胖子WAR,把它放在饮食和生产:
- 大发ZIP与Apache的静态文件
- 一个脂肪少WAR的servlet引擎。
或者,更进一步在使WAR更薄的过程:如果可能的话,部署Grails和不经常改变(这很可能是他们大多数人的情况下),在应用服务器级别其他JAR。
如果你生产一个打火机WAR成功,我不会理会rsyncing目录,而不是档案。
这种方法的优点:
- 静态文件可以烫在阿帕奇“部署”(例如使用一个符号链接指向当前目录,解压新文件,更新的符号链接就万事大吉了)。
- 该WAR将更薄,而且需要较少的部署时间。
这种方法的弱点:
- 还有一个服务器(Web服务器),所以此插件(有点)更多的复杂性。
- 您需要更改构建脚本(不是什么大不了的IMO)。
- 你需要改变rsync的逻辑。
Answer 10:
我不知道这是否回答你的问题,但我只是分享我使用的部署过程或遭遇在我做了几个项目。
类同你,我从来没有记得曾有一个完整的战争重新部署或更新。 大多数时候,我的更新仅限于少数jsp文件,也许一个图书馆,一些类文件。 我能够管理并确定哪些是受影响的构件,通常,我们打包在一个zip文件的更新,与更新脚本一起。 我会运行更新脚本。 该脚本执行以下操作:
- 备份将被覆盖,也许到一个文件夹与今天的日期和时间的文件。
- 解包我的文件
- 停止应用程序服务器
- 在移动文件
- 启动应用程序服务器
如果停机时间是一个问题,他们通常是,我的项目通常是HA,即使他们没有共享状态,但使用提供粘性会话路由的路由器。
我很好奇会是另一件事,为什么需要rsync的? 你应该能够知道需要什么样的变化,通过确定它们暂存/开发环境,不带现场表演三角洲检查。 在大多数情况下,你必须调整你的rsync反正忽略的文件,如定义资源生产服务器使用的某些属性的文件,如数据库连接,SMTP服务器等
我希望这是有帮助的。
Answer 11:
什么是你的PermSpace设置? 我希望看到这个成长很好,但老班的收集后要下去? (或不ClassLoader的还是围坐?)
想着念Wo,你可以Rsync在一个单独的版本 - 或日期命名的目录。 如果容器支持符号链接,你可以SIGSTOP根进程,通过符号链接切换上下文的文件系统根目录,然后SIGCONT?
Answer 12:
至于早期的情况下重新启动。 所有容器都配置选项上的类文件或静态资源的变化禁用自动重新部署。 你可能无法禁用web.xml上的变化自动重新部署所以这个文件是最后一个更新。 所以,如果你禁用自动重新部署和更新web.xml作为最后一个整体更新后 ,您会看到背景下重新启动。
Answer 13:
我们的Web应用程序的新版本上传到一个单独的目录,然后可以移动与正在运行的一个交换出来,或使用符号链接。 例如,我们有一个名为“MYAPP” tomcat的webapps目录下,它指向名为“MYAPP 1.23”当前的webapp一个符号链接。 我们上传新的Web应用程序,以“MYAPP 1.24”。 当一切准备就绪后,停止服务器,删除符号链接,使一个新的指向新的版本,然后重新启动服务器。
我们在生产服务器上禁用自动重载性能,但即使如此,具有Web应用程序在非原子的方式改变中的文件可能会导致问题,因为静态文件,甚至JSP页面可能在造成损坏的链接或者更糟的方式改变。
在实践中,web应用实际上是位于共享存储设备上,所以群集,负载平衡和故障转移服务器的所有具有可用相同的代码。
适合自己情况的主要缺点是,上载将需要更长的时间,因为你的方法允许rsync将只修改或添加的文件传输。 您可以在Web应用程序旧文件夹复制到新的一个第一和rsync到的是,它是否有显著差异,如果它是一个真正的问题。
Answer 14:
Tomcat的7有一个名为“一个很好的功能并行部署 ”这是专为这种使用情况。
要点是,您展开的.war到一个目录中,无论是直接的webapps下/或符号链接。 应用程序的后续版本在目录中名为app##version
,例如myapp##001
和myapp##002
。 Tomcat将处理现有会话将旧版本,而新的会话持续到新版本。
美中不足的是,你必须非常小心PermGen的泄漏。 这与使用了大量的PermGen的Grails的尤其如此。 VisualVM的是你的朋友。
Answer 15:
只需使用2个或多个Tomcat服务器有超过它的代理。 该代理可阿帕奇/ nignix / HAProxy的的。
现在,在每个代理服务器的存在“来”与“走出去”的网址与端口配置。
在tomcat你的战争首先复制不回采的服务。 一旦战争部署会自动由Tomcat引擎打开。
注意交叉检查unpackWARs在节点“主机” =“true”和自动部署=“真”里的server.xml
它看起来喜欢这个
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true"
xmlValidation="false" xmlNamespaceAware="false">
现在看到的tomcat的日志。 如果没有错误是存在的意思是它建立成功。
打到现在测试的所有API
现在来到你的代理服务器。
简单地改变与新的战争的名字的背景URL映射。 由于与如Apache / nignix / HAProxy的花很短的时间,你会感觉到停机时间最短的代理服务器注册
请参阅- https://developers.google.com/speed/pagespeed/module/domains的URL映射
Answer 16:
您使用的树脂,树脂具有内置的Web应用程序版本的支持。
http://www.caucho.com/resin-4.0/admin/deploy.xtp#VersioningandGracefulUpgrades
更新:这是看门狗过程可与permgenspace问题的帮助了。
Answer 17:
没有一个“最佳实践”的东西,但我只是想的。
如何通过DVCS如git的部署web应用程序?
这种方式可以让混帐弄清楚哪些文件传输到服务器。 你也有一个很好的方法来备份出来的,如果它真可谓是破获,只是做一个恢复!
Answer 18:
我写了一个bash脚本,它的几个参数和rsyncs服务器之间的文件。 加快rsync的较大档案转移了很多:
https://gist.github.com/3985742
文章来源: Best practices for deploying Java webapps with minimal downtime?