我们当前的部署流程如下:
grunt
创建生产资产。在我们的CDN上创建日期戳和指向文件(例如/scripts/20140324142354/app.min.js
)。
旁注:我听说过这个过程称为"版本化"之前,但我不确定它是否是正确的术语。
提交构建到github。
git pull
以从github检索新代码。这是一个node.js网站,我们正在使用forever -w
来监控文件更改并相应地更新网站。
我们的应用中设置了路线设置,可通过/scripts/*/app.min.js
投放最新版本的应用。
我们这样的版本的原因是因为我们的CDN设置为无限期缓存JavaScript文件,这故意创建缓存未命中,以便在CDN(以及我们的用户浏览器)中更新代码。
这种情况很好最。但是,如果其中一台服务器在检查新代码方面有所欠缺,那么它就会崩溃。
有时客户端会在部署过程中点击页面并尝试从CDN检索新的JavaScript代码。 CDN尝试检索它,但命中服务器尚未检查出新代码,并缓存旧的或部分下载的文件,导致各种问题。
这个问题因我们的CDN有许多边缘位置而加剧,因此我们的办公室始终无法立即看到问题。一些边缘位置可能已经删除了旧/坏代码,而其他位置可能已经下拉了新的/好的代码。
有没有更好的方法来执行这些可避免此问题的部署?
答案 0 :(得分:3)
作为一般经验法则:
不要进行实时升级。 (除非语言支持它,但即便再考虑三次)
使用git pull
拉取代码,然后等待应用程序注意文件的更改听起来很像90:使用ftp将php文件上传到apache web服务器(如果你很酷的话,将sftp上传到sftp)并等待apache注意到它们已更新。它不可能原子地发生,所以当然存在竞争条件。一些用户将获得一半建立和破坏的网站。
我建议只升级您的实时和正在运行的应用程序,而没有人使用它。希望您在某种负载均衡器后面有一个服务器池,这样您就可以一次删除它们并升级它们。
这意味着用户可以同时使用旧网站和新网站,具体取决于他们访问网站的方式和时间,但这比根本无法访问它更好。
理想情况下,您可以使用新版本的网站启动运行的每个Web服务器的副本。检查新版本是否正常工作,然后以原子方式更新负载均衡器,以便每个人同时遇到新站点。只有一切都经过验证才能完美运行,旧机器才会关闭,退役或重复使用。
答案 1 :(得分:2)
你的程序中的第4步应该是:
git archive --remote $yourgithubrepo --prefix=$timestamp/ | tar -xf -
stop-server
ln -sf $timestamp current
start-server
您的服务器将始终使用current
目录(以及符号链接)。无论部署多长时间,您的应用程序都处于一致状态。
答案 2 :(得分:0)
我会继续发布我们现在正在使用的远离理想的猴子补丁。
一旦我们确定代码部署在我们进行另一次构建的所有服务器上,我们会部署一次可能会或可能不会按计划进行,其中唯一更改的是版本号。
然后我们再次按服务器部署服务器。
竞争条件仍然存在但由于两个版本之间的应用程序代码相同,这掩盖了问题,因为无论CDN命中哪个服务器,它都会获得“最新”代码。