8.3 测试部署与环境管理


8.3 测试部署与环境管理

延伸段的最后一课是「最后一公里」:代码在本机跑通只是起点,进入生产要过三关——测试证明它该对的对、环境保证它在哪都按同一套规矩跑、部署流程保证出问题能回得去。本节是全册的收束:前七章的每个知识点在发布清单里都会留下名字。学完你应当能为书店项目执行一次带完整护栏的发布,并在出问题时五分钟内回滚。

测试:关键路径的最小覆盖

测试不必追求覆盖率数字,先保住关键路径:下单、支付回调、登录——这些路径坏了是资金与信任事故,值得每条至少一组用例。框架对接 PHPUnit,HTTP 层测试可以不启动浏览器直接打满全流程:

class OrderTest extends TestCase { public function testCreateOrderDeductsStock(): void { $book = Book::find(1); $before = $book->stock; $response = $this->post('/order/create', [ 'book_id' => 1, 'num' => 2, ]); $response->assertCode(0); // 业务码成功 $this->assertEquals($before - 2, $book->refresh()->stock); // 库存精确扣减 } public function testCreateOrderFailsWhenStockNotEnough(): void { $response = $this->post('/order/create', ['book_id' => 2, 'num' => 99999]); $response->assertCode(422); // 6.1 验证与业务双闸都在拦 } }

两个用例代表了最值得写的类型:正向主流程(结果不仅返回成功,状态真的变了)与边界反例(越界输入被挡住且系统无副作用)。注意测试要跑在独立环境——独立的数据库或事务回滚包裹,绝不允许测试数据混进开发库,更别提生产库。这一条与 6.3 会话隔离、7 章数据库分权一脉相承:环境间的墙,测试期就要砌起来。

环境管理:一套代码,三副面孔

同一份代码要在开发、预发布、生产三套环境里跑出正确行为,差异全部收敛进环境变量:

# .env.example(入库样板);真实 .env 不进版本库 APP_DEBUG = false [DATABASE] hostname = 127.0.0.1 database = shop username = shop_app password = [CACHE] driver = redis

纪律有三条。其一,.env 只在各环境机器上存在,版本库里只有无敏感信息的样板(7 章的安全纪律:密码进库即泄漏)。其二,预发布环境与生产同构:同样的驱动、同样的伪静态、同样关闭调试——「本地好的」与「生产好的」之间隔着的,往往就是这些没对齐的配置项。其三,调试开关与环境绑定:APP_DEBUG 在生产必须是 false,Trace 面板与详细错误页都会向攻击者交付系统情报(7 章防线的最后一块砖)。

部署:伪静态、容器与发布流程

Web 服务器要把所有请求导向入口文件,Nginx 参考配置:

server { listen 80; server_name shop.example.com; root /www/shop/public; # 站点根指向 public,绝不指向项目根 index index.php; location / { if (!-e $request_filename) { rewrite ^(.*)$ /index.php?s=$1 last; } } location ~ \.php$ { fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } }

root 指向 public 是安全要求而不是偏好——项目根下的配置、环境变量、模板源码都不该有对外路径。容器化部署时同样的原则换了个载体:镜像内应用与配置分层,环境变量注入而非写死,数据卷挂载缓存与日志目录(8.1 的队列进程在容器方案里是独立的服务副本,与 Web 容器分开伸缩)。

图 8-3:部署分层 · 从代码到流量

图 8-3:部署分层 · 从代码到流量

发布清单与回滚纪律

把本章与全册收进一张发布清单:测试全绿、环境变量核对、调试关闭、队列进程在线、缓存预热(6.2 的榜单)、灰度启动、观察指标就位、回滚命令演练过。回滚的可行性取决于两个前置:版本化发布——每次发布保留完整版本目录,切回旧版是改一个软链而不是重新发一遍;数据库变更向后兼容——回滚能还原代码,还原不了已执行的数据迁移,所以删列延后一个版本、加列先行的「扩展收缩」节奏是硬约束。灰度期间盯着 8.2 的观测面板:错误率与耗时的任何异动先放量暂停、再定位、最后决定放量或回滚——顺序不能反,先回滚止损永远是第一选择。

动手练习:执行一次带护栏的完整发布

背景:练习项目准备把「下单队列化」版本发上预发布与生产。操作:写出并跑通关键路径用例;核对三环境变量表;在预发布完整走一遍发布清单;生产灰度百分之五流量,观察半小时指标后全量;随后故意制造一次告警(把队列进程停掉),执行回滚并复盘。结果示例:灰度期间指标平稳,全量后队列监控显示消费及时;故障演练中回滚在数分钟内完成,复盘确认「版本目录保留」是本次能快速回退的关键。解读:注意演练里最耗时的环节往往不是回滚本身,而是「确认该不该回滚」——预先约定好放量暂停的指标阈值,演练的就是这个决策链。变式:为下一次含删列的数据库变更写一份向后兼容的分步方案,标注每一步允许回滚的窗口。

⚠️ 常见坑:从未演练过的回滚预案等于没有预案——真出事时才发现版本目录早被清理、回滚脚本引用了已废弃的环境变量。每次发布演练一次回滚,五分钟的演练买的是深夜五分钟的从容。

本节要点回顾

  • 关键路径优先:下单、支付、登录每组至少正向加反例两条用例,测试环境绝对隔离。
  • 差异全进环境变量.env 不进库,预发布与生产同构,调试开关绑环境。
  • 入口指向 public:伪静态与容器配置同守一条安全线,配置源码不对外。
  • 灰度加回滚是护栏:小流量观察、达标放量、异动先回滚后定位。
  • 回滚靠两个前置:版本化发布保留目录,数据库变更向后兼容。

总线到站。八座站台走完,回头再看那条凌晨的告警:请求的每一站你都了如指掌,慢在哪、堵在哪、怎么防、怎么退——这正是开篇承诺的观察哨视野。愿你接下来的每个项目,都跑得又快又稳。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U