软件架构考试之夜提供了证据,不是容量保证——NovaCommerce 第五篇
两场真实考试、一次缩容失误和一个规划模型。最后一篇把观察、外推、运维成本与尚欠测试分清楚。
增加一个应用实例不等于多完成一次结账。衡量就绪时间、验证受限层,并为故障保留容量。
作者
Anichur Rahaman

午夜,预定促销开始。源站需求从每秒20次升到440次,团队等待扩容规则增加容量。机器终于启动,但拉取镜像、应用启动、注册和缓存预热,仍隔在“运行中”和有效结账之间。这是教学情境,不是事故报道或StoreConsole基准。
已知需求给你准备时间,却不保证多加机器有效。规划必须连接到达形态、真实请求路径、共享约束与就绪时间。本篇是Engineering for High Volume第1部分,关注边缘到应用的请求路径。
响应式扩容是控制循环:观察、评估、申请资源、启动工作负载、接入流量。预热池或轻进程可很快,慢镜像、配额或冷依赖也可能很慢。不存在通用一至三分钟下限,或适用于所有策略的同一冷却期。
AWS区分步进/简单扩容及预热行为。应读实际策略、指标周期、评估和缩容规则。简单扩容的某个默认值,不是所有目标跟踪扩容前的固定等待。测量自己的关键路径,包括供应失败和就绪。
仅作规划,假设依次需要检测/控制60秒、供应90秒、注册/健康30秒、预热30秒,共210秒即3分30秒。现实可能重叠。按观察到的慢情形加合理缓冲,提前安排容量;仅看运行VM数量不能证明就绪。
| 示例串行阶段 | 秒 | 累计秒 |
|---|---|---|
| 检测/控制 | 60 | 60 |
| 供应资源 | 90 | 150 |
| 注册/健康 | 30 | 180 |
| 预热 | 30 | 210 |
已知活动使用定时或预测准备,搭配响应式规则处理剩余波动,并声明最大费用/容量。提前扩容也有成本且可能失败,须验证配额、可用实例与依赖。超出已验证容量时保留准入控制或诚实的等待体验。
区分缓存静态资源、公共页、动态渲染、API、结账写入与后台任务。边缘请求、源站请求、用户和订单不是同一单位。Next.js页面可能调用API,内置单体可能使用内部SSR,部分API绕过SSR,不要强行画成一条虚构链路。
按明确主机/语言/变体策略缓存不可变资源和真正可共享响应。个人账户、购物车、依赖权限内容和设置会话的响应需要相应绕过或私有处理。看似公共页面也可能包含个性数据。验证冷/热缓存、失效、重建惊群和真实命中率。
WAF、限流和负载均衡器也有连接、TLS、带宽、注册、配额与健康限制。托管不等于无限或永不成为瓶颈。AWS ALB容量预留是突发活动的特定服务选项,应按实际负载估计和验证,不复制旧的容量翻倍说法。
健康检查只能证明所检查的内容。用依赖感知探针和真实流程验证就绪,但不要因共享依赖故障移除全部仍有用节点。测试排空、传播及宽限期;排空减少中断,不保证无感扩容,也不会修复已失败请求。
实例消失后,会话、上传、任务所有权、锁和可变业务状态应仍可用。适当共享数据库/会话存储与持久共享/对象存储可帮助;Redis和S3是选项,不是每个部署的必选。局部不可变缓存可以合理,共享协调/失效与可丢弃本地缓存的需求不同。
Next.js自托管指南解释多实例缓存和构建/版本问题。部署兼容产物,协调失效、身份/密钥及生成资源。只有共享缓存存储,不证明所有缓存类型、标签和处理中版本都安全。
协调定时任务,防止重复业务作用。Laravel调度文档介绍共享原子锁的单服务器执行协调。锁、过期/故障切换及唯一业务身份仍须故障验证;只在一台跑cron不是完整恰好一次设计。
统一真实代理/应用路径的请求大小、超时与上传行为,不是所有想象服务。节点故障不能丢失已接受上传或支付结果。权威服务继续检查租户/记录权限,扩容不会授予新权力。
Node事件循环上的CPU密集JavaScript可能打满,而其他核空闲。这不表示进程永远不能用其他核:原生工作、运行时后台及worker threads会改变情况。增加进程、调整渲染/缓存或优化代码前,测每进程CPU、循环延迟、内存/GC、I/O与后台等待。
PHP-FPM官方进程池设置约束并发请求和生命周期。另一个稳定示例:每秒200请求开始worker执行,平均占用0.15秒,则平均约30个worker被占用。这不直接规定60个子进程、CPU核或数据库连接,不能用p95替代平均。
若示例每worker增量/私有内存预算100MiB,60个需6,000MiB≈5.86GiB,尚未算OS、其他服务与共享内存。不要将共享OPcache重复累加为私有。测真实峰值及下游连接/CPU上限;增加FPM并发可能压垮数据库,而非增加有效吞吐。
用安全代表请求预热合适进程模式和缓存。关闭OPcache时间检查需要在发布时刷新实际服务进程;一项照抄设置或CLI重置不保证部署安全。进程/容器也可能启动预热很慢,秒级响应应实测。
仅对规划表,假设相同应用实例在选定目标下,可维持代表组合每秒220源站请求,峰值440。乘法是临时预算,不是实测线性增长。这里只损失一个实例,不是整台主机或可用区。
三个名义660,少一个剩440,刚好峰值,没有余量;四个名义880,少一个剩660,是目标1.5倍。放在同一机器不代表四个独立故障域,应测试打算承受的主机/区域故障。
| 实例数 | 名义req/s | 少一个后req/s | 与440峰值比较 |
|---|---|---|---|
| 2 | 440 | 220 | 故障后220,低于峰值 |
| 3 | 660 | 440 | 440刚好峰值,无余量 |
| 4 | 880 | 660 | 660为待验证余量 |
数据库写入、池连接、缓存/锁争用、支付物流配额、网络及后台工作可能更早限制全系统。别解决一层饱和却淹没另一层。用背压、有限工作和业务归属,延后任务也要有时效目标和恢复预算。
NGINX least_conn按活动连接及权重选择,不理解全部业务成本,也不等同于最少未完成请求算法。长连接、多路复用、请求组合和上游限制影响选择,应按真实负载比较,轮询并非天然错误。

