当一秒停机价值百万
\n\n想象一下:你正在更新一个基于PHP的在线商店,通过FTP上传新版本,此时网站宕机了5分钟。五分钟就是300秒。在这段时间里,100个潜在客户流失到竞争对手那里,你不仅损失了金钱,还损失了声誉。是不是很熟悉的心痛?
\n\n在当今世界,用户不会容忍错误,PHP服务的零停机部署不是奢侈品,而是必需品。但是,如果你的技术栈是PHP、Nginx和几台服务器,如何实现无缝部署呢?让我们通过实际案例来探讨。
\n\n为什么PHP比看起来更复杂?
\n\n与Node.js或Python不同,PHP在经典意义上不支持多线程。每个请求都由一个独立的PHP-FPM进程处理。这带来了限制:你不能简单地“重新加载”代码而不丢失当前会话。然而,同样的特性也赋予了我们超能力——能够在不同版本之间平滑切换流量。
\n\nPHP部署的主要问题:
\n- \n
- 连接中断 — 用户丢失表单数据或会话 \n
- 脏缓存 — 旧代码返回过时缓存中的数据 \n
- 损坏的迁移 — 新数据库版本与旧代码不兼容 \n
为了避免这些陷阱,我们使用经过验证的策略。是的,零停机部署不是魔法,而是一个清晰的计划。
\n\n策略一:蓝绿部署
\n\n最可靠的方法是维护两个完整的应用程序副本:“蓝色”(当前)和“绿色”(新版本)。Nginx充当负载均衡器。
\n\n实际运作方式
\n假设你有两台服务器:app1.example.com(蓝色)和app2.example.com(绿色)。两者都运行PHP-FPM。当前蓝色处于活动状态。你将新版本部署到绿色,进行测试,然后将Nginx切换到绿色。
用于切换的Nginx配置示例:
\n\n# nginx.conf\nupstream php_backend {\n # 首先激活蓝色\n server app1.example.com:9000 weight=1; # 蓝色\n server app2.example.com:9000 weight=0; # 绿色(已关闭)\n}\n\nserver {\n listen 80;\n server_name myshop.com;\n\n location ~ \\.php$ {\n fastcgi_pass php_backend;\n include fastcgi_params;\n fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;\n }\n}\n\n\n部署到绿色后,更改权重:
\n\n# 部署后 — 切换流量\nupstream php_backend {\n server app1.example.com:9000 weight=0; # 蓝色(已关闭)\n server app2.example.com:9000 weight=1; # 绿色(已激活)\n}\n\n\n重新加载Nginx而不宕机:nginx -s reload。所有现有连接正常完成,新连接流向绿色。PHP零停机部署已实现!
优缺点
\n优点:完全容错,可以快速回滚(只需恢复权重)。
\n缺点:需要双倍的资源(服务器或容器)。
策略二:滚动更新
\n\n如果预算有限,我们使用滚动更新。思路:逐个更新PHP服务器,不关闭其他服务器。用户不会注意到停机,因为Nginx将请求重定向到活跃的服务器。
\n\n在PHP-FPM上的实现
\n假设你有3台运行PHP-FPM的服务器。我们依次将它们从轮换中移除,更新代码,然后重新加入。
\n\n步骤1:从负载均衡器中移除服务器(优雅关闭):
\n\n# 在要更新的服务器上\nsudo systemctl stop php8.1-fpm\n# Nginx将自动停止向此服务器发送请求,因为它不可用\n\n\n步骤2:更新代码(通过git pull、rsync或Docker)。
\n\n步骤3:重新启动PHP-FPM:
\n\nsudo