实时部署新代码


29

在实时(电子商务)站点上部署新代码的最佳实践是什么?

现在,在将目录重命名public_html_newpublic_html并旧命名为时,我已停止apache +/- 10秒public_html_old。在我再次启动Apache之前,这会造成短暂的停机时间。

如果使用Git将新存储库拉到活动目录,也会遇到同样的问题。网站活跃时,我可以拉回购吗?如果我也需要复制数据库又如何?

在实时站点的tar(备份目的)压缩过程中,我注意到媒体目录中发生了更改。这向我表明文件会定期更改。如果在部署过程中未停止Apache,这些更改是否会造成干扰。

Answers:


13

使用负载平衡器是一个好主意。如果站点足够重要,可以担心几秒钟的停机时间,那么它足够重要,可以考虑容错能力。

除此之外,如果这是在UNIX系统上,则可以在重命名(或symlink更新等)期间将Apache搁置:

killall -STOP httpd  # Pause all httpd processes
mv public_html public_html_orig
mv public_html_new public_html
killall -CONT httpd  # Resume all httpd processes

这将防止Apache在重命名期间接受新请求。如果您更喜欢符号链接或其他方法,则可以使用相同的想法:

killall -STOP httpd  # Pause all httpd processes
rm /var/www/html
ln -s /var/www/version/03 /var/www/html
killall -CONT httpd  # Resume all httpd processes

请注意,所有未决的连接或数据包都将在操作系统中排队。对于非常繁忙的站点,请考虑根据您的httpd工作程序类型调整ListenBacklog,并检查与TCP侦听积压相关的OS设置。

您还可以在httpd.conf中更改DocumentRoot并进行正常重启(apachectl graceful)。这样做的缺点是增加了出错的风险,因为您还必须更新任何Directory配置。


暂停会话是否仍可以在网站上运行?
nicoX 2014年

4
它停止为Apache提供CPU时间。如果您在暂停Apache的情况下尝试通过浏览器访问该站点,则浏览器将等待连接,直到恢复Apache(否则,如果Apache暂停的时间超过超时时间,则浏览器将超时)。如果有人正在下载文件,Apache会在暂停时停止发送数据,这又是因为它没有占用任何CPU时间。同样,这只会在Apache停止时间过长而导致传输超时的情况下引起问题。
GargantuChet 2014年

5
换句话说,站点在Apache暂停时将无响应,但是待恢复的操作将在恢复后完成。用户不会收到“连接被拒绝”的消息,下载也不会中断,但是操作只有在恢复Apache后才能继续。这样可以确保现有交易可以完成,但是只有在将新内容移到适当位置后才能处理新请求。
GargantuChet 2014年

1
请注意,在任何高流量的网站中,这很容易导致您的Apache服务中断。一旦您在移动后“解锁” Apache进程(如果需要一点时间)
那么

1
在人流量大的站点上,恢复Apache时会有大量的运行中请求完成。这将错开新请求的处理。确保您的Apache设置(线程/服务器/客户端的最大数量)合理,并相应地调整TCP积压也是一个很好的论据。尽管我对您“终止”服务的含义感到困惑。Apache非常可调。
GargantuChet 2014年

32

最快,最简单的方法是使用版本目录,例如

/var/www/version/01
/var/www/version/02

并使用当前的符号链接作为html_root:

/var/www/html -> /var/www/version/02

该技术可以完美地集成到修订控制系统(svn,git,mercurial等)中,因为您可以签出分支和标签,更改符号链接并重新加载Apache。该停机时间最小使用这种技术,它可以很容易的回滚

它还可以与更复杂的部署系统(例如RPM软件包)或配置更改管理(首席,木偶等)基础架构很好地集成。


4
最简单的解决方案始终是最好的解决方案... :-)当然,不要忘了提到,可能需要一些FollowSymlinks和配置中的此类apache标志。
彼得说恢复莫妮卡

@PeterHorvath说的要特别小心。使用符号链接的DocumentRoots时,Apache会变得非常脾气暴躁。请务必仔细测试!
mhutter 2014年

@mhutter谢谢:-)真正有问题的是在apache上启用FollowSymlinks会导致安全问题……
彼得说恢复莫妮卡(Monica)2014年

更新符号链接不是原子操作。即使使用诸如ln -snf破坏原始符号链接之类的方法,底层操作也是unlinkand symlink。用户在更新期间可能会收到404。这不仅仅只是重命名原始目录并重命名一个新目录(假设您没有跨越文件系统),这也没有什么好。请参阅上面的答案,并在其旁边打勾,以解决此问题。
GargantuChet 2014年

14

重命名目录而不关闭Apache也应该起作用。这将大大缩短窗口。mv public_html public_html_old && mv public_html_new public_html应该在不到一秒钟的时间内完成。

