部署竞争条件导致CDNcaching旧的或损坏的文件

我们目前的部署过程如下所示:

  1. 使用grunt来创build生产资产。
  2. 在我们的CDN创builddate戳记和点文件(例如/scripts/20140324142354/app.min.js )。

    旁注:我以前听说过这个叫“版本控制”的过程,但是我不确定这个过程是否合适。

  3. 提交到github构build。

  4. 在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打哪个服务器都会得到“最新”的代码。