部署竞争条件导致CDNcaching旧的或损坏的文件
我们目前的部署过程如下所示:
- 使用
grunt
来创build生产资产。 -
在我们的CDN创builddate戳记和点文件(例如
/scripts/20140324142354/app.min.js
)。旁注:我以前听说过这个叫“版本控制”的过程,但是我不确定这个过程是否合适。
-
提交到github构build。
- 在web服务器上运行
git pull
从github中获取新的代码。
这是一个node.js站点,我们forever -w
使用forever -w
来监视文件更改并相应地更新站点。
我们的应用程序中有一个path设置,通过/scripts/*/app.min.js
提供最新版本的应用程序。
我们这样版本的原因是因为我们的CDN被设置为无限期地cachingJavaScript文件,这有意创buildcaching未命中,以便在CDN(也在用户的浏览器中)更新代码。
这在大多数情况下工作正常。 但是,如果其中一台服务器在检查新代码时有点滞后,
有时客户端在部署正在进行的同时点击该页面,并尝试从CDN检索新的JavaScript代码。 CDN试图检索它,但点击一个未完成检查新代码的服务器,并caching一个旧的或部分下载的文件,导致各种问题。
这个问题由于我们的CDN有很多边缘位置而加剧了,所以我们的办公室并不总是能立即看到问题。 一些边缘位置可能已经拉下了旧的/坏的代码,而其他的可能已经拉下了新的/好的代码。
有没有更好的方法来做这些部署,以避免这个问题?
你的程序中的第4步应该是:
git archive --remote $yourgithubrepo --prefix=$timestamp/ | tar -xf - stop-server ln -sf $timestamp current start-server
您的服务器将始终使用current
目录(以及符号链接)。 无论部署需要多长时间,您的应用程序都处于一致状态。
作为一般的经验法则:
不要做现场升级。 (除非语言支持,但即使这样想)
使用git pull
拉代码,然后等待应用程序注意文件的变化听起来很像90年代:使用ftp(或sftp,如果你很酷)上传php文件到apache web服务器,等待apache注意到它们是更新。 primefaces不可能发生,所以当然有一个竞争条件。 一些用户将得到一半build立和破碎的网站。
我build议只在没有人使用的情况下升级您的实时和正在运行的应用程序。 希望你有一个负载均衡器背后的服务器池,这将允许您一次删除它们并升级它们。
这意味着用户可以同时使用旧网站和新网站,具体取决于用户访问网站的方式和时间,但是这比根本不能访问网站要好得多。
理想情况下,您将能够使用新版本的站点启动运行的每个Web服务器的副本。 检查新版本是否正常工作,然后自动更新负载均衡器,以便每个人都能同时碰到新的站点。 只有一切都validation完美的工作旧机器closures和退役,或重新使用。
我会继续发布我们现在正在使用的远非理想的猴子补丁。
一旦我们确定代码被部署在所有我们做另一个构build的服务器上,我们只部署一次可能或不可能按计划进行的部署,其中唯一改变的是版本号。
然后我们再通过服务器部署服务器。
竞争条件依然存在,但是由于两个版本之间的应用程序代码是相同的,所以这掩盖了这个问题,因为无论CDN打哪个服务器都会得到“最新”的代码。