有两个缺点,即该方法将给404仍然在窗口期间发生的任何请求提供一个。而且,如果您在没有public_html_new目录的情况下运行上述命令,它将失败,并为您提供一个404针对每个请求的站点。

不支持对目录执行原子操作。但是您可以使用符号链接来实现。与其拥有一个名为public_html的目录public_html.version-number,不如拥有一个名为的目录和一个public_html指向该目录的符号链接。现在,您可以创建一个名为的目录public_html.new-version-number和一个名为的新符号链接public_html.new

然后,您可以重命名public_html.newpublic_html自动切换。请注意,mv执行该重命名“太聪明了”,但是可以使用os.renamepython或其他任何会调用rename系统调用而又不会变得聪明的方法来完成。

如何处理数据库取决于您使用的数据库以及数据库的用途。您需要提供有关数据库的更多详细信息,然后我们才能为您提供对这一部分问题的良好答案。


1
在我的Debian系统上,mv有一个-T选项可以阻止它遵循符号链接。假设两者都是软链接,这将使您原子重命名public_html.newover public_html
GargantuChet 2014年

11

Symlinks和mv是您的朋友,但是,如果您确实需要避免最终用户在部署新版本时出现错误页面,则应该在至少2台后端服务器(Apache)前面安装反向代理或负载均衡器(Apache在您的情况下)。

在部署过程中,您只需要一次停止一个后端,部署新代码,重新启动它,然后在其余后端上进行迭代。

最终用户将始终通过代理定向到良好的后端。


4
当我看到您已经发布它时,我只是在解决这个问题。Balancer + 2台服务器使该过程不可见,并且很容易从错误的升级中恢复...
Bart Silverstrim 2014年


4

我这样做的方法是将所做的更改从本地开发环境提交到在线Git存储库(如Github)。我的生产环境在一个远程存储库上运行,因此我要做的就是将ssh连接到服务器并运行git pull以减少最新的更改。无需停止您的网络服务器。

如果项目中的文件的设置和/或内容与本地版本不同(例如配置文件和媒体上载),则可以使用环境变量和/或将这些文件/目录添加到.gitignore文件中以防止与存储库同步。


3

我的第一个想法是:

# deploy into public_html_new, and then:
rsync -vaH --delete public_html_new/ public_html/

一个好的解决方案是使用rsync。它仅更改了真正更改的文件。当心,路径结尾处的斜线在这里很重要。

通常apache不需要重启,这不是Java世界。它根据请求检查每个php文件的更改,并根据更改自动重新读取(并重新标记)。

Git pull具有相似的效率,尽管编写起来有些困难。当然,它实现了多种不同的合并/更改检测可能性。

仅当没有真正的重大更改时,此解决方案才能无缝运行-如果部署中有较大更改,则无法消除一点危险,因为存在不可忽略的时间间隔,此时将部分更改代码部分不是。

如果有很大的变化,我的建议是您最初的解决方案(两个重命名)。


这有点硬,但是100%是原子解决方案:

(1)在您的magento发生的地方做一些文件系统的替代挂载:

mount /dev/sdXY /mnt/tmp

(2)--bind将您的public_html_new装载到public_html:

mount --bind /path/to/public_html_new /path/to/public_html

至此,apache将看到您的新部署。404的任何更改都是不可能的。

(3)使用rsync进行synhcronistation,但是在备用安装点上):

rsync -vaH --delete /mnt/tmp/path/to/public_html_new/ /mnt/tmp/path/to/public_html/

(4)拆下装订架

umount /path/to/public_html

该命令将删除public_html并将其部署到public_html_new吗?
nicoX 2014年

@nicoX不,它将复制更改。
彼得说恢复莫妮卡2014年

@nicoX它在两个目录结构中都经过,并且如果发现差异(新文件,已修改文件,已删除文件),则会根据需要修改第二个目录以匹配第一个目录。如果您删除的public_html,然后将结果public_html_new移动到它的地方,没有一个临时的404问题的任何可能性。
彼得说恢复莫妮卡2014年

1
不,这不是一个好主意。根据public_html所做的更改,您可能会在很短的时间内,其中的代码处于不一致状态,并且您不希望借此机会。
斯文

@SvW是的,只有微小的变化,我的想法是正确的。我相应地扩大了答案。
彼得说恢复莫妮卡2014年

1

移动/替换http_public文件夹可以用简单的实现mvln -s命令或等效的,而你的HTTP服务器保持运行。您可以执行一些脚本编写以显着减少停机时间,但是如果您要自动执行该过程,请仔细检查脚本中命令的返回码。

就是说,如果您不希望停机,那么您的应用程序也必须支持它。大多数应用程序使用数据库来保持持久性。如果开发团队未预料到,将应用程序的N版本与数据模型的N + 1版本(或相反)混为一谈,可能会破坏事情。

根据经验,对于大多数应用程序并没有通过升级来保持这种一致性。尽管有停机时间,但适当的关机是避免一致性问题的好方法。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.