首个响应丢失后重试上游,可能重复已发生作用。NGINX重试规则限制何时另试,但方法名称和代理配置不能取代应用幂等。不要把支付错误变成无差别POST重试。保留持久业务身份,查询未知结果,对允许重试采用有限退避/抖动、次数/年龄上限与负责人。
在维护业务承诺的边界准入/限流,提供可理解状态与安全返回方式。避免无限队列在告知失败后又执行成功。队列年龄应统计合格就绪工作,不含故意未来计划任务。区分已接受/待处理/完成订单、库存预留、已扣款及已交付。
到达、活动工作、恢复积压和最低故障容量允许时才缩容。排空并监督退出,等待或安全恢复所属工作,保留对账证据。活动结束的计时器不代表支付和履约义务结束。
测试前定义业务成功、错误/超时上限与延迟目标。按真实比例加入浏览、搜索、变体、购物车、登录及获授权结账夹具,包含缓存未命中与重试。隔离外部作用,防止演练真的扣客户款或发货。
k6区分开放和封闭负载模型。阶跃到达测试不能让慢响应悄悄降低所提供需求。到达率迭代可包含多次请求,应看真实发送/完成速率、丢弃迭代与发生器能力,而非只看配置虚拟用户。
验证目标阶跃、持续峰值、合理更高情景、冷缓存/失效、实例故障及安全缩容。记录尾延迟、业务结果、准入/拒绝及分层等待。按约定上限与人工停止路径中止,CPU保护单独发现不了重复扣款。改变一个关键约束后重测相关情景。
午夜示例中,准备好的团队能指出哪些实例提前就绪、故障后还剩多少、超载如何处理。只有整合测试才能说明440请求组合是否达标。要求供应商,包括StoreConsole,在实际所售版本、模块与部署上展示证据。
审阅于2026年11月5日。Anichur Rahaman,StoreConsole创建者。流量、时间、内存和容量均为规划示例,不是已执行测试或产品吞吐保证。
系列
高并发系统工程作者简介
Anichur Rahaman
继续阅读