🇬🇧 English version | 📦 GitHub: https://github.com/geekchow/aws-lambda-guide
背景: 本文选自开源学习指南《AWS Lambda 心智模型》(中英双语)。全书用一个贯穿示例串联:网店 ShopFast 的
checkout函数,周四通过prod别名把 v7 金丝雀发布到 v8,周五黑五开售前把预置并发(PC,Provisioned Concurrency)提到 400;文中的"第 N 步"即指该示例中的步骤,完整场景见 04 贯穿示例。
你在这里: 第 5 阶段,深入 3 / 7。示例第 3 步(金丝雀期间预热池拆分)、第 6 步(PC 扩到 400)、第 7 步(09:00 全热的第一波)、第 8 步(Bob 溢出)。读完本文你将知道: PC(Provisioned Concurrency,预置并发)究竟预先创建了什么、它的生命周期、溢出如何发生、如何扩缩、成本几何,以及它如何失败。
1. 角色回顾
负责: 为某个版本或别名保持 N 个已初始化的执行环境就绪。出场于: 第 3 步(预热池跟随加权别名)、第 6 步(08:30 扩到 400)、第 7 步(09:00 第一波全部热服务)、第 8 步(池耗尽 → Bob 溢出)。
2. 内部设计
2.1 "预置"的精确含义
按需环境在第一个请求内部 运行 Init 阶段(启动扩展、引导运行时、执行你的顶层代码)。PC 把 Init 提前:
#mermaid-svg-FVLJJt6gUvXwFGNG{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-FVLJJt6gUvXwFGNG .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-FVLJJt6gUvXwFGNG .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-FVLJJt6gUvXwFGNG .error-icon{fill:#552222;}#mermaid-svg-FVLJJt6gUvXwFGNG .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-FVLJJt6gUvXwFGNG .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-FVLJJt6gUvXwFGNG .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-FVLJJt6gUvXwFGNG .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-FVLJJt6gUvXwFGNG .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-FVLJJt6gUvXwFGNG .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-FVLJJt6gUvXwFGNG .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-FVLJJt6gUvXwFGNG .marker{fill:#333333;stroke:#333333;}#mermaid-svg-FVLJJt6gUvXwFGNG .marker.cross{stroke:#333333;}#mermaid-svg-FVLJJt6gUvXwFGNG svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-FVLJJt6gUvXwFGNG p{margin:0;}#mermaid-svg-FVLJJt6gUvXwFGNG .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-FVLJJt6gUvXwFGNG .cluster-label text{fill:#333;}#mermaid-svg-FVLJJt6gUvXwFGNG .cluster-label span{color:#333;}#mermaid-svg-FVLJJt6gUvXwFGNG .cluster-label span p{background-color:transparent;}#mermaid-svg-FVLJJt6gUvXwFGNG .label text,#mermaid-svg-FVLJJt6gUvXwFGNG span{fill:#333;color:#333;}#mermaid-svg-FVLJJt6gUvXwFGNG .node rect,#mermaid-svg-FVLJJt6gUvXwFGNG .node circle,#mermaid-svg-FVLJJt6gUvXwFGNG .node ellipse,#mermaid-svg-FVLJJt6gUvXwFGNG .node polygon,#mermaid-svg-FVLJJt6gUvXwFGNG .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-FVLJJt6gUvXwFGNG .rough-node .label text,#mermaid-svg-FVLJJt6gUvXwFGNG .node .label text,#mermaid-svg-FVLJJt6gUvXwFGNG .image-shape .label,#mermaid-svg-FVLJJt6gUvXwFGNG .icon-shape .label{text-anchor:middle;}#mermaid-svg-FVLJJt6gUvXwFGNG .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-FVLJJt6gUvXwFGNG .rough-node .label,#mermaid-svg-FVLJJt6gUvXwFGNG .node .label,#mermaid-svg-FVLJJt6gUvXwFGNG .image-shape .label,#mermaid-svg-FVLJJt6gUvXwFGNG .icon-shape .label{text-align:center;}#mermaid-svg-FVLJJt6gUvXwFGNG .node.clickable{cursor:pointer;}#mermaid-svg-FVLJJt6gUvXwFGNG .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-FVLJJt6gUvXwFGNG .arrowheadPath{fill:#333333;}#mermaid-svg-FVLJJt6gUvXwFGNG .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-FVLJJt6gUvXwFGNG .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-FVLJJt6gUvXwFGNG .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-FVLJJt6gUvXwFGNG .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-FVLJJt6gUvXwFGNG .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-FVLJJt6gUvXwFGNG .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-FVLJJt6gUvXwFGNG .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-FVLJJt6gUvXwFGNG .cluster text{fill:#333;}#mermaid-svg-FVLJJt6gUvXwFGNG .cluster span{color:#333;}#mermaid-svg-FVLJJt6gUvXwFGNG div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-FVLJJt6gUvXwFGNG .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-FVLJJt6gUvXwFGNG rect.text{fill:none;stroke-width:0;}#mermaid-svg-FVLJJt6gUvXwFGNG .icon-shape,#mermaid-svg-FVLJJt6gUvXwFGNG .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-FVLJJt6gUvXwFGNG .icon-shape p,#mermaid-svg-FVLJJt6gUvXwFGNG .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-FVLJJt6gUvXwFGNG .icon-shape .label rect,#mermaid-svg-FVLJJt6gUvXwFGNG .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-FVLJJt6gUvXwFGNG .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-FVLJJt6gUvXwFGNG .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-FVLJJt6gUvXwFGNG :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 预置: Init 提前完成
环境空闲等待
配置 PC
提前数分钟
启动 + Init
不在请求路径上
请求到达
Handler:
150 ms
按需冷启动: 在请求内部
请求到达
启动微虚拟机
- 拉取代码
Init:
约 600 ms
Handler:
150 ms
图注:PC 不会让代码变快------它把启动 + Init 移出请求的延迟。
关键推论:
- Init 时机不同。 对 PC 而言,Init 可能在首次调用前数分钟甚至数小时运行,且 10 秒 Init 限制被放宽(最长 15 分钟)。不要在 Init 中假设请求马上到来,比如计算"请求开始时间"或拉取短期令牌。
- 代码可以分辨。
AWS_LAMBDA_INITIALIZATION_TYPE的值为provisioned-concurrency(对应还有on-demand、snap-start)。 - 环境仍会被回收。 Lambda 会定期替换 PC 环境(与其他环境一样),并在淘汰旧环境之前预初始化替代者,所以 Init 会再次运行------保持它幂等。
- 一个环境一个请求 依然成立:PC = 400 意味着 400 个同时的热调用,而不是 400 RPS(Requests Per Second,每秒请求数)。
2.2 PC 可以挂在哪里
| 目标 | 允许? |
|---|---|
已发布版本(checkout:8) |
是 |
别名(checkout:prod) |
是------跟随别名;若加权则拆分到 2 个版本 |
$LATEST,或指向 $LATEST 的别名 |
否 |
| 同时挂在别名和它指向的版本上 | 否(冲突) |
PC 从并发限额中划出:它计入函数的预留并发(若设置了 RC(Reserved Concurrency,预留并发),则 PC ≤ RC),也计入账号限额(始终保留 100 未预留)。
2.3 生命周期
#mermaid-svg-Hq9Ial7Hh9NlzZiO{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-Hq9Ial7Hh9NlzZiO .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Hq9Ial7Hh9NlzZiO .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Hq9Ial7Hh9NlzZiO .error-icon{fill:#552222;}#mermaid-svg-Hq9Ial7Hh9NlzZiO .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Hq9Ial7Hh9NlzZiO .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Hq9Ial7Hh9NlzZiO .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Hq9Ial7Hh9NlzZiO .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Hq9Ial7Hh9NlzZiO .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Hq9Ial7Hh9NlzZiO .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Hq9Ial7Hh9NlzZiO .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Hq9Ial7Hh9NlzZiO .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Hq9Ial7Hh9NlzZiO .marker.cross{stroke:#333333;}#mermaid-svg-Hq9Ial7Hh9NlzZiO svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Hq9Ial7Hh9NlzZiO p{margin:0;}#mermaid-svg-Hq9Ial7Hh9NlzZiO defs #statediagram-barbEnd{fill:#333333;stroke:#333333;}#mermaid-svg-Hq9Ial7Hh9NlzZiO g.stateGroup text{fill:#9370DB;stroke:none;font-size:10px;}#mermaid-svg-Hq9Ial7Hh9NlzZiO g.stateGroup text{fill:#333;stroke:none;font-size:10px;}#mermaid-svg-Hq9Ial7Hh9NlzZiO g.stateGroup .state-title{font-weight:bolder;fill:#131300;}#mermaid-svg-Hq9Ial7Hh9NlzZiO g.stateGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-Hq9Ial7Hh9NlzZiO g.stateGroup line{stroke:#333333;stroke-width:1;}#mermaid-svg-Hq9Ial7Hh9NlzZiO .transition{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-Hq9Ial7Hh9NlzZiO .stateGroup .composit{fill:white;border-bottom:1px;}#mermaid-svg-Hq9Ial7Hh9NlzZiO .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px;}#mermaid-svg-Hq9Ial7Hh9NlzZiO .state-note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-Hq9Ial7Hh9NlzZiO .state-note text{fill:black;stroke:none;font-size:10px;}#mermaid-svg-Hq9Ial7Hh9NlzZiO .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-Hq9Ial7Hh9NlzZiO .edgeLabel .label rect{fill:#ECECFF;opacity:0.5;}#mermaid-svg-Hq9Ial7Hh9NlzZiO .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Hq9Ial7Hh9NlzZiO .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-Hq9Ial7Hh9NlzZiO .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Hq9Ial7Hh9NlzZiO .edgeLabel .label text{fill:#333;}#mermaid-svg-Hq9Ial7Hh9NlzZiO .label div .edgeLabel{color:#333;}#mermaid-svg-Hq9Ial7Hh9NlzZiO .stateLabel text{fill:#131300;font-size:10px;font-weight:bold;}#mermaid-svg-Hq9Ial7Hh9NlzZiO .node circle.state-start{fill:#333333;stroke:#333333;}#mermaid-svg-Hq9Ial7Hh9NlzZiO .node .fork-join{fill:#333333;stroke:#333333;}#mermaid-svg-Hq9Ial7Hh9NlzZiO .node circle.state-end{fill:#9370DB;stroke:white;stroke-width:1.5;}#mermaid-svg-Hq9Ial7Hh9NlzZiO .end-state-inner{fill:white;stroke-width:1.5;}#mermaid-svg-Hq9Ial7Hh9NlzZiO .node rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Hq9Ial7Hh9NlzZiO .node polygon{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Hq9Ial7Hh9NlzZiO #statediagram-barbEnd{fill:#333333;}#mermaid-svg-Hq9Ial7Hh9NlzZiO .statediagram-cluster rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Hq9Ial7Hh9NlzZiO .cluster-label,#mermaid-svg-Hq9Ial7Hh9NlzZiO .nodeLabel{color:#131300;}#mermaid-svg-Hq9Ial7Hh9NlzZiO .statediagram-cluster rect.outer{rx:5px;ry:5px;}#mermaid-svg-Hq9Ial7Hh9NlzZiO .statediagram-state .divider{stroke:#9370DB;}#mermaid-svg-Hq9Ial7Hh9NlzZiO .statediagram-state .title-state{rx:5px;ry:5px;}#mermaid-svg-Hq9Ial7Hh9NlzZiO .statediagram-cluster.statediagram-cluster .inner{fill:white;}#mermaid-svg-Hq9Ial7Hh9NlzZiO .statediagram-cluster.statediagram-cluster-alt .inner{fill:#f0f0f0;}#mermaid-svg-Hq9Ial7Hh9NlzZiO .statediagram-cluster .inner{rx:0;ry:0;}#mermaid-svg-Hq9Ial7Hh9NlzZiO .statediagram-state rect.basic{rx:5px;ry:5px;}#mermaid-svg-Hq9Ial7Hh9NlzZiO .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#f0f0f0;}#mermaid-svg-Hq9Ial7Hh9NlzZiO .note-edge{stroke-dasharray:5;}#mermaid-svg-Hq9Ial7Hh9NlzZiO .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-Hq9Ial7Hh9NlzZiO .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-Hq9Ial7Hh9NlzZiO .statediagram-note text{fill:black;}#mermaid-svg-Hq9Ial7Hh9NlzZiO .statediagram-note .nodeLabel{color:black;}#mermaid-svg-Hq9Ial7Hh9NlzZiO .statediagram .edgeLabel{color:red;}#mermaid-svg-Hq9Ial7Hh9NlzZiO #dependencyStart,#mermaid-svg-Hq9Ial7Hh9NlzZiO #dependencyEnd{fill:#333333;stroke:#333333;stroke-width:1;}#mermaid-svg-Hq9Ial7Hh9NlzZiO .statediagramTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-Hq9Ial7Hh9NlzZiO :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} PutProvisioned
ConcurrencyConfig
N 个环境
全部初始化
Init 出错 /
容量问题
N 改变,或别名
目标/权重改变
修复后重新设置
DeleteProvisioned
ConcurrencyConfig
IN_PROGRESS
READY
FAILED
图注:PC 是异步的------你请求 N,Lambda 报告 Allocated 逐步逼近 N,然后变为 READY。
数百个环境的分配通常需要一到几分钟;它同样受函数级扩缩速率约束(每 10 秒新增 1,000 个环境)。
2.4 溢出:PC 是下限,绝不是上限
#mermaid-svg-i23yenpXNgofhvGJ{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-i23yenpXNgofhvGJ .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-i23yenpXNgofhvGJ .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-i23yenpXNgofhvGJ .error-icon{fill:#552222;}#mermaid-svg-i23yenpXNgofhvGJ .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-i23yenpXNgofhvGJ .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-i23yenpXNgofhvGJ .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-i23yenpXNgofhvGJ .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-i23yenpXNgofhvGJ .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-i23yenpXNgofhvGJ .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-i23yenpXNgofhvGJ .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-i23yenpXNgofhvGJ .marker{fill:#333333;stroke:#333333;}#mermaid-svg-i23yenpXNgofhvGJ .marker.cross{stroke:#333333;}#mermaid-svg-i23yenpXNgofhvGJ svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-i23yenpXNgofhvGJ p{margin:0;}#mermaid-svg-i23yenpXNgofhvGJ .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-i23yenpXNgofhvGJ .cluster-label text{fill:#333;}#mermaid-svg-i23yenpXNgofhvGJ .cluster-label span{color:#333;}#mermaid-svg-i23yenpXNgofhvGJ .cluster-label span p{background-color:transparent;}#mermaid-svg-i23yenpXNgofhvGJ .label text,#mermaid-svg-i23yenpXNgofhvGJ span{fill:#333;color:#333;}#mermaid-svg-i23yenpXNgofhvGJ .node rect,#mermaid-svg-i23yenpXNgofhvGJ .node circle,#mermaid-svg-i23yenpXNgofhvGJ .node ellipse,#mermaid-svg-i23yenpXNgofhvGJ .node polygon,#mermaid-svg-i23yenpXNgofhvGJ .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-i23yenpXNgofhvGJ .rough-node .label text,#mermaid-svg-i23yenpXNgofhvGJ .node .label text,#mermaid-svg-i23yenpXNgofhvGJ .image-shape .label,#mermaid-svg-i23yenpXNgofhvGJ .icon-shape .label{text-anchor:middle;}#mermaid-svg-i23yenpXNgofhvGJ .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-i23yenpXNgofhvGJ .rough-node .label,#mermaid-svg-i23yenpXNgofhvGJ .node .label,#mermaid-svg-i23yenpXNgofhvGJ .image-shape .label,#mermaid-svg-i23yenpXNgofhvGJ .icon-shape .label{text-align:center;}#mermaid-svg-i23yenpXNgofhvGJ .node.clickable{cursor:pointer;}#mermaid-svg-i23yenpXNgofhvGJ .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-i23yenpXNgofhvGJ .arrowheadPath{fill:#333333;}#mermaid-svg-i23yenpXNgofhvGJ .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-i23yenpXNgofhvGJ .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-i23yenpXNgofhvGJ .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-i23yenpXNgofhvGJ .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-i23yenpXNgofhvGJ .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-i23yenpXNgofhvGJ .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-i23yenpXNgofhvGJ .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-i23yenpXNgofhvGJ .cluster text{fill:#333;}#mermaid-svg-i23yenpXNgofhvGJ .cluster span{color:#333;}#mermaid-svg-i23yenpXNgofhvGJ div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-i23yenpXNgofhvGJ .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-i23yenpXNgofhvGJ rect.text{fill:none;stroke-width:0;}#mermaid-svg-i23yenpXNgofhvGJ .icon-shape,#mermaid-svg-i23yenpXNgofhvGJ .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-i23yenpXNgofhvGJ .icon-shape p,#mermaid-svg-i23yenpXNgofhvGJ .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-i23yenpXNgofhvGJ .icon-shape .label rect,#mermaid-svg-i23yenpXNgofhvGJ .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-i23yenpXNgofhvGJ .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-i23yenpXNgofhvGJ .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-i23yenpXNgofhvGJ :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 有
没有
有
没有
已准入的 v8 请求
有空闲的
v8 PC 环境?
在热 PC 环境运行
无冷启动
有可复用的
空闲按需环境?
热运行
按需价格
新建按需环境:
冷启动
图注:PC 耗尽时请求溢出到按需而不是失败------限流是计数服务更早做出的另一项决策(05.4)。
需要关注的指标(使用 Maximum 统计):
| 指标 | 含义 |
|---|---|
ProvisionedConcurrentExecutions |
此刻忙碌的 PC 环境数 |
ProvisionedConcurrencyUtilization |
忙碌数 ÷ 已分配数(0--1) |
ProvisionedConcurrencyInvocations |
由 PC 服务的调用数 |
ProvisionedConcurrencySpilloverInvocations |
没有拿到 PC 环境的调用数 |
2.5 用 Application Auto Scaling 扩缩 PC
PC 本身是一个静态数字。Application Auto Scaling 替你改变这个数字:
- 计划扩缩(Scheduled scaling)------用于已知事件(黑五、09:00 开市)。可靠,因为它在需求之前行动。
- 目标跟踪(Target tracking) ,基于
LambdaProvisionedConcurrencyUtilization(如目标 0.7)。被动式:依赖 CloudWatch 告警对若干个 1 分钟数据点的评估(约 3 分钟后扩容,缩容慢得多),所以它抓不住 30 秒的尖峰。要与计划的最小值搭配使用。
2.6 成本模型
只要 PC 处于配置状态,无论忙闲都要付费;运行时则按更低 的时长单价计费。us-east-1 x86 的示意价格(请以定价页为准,价格会变):
| 收费项 | 按需 | 使用 PC |
|---|---|---|
| 保持环境预热(每配置 GB-s(Gigabyte-second,GB 秒)) | ------ | ≈ $0.0000041667 |
| 时长(每执行 GB-s) | ≈ $0.0000166667 | ≈ $0.0000097222 |
| 请求 | 每百万 $0.20 | 相同 |
经验法则:利用率持续高于约 60% 时,PC 比按需更便宜;低于此值时,你是在花钱买延迟,而不是省钱。SnapStart(Java、Python、.NET)是没有闲置成本的替代方案:它在发布时给已初始化的环境打快照,冷启动时从快照恢复------冷启动更快,但不是零。
3. 交互
| 邻居 | 契约 |
|---|---|
| 别名路由(05.2) | 别名上的 PC 跟随其版本;权重变化触发重新分配。 |
| 计数服务(05.4) | PC 计入预留/账号并发;PC 不准入也不拒绝请求。 |
| 分配 + 放置(05.5) | PC 管理器请放置服务创建 N 个环境,并向分配服务登记为"预置、空闲"。 |
| 执行环境(05.6) | Init 在分配时运行;handler 在请求时运行。 |
| Application Auto Scaling | 负责随时间改变 N;Lambda 只执行最新的 N。 |
4. ⚓ 回到示例------第 3、6、7、8 步
周四之前, prod 有 PC 50,全部在 v7 上:
bash
aws lambda put-provisioned-concurrency-config \
--function-name checkout --qualifier prod \
--provisioned-concurrent-executions 50
第 3 步------周四 14:01 ,别名变为 v7 90% / v8 10%。PC 管理器重新分配,约 45 个热环境服务 v7、5 个服务 v8(切换期间 AllocatedProvisionedConcurrentExecutions 会波动)。Alice 的请求(第 4 步)找到了 5 个热 v8 环境之一。周四下午流量约 20 并发,5 个绰绰有余;若是更忙的日子,团队会在金丝雀窗口调高 PC。
第 6 步------周五 08:30,周一注册的计划任务触发:
bash
aws application-autoscaling register-scalable-target \
--service-namespace lambda \
--resource-id function:checkout:prod \
--scalable-dimension lambda:function:ProvisionedConcurrency \
--min-capacity 50 --max-capacity 600
aws application-autoscaling put-scheduled-action \
--service-namespace lambda \
--resource-id function:checkout:prod \
--scalable-dimension lambda:function:ProvisionedConcurrency \
--scheduled-action-name black-friday-open \
--schedule "at(2026-11-27T08:30:00)" \
--scalable-target-action MinCapacity=400,MaxCapacity=600
aws application-autoscaling put-scaling-policy \
--service-namespace lambda \
--resource-id function:checkout:prod \
--scalable-dimension lambda:function:ProvisionedConcurrency \
--policy-name pc-utilization-70 --policy-type TargetTrackingScaling \
--target-tracking-scaling-policy-configuration \
'{"TargetValue":0.7,"PredefinedMetricSpecification":{"PredefinedMetricType":"LambdaProvisionedConcurrencyUtilization"}}'
prod 的 PC 变为 IN_PROGRESS;放置服务再创建 350 个 v8 环境,每个都以 AWS_LAMBDA_INITIALIZATION_TYPE=provisioned-concurrency 记录一次 Init。到约 08:33:
bash
aws lambda get-provisioned-concurrency-config --function-name checkout --qualifier prod
# { "RequestedProvisionedConcurrentExecutions": 400,
# "AllocatedProvisionedConcurrentExecutions": 400,
# "AvailableProvisionedConcurrentExecutions": 400, "Status": "READY" }
第 7 步------09:00:2,000 RPS × 0.15 秒 ≈ 300 并发。利用率 = 300/400 = 0.75;溢出 = 0。每位顾客都在约 150 毫秒内完成。
第 8 步------09:05 :需求约 675 并发。400 个跑在 PC 上;约 275 个计入 ProvisionedConcurrencySpilloverInvocations。Bob 的请求就是其中之一 → 冷的按需环境,多出约 600 毫秒。目标跟踪看到利用率 1.0,开始把 PC 推向 600------但它的告警需要数分钟,所以尖峰的第一波仍要付出冷启动。明年的经验教训:计划值设为 700。
5. 失败行为
| 失败 | 症状 | 应对 |
|---|---|---|
| PC 环境中 Init 抛异常 | 状态 FAILED;部署报错 "Invalid alias configuration for provisioned concurrency" |
把别名回滚到上一个正常版本;修复 Init;发布新版本。 |
| PC 耗尽 | 溢出 → 冷启动(而不是错误) | 在已知高峰前计划扩容;对溢出设告警。 |
| PC 大于预留并发或账号余量 | put-provisioned-concurrency-config 被拒 |
先提高 RC / 账号限额。 |
新版本 PC 未 READY 就切换别名 |
新版本冷启动 | 等待 READY;加权切换期间超额预置。 |
| 忘了缩容 | 整个周末为闲置的 600 个环境付费 | 计划缩容任务;预算告警。 |
下一篇 → 05.4 调用前端与并发 · 返回 03 概念地图
📚 返回专栏目录