这是一个PHP应用程序。在更新整个代码库时,如何最大程度地减少停机时间?

#1 楼

在更新之前,通常要做的是:


服务器的文档根目录是:/www/app-2009-09-01中的




>但通过称为/www/application的符号链接进行访问



我们将整个新代码库放入/www/app-2009-09-08

,一旦整个代码库为在那里:

我们删除了旧的符号链接
我们创建了一个新的符号链接,仍然称为/www/application,但是它指向新的源:/www/app-2009-09-08



我们重新加载apache以迫使修改被考虑。 。这意味着:


一切进展很快(尤其是符号链接的切换,这是重要的一部分)
没有犯错误的风险:脚本已经过充分测试,并且可以使用数月/年。



此符号链接程序的另一个优点是,如果仅在放置新版本后才发现灾难性错误,则很容易“回滚”更新来源到生产:我们只需要切换符号链接即可。

当然,这并不妨碍您在登台服务器上测试新版本之前将其投入生产-但是, ,谁知道...有时候,有一个非常大的错误,在测试时没有人能够看到:-(
,例如,因为在此阶段没有定期进行负载测试
(我已经看到“回滚”的东西在3年中使用了大约4到5次-每次都节省了一天-以及网站^^)



这里是某种一个简单的例子:假设我在Apache配置中有这个VirtualHost:只是到源的当前版本的符号链接。
这意味着,当您将源放置到服务器上但尚未切换时,您将看到类似以下内容的内容:

旧版本”

现在,新版本已完全上传到服务器,让我们切换:
/www/application指向源的新版本:

<VirtualHost *>
        ServerName example.com
        DocumentRoot /www/application
        <Directory /www/application>
            # Whatever you might need here (this example is copy-pasted from a test server and test application ^^ )
            Options Indexes FollowSymLinks MultiViews +SymLinksIfOwnerMatch
            AllowOverride All
            php_value   error_reporting 6135
            php_value short_open_tag  on
        </Directory>
</VirtualHost>


我们只需要重新启动Apache即可:

root@shark:/www
# ll
total 8
drwxr-xr-x 2 root root 4096 2009-09-08 22:07 app-2009-09-01
drwxr-xr-x 2 root root 4096 2009-09-08 22:07 app-2009-09-08
lrwxrwxrwx 1 root root   19 2009-09-08 22:08 application -> /www/app-2009-09-01


应迅速完成“删除链接;创建新链接;重新启动apache”这三个步骤;即使用自动脚本,而不是人工操作。新版本的资源:只要未更改symlic,apache就不会使用它们。
一切正常后,只需切换symlink:它的速度比更改1或2个文件还要快...基本上意味着没有停机时间:-)

我想,如果使用stat选项为0的APC等操作码缓存,则意味着停机的风险更低。


当然,这是“简单”版本-例如,如果您有一些上传的文件,则必须在某个地方使用另一个符号链接,另一个VirtualHost或其他任何方式...


希望更清楚:-)

评论


这也是一种服务器交换。 :-)

–十个边缘饮料
09年9月8日20:00

mod_rewrite管理符号链接?

– gAMBOOKa
09年9月8日于20:01

@gAMBOOKa:否:仅与Apache的DocumentRoot(或VirtualHost DocumentRoot)有关,该文件为/ www / application;即符号链接-无论该链接指向何处。

– Pascal MARTIN
09年9月8日于20:02

很棒的答案。不过,还有一个提示:您可以使符号链接发生而无需取消链接。引述如下:“这三个步骤……应迅速完成;即,通过自动化脚本而不是人。” mv命令是原子操作,因此您可以创建类似“ ln -s / www / app-2011-01-28 / www / application-temp”的符号链接,然后执行“ mv -T / www / application-temp” / www / application”。

– Joe Liversedge
2011年1月29日,11:24

symlink方法未涵盖某些内容。您的方式适用于Apache + mod_php,但在lighttpd + fastcgi上可能会失败。在一个高流量的网站中,请求将在交换链接的过程中得到服务,即php代码依赖关系将因混合版本而失败。

–丹尼斯C
2011年5月25日下午2:25

#2 楼

您不能采用现有代码并将项目迁移到单独的测试php文件中,并在进行更新时使用它吗?我的意思是,您应该拥有一个测试服务器和一个生产服务器,以便在必须进行更新时不会造成任何停机。

#3 楼

使用更新的代码库设置第二台服务器,并尽快切换它们。 :-)

如果不可能,请确保将代码库分为数十个较小的部分。这样一来,停机时间将仅限于一个子部分。较小的代码块更易于替换,并且大多数代码块将继续运行而不会出现问题。不过,只需先在测试环境上尝试一下即可!

评论


由于尚未对应用程序进行零碎模块测试,因此可能会导致意外情况。

– gAMBOOKa
09年9月8日于20:02

这意味着在此更新之后,这将在您的“待办事项”列表中。 :-)使它更具模块化,您可以每个模块进行更新。

–十个边缘饮料
09年9月8日在20:05

这在“待办事项”列表中,但这是一个长期目标。我们是一家年轻的初创公司,因此开发团队中的组织自然会花费一段时间。 = D

– gAMBOOKa
09年9月8日在20:07

#4 楼

首先,我经常使用并且喜欢与Pascal MARTIN的响应类似的方法。

我也喜欢的另一种方法是使用SCM推送新代码。确切的过程取决于您的SCM类型(git vs svn vs ...)。如果您使用的是svn,我想创建一个“在线”或“生产”分支,并将其签出作为服务器上的文档根目录。然后,每当我想从另一个分支/标记/主干推送新代码时,我只需将新代码提交到“在线”分支中,然后在文档根目录中运行svn update即可。这提供了非常容易的回滚,因为有完整的修订日志,记录了服务器上/下发生的事情以及执行此操作的人员和时间。您还可以轻松地在测试框上运行该“在线”分支,从而允许您审核要推送的应用程序。使其工作流程风格更加自然。

想要拉/轮询而不是推送更新?只需执行cron作业或其他更智能的机制即可自动运行svn update。

额外:您还可以使用此过程来备份应用程序写入磁盘的文件。只需执行cron作业或运行svn commit的其他机制即可。现在,您的应用程序创建的文件已备份到SCM中,记录了修订等。(例如,如果用户更新了磁盘上的文件,但要您还原它,只需推送旧修订)。

#5 楼

我也使用类似Pascal MARTIN的方法。但是,我没有将我的应用程序的多个版本上传到生产服务器,而是将“版本”保留在防火墙后,每个版本都包含在单独的目录中,其中包含版本号和日期。当我想上传新版本时,我使用了一个简单的脚本,其中包括“ rsync -avh --delay-updates”。 “ delay = updates”标志会将所有内容(不同)上传到一个临时文件夹,直到所有更新都存在为止,然后在传输结束时立即将所有内容移到它们的正确路径,因此该应用程序永远不会半新状态。它与上述方法具有相同的效果,除了我只在生产站点上保留一个版本的应用程序(最好在生产服务器IMO上仅保留裸露的基本文件)。