异构调度、Kubernetes 调度器、GPU 任务绑定、MIG 分配、推理流量调度、服务亲和性、任务隔离、资源优先级、边缘协同、动态算力管理
在 AI 推理系统的生产级部署中,单一自动扩缩容机制已无法满足实际复杂环境中对资源利用率、任务延迟与系统稳定性的多重要求。特别是在 GPU/NPU/CPU 并存的异构计算集群中,运行时的动态负载调度与智能资源分配成为系统性能的核心瓶颈。本文围绕异构推理系统中的“多节点协同调度”、“推理任务绑定机制”、“请求级资源感知分发策略”等关键技术展开系统解析,结合 Kubernetes 原生调度器与自定义调度插件的工程实践路径,提供一套完整的智能推理调度方案,实现高吞吐、低延迟与资源复用率最大化并存的工程目标。
推理服务调度核心问题与异构场景分类
1.1 推理请求流量特性与调度难点分析
1.2 异构计算资源分类(GPU/NPU/CPU)与场景剖面
1.3 多目标调度目标函数建模(延迟、成本、隔离)
Kubernetes 原生调度器机制解构与能力边界
2.1 默认调度策略执行路径解析
2.2 资源亲和性(Affinity)、污点容忍与优先级机制
2.3 Scheduler Extender 与 Scheduling Framework 插件机制
自定义调度器实现:异构算力节点动态匹配策略
3.1 节点分级标签设计与算力评分函数构建
3.2 推理任务 QoS 等级控制与调度优先级模型
3.3 实时调度器实现流程与跨资源池调度决策
多模型推理服务的任务绑定与 GPU 隔离策略
4.1 多副本服务的 GPU 亲和性绑定配置
4.2 NVIDIA MPS 与 MIG 实战配置与容器级隔离
4.3 多模型场景下的资源预留与动态配额策略
请求级智能分发与协同推理执行路径
5.1 基于任务类型的流量路由机制设计
5.2 GPU 使用率感知分发器设计(延迟预测 + 资源状态)
5.3 实战部署:推理请求从入口到执行的路径映射与性能分析
案例分析与调度优化验证数据
6.1 多 GPU 节点调度效果对比测试结果
6.2 各策略下系统资源利用率与延迟评估
6.3 故障节点隔离、调度回退与任务重试机制验证
在现代 AI 应用场景中,推理请求呈现出明显的高动态、高并发、高异质特征。以下为来自某头部互联网公司在线推理平台(部署 47 个模型服务,日均 30 亿次调用)真实采样的请求数据统计:
时间区间 | 峰值 QPS(单模型) | 请求分布偏差 | 平均响应时延(P95) | 典型模型类型 |
---|---|---|---|---|
08:00 - 12:00 | 5200 | 高频、稳定 | 11.3 ms | 图像识别、OCR |
14:00 - 18:00 | 6700 | 峰值突增 | 17.5 ms | 多轮问答、语义分类 |
21:00 - 01:00 | 3200 | 流量切换频繁 | 25.9 ms | 大语言模型、长文本摘要 |
从运行时行为可总结出以下调度挑战:
这些问题说明,推理服务调度不能仅依赖副本数控制(如 HPA/KEDA),而必须结合运行时任务的类型、优先级、资源需求进行精细化任务调度与算力分配策略设计。
AI 推理服务涉及的异构算力通常包含以下三类计算单元:
类型 | 特征描述 | 常见部署平台 | 适用任务类型 |
---|---|---|---|
GPU | 高吞吐、支持并行、编程生态完善 | NVIDIA A100/V100、RTX 系列 | 通用 CNN、Transformer 模型 |
NPU | 面向推理优化、低功耗、适合边缘侧 | 华为昇腾、寒武纪 MLU、MediaTek APU | 视频分析、语音合成、轻量模型 |
CPU | 通用计算、高稳定性、适合非并行或低延迟任务 | Intel Xeon、ARM Core、边缘嵌入式平台 | 文本后处理、数据整合、特征计算 |
应用场景 | 调度目标节点优先级 |
---|---|
智能语音助手系统 | CPU(控制/后处理) → NPU(唤醒词) → GPU(语义理解) |
自动驾驶感知系统 | NPU(摄像头前端) → GPU(融合推理) |
智能客服平台 | GPU(大模型推理) → CPU(结构化结果处理) |
系统必须感知每个推理任务的执行特征、模型结构与部署资源的算力边界,构建运行时调度路径与资源优先级图谱,实现按任务类型动态匹配最优执行位置。
推理调度本质上是一个资源约束下的多目标最优化问题。调度目标不仅限于资源占用与吞吐,还包括服务质量、安全隔离、能耗约束等指标。常见目标函数包括:
Min Σ_i W_i * T_i
,其中 T_i 为第 i 类任务平均延迟,W_i 为其业务权重;Max Σ_j GPU_Util_j / GPU_Capacity_j
;Min Σ_k E_k * R_k
,E_k 为设备能耗指标,R_k 为资源使用量;综合上述目标,系统应设计支持以下调度维度:
Kubernetes 原生调度器(kube-scheduler
)负责将未绑定 Node 的 Pod 分配到合适的节点上。在默认配置下,其调度过程主要分为两个阶段:
该阶段主要过滤掉不符合调度条件的节点,例如:
执行模块位于 FilterPlugins
,例如:
filters:
- name: NodeResourcesFit # 检查 CPU / 内存 是否足够
- name: NodeAffinity # 匹配 NodeSelector / Affinity
- name: TaintToleration # 处理污点容忍逻辑
在通过过滤的节点中打分排序,选出优先级最高的节点。常用的打分插件包括:
插件名 | 作用说明 |
---|---|
NodeResourcesBalancedAllocation | 选择 CPU/内存负载更均衡的节点 |
ImageLocality | 优先调度到已缓存镜像的节点 |
TopologySpreadConstraint | 控制任务跨节点分布,避免单点过载 |
NodePreferAvoidPods | 基于软亲和性的调度优先级 |
默认调度算法会给每个打分项一个权重,并最终计算加权平均分,选择得分最高节点绑定 Pod。
调度器通过 SchedulerConfiguration
进行参数配置,示例如下:
apiVersion: kubescheduler.config.k8s.io/v1
kind: KubeSchedulerConfiguration
profiles:
- schedulerName: default-scheduler
plugins:
score:
enabled:
- name: NodeResourcesBalancedAllocation
- name: ImageLocality
虽然 Kubernetes 默认调度器可满足通用资源调度需求,但在以下方面存在能力边界:
因此,为适配复杂的 AI 推理场景,需要借助原生调度框架的扩展机制来构建异构感知的智能调度策略。
Kubernetes 提供三种基本调度策略控制机制,可作为自定义调度策略的基础:
配置示例(GPU 类型节点绑定):
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: nvidia.com/gpu.arch
operator: In
values:
- ampere
允许节点标记“不可容忍”的属性(如预留节点、专属资源),防止无关任务被调度。
示例:
kubectl taint nodes node-a gpu-only=true:NoSchedule
Pod 配置:
tolerations:
- key: "gpu-only"
operator: "Equal"
value: "true"
effect: "NoSchedule"
用于定义不同 Pod 的调度优先级,结合抢占机制决定在资源不足时优先调度哪类任务。
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: high-priority
value: 100000
globalDefault: false
description: "Priority for latency-sensitive inference jobs"
通过合理配置 Affinity
、Taints
与 PriorityClass
,可在调度器仍使用默认逻辑的前提下实现部分基础的资源控制与任务隔离。
为了实现更高阶的自定义调度逻辑,Kubernetes 提供了两种扩展机制:
K8s 1.19+ 起主推的插件式调度架构,支持完整调度流程的可插拔控制:
插件阶段 | 功能说明 |
---|---|
PreFilter | 在调度开始前做参数预处理 |
Filter | 过滤掉不合适节点 |
Score | 对候选节点打分排序 |
Reserve | 资源预留,阻止并发调度冲突 |
Permit | 调度器最终决策前拦截 |
PreBind | Pod 与 Node 绑定前执行验证逻辑 |
Bind | 执行绑定动作,可自定义绑定行为 |
插件以 Golang 实现,并通过调度配置 KubeSchedulerConfiguration
加载。在异构推理系统中,可实现如下插件逻辑:
Filter
阶段排除 GPU 满载节点;Score
阶段根据显存剩余 + 任务优先级加权评分;Permit
阶段为高优先级模型独占节点保留资源。调度器插件开发框架已被社区成熟支持(如 Volcano、Koordinator、Openkruise),具备丰富的调度优化能力与企业级场景落地基础。
为实现动态调度与精准资源匹配,必须在节点层进行明确的能力标注,提供给调度器可供决策的静态与动态信息。通常应从以下两类标签维度进行建模:
kubectl label node node-a nvidia.com/gpu.arch=ampere
kubectl label node node-b edge.npu.enabled=true
kubectl label node node-c node.tier=gold
{
"nodeName": "node-a",
"metrics": {
"gpu_0_utilization": 74,
"gpu_0_memory_used": 7832,
"gpu_temperature": 65
}
}
调度器应基于上述标签构建分数函数(Scoring Function),按以下维度对候选节点打分:
因子 | 示例指标 | 分数映射逻辑 |
---|---|---|
GPU 利用率 | gpu_0_utilization |
利用率越低越优,线性反向打分 |
GPU 显存空余 | gpu_memory_free |
空余越大越优;可按比例打分 |
GPU 架构匹配度 | nvidia.com/gpu.arch |
完全匹配得分高,兼容匹配居中,不兼容为 0 |
模型运行适配性 | Pod 标签 vs Node Label | 若节点具备 model.family=transformer ,得高分 |
任务优先级权重 | PriorityClass.value |
高优先级 Pod 在低资源节点得分降低,避免降级运行 |
组合打分函数示例:
finalScore = 0.4 * (1 - GPU_Utilization/100) +
0.3 * (GPU_Mem_Free / Total_GPU_Mem) +
0.2 * ArchitectureMatchScore +
0.1 * TaskPriorityPenalty
调度器将所有候选节点打分后,选择得分最高节点绑定 Pod,实现按资源负载、任务特征动态优选调度。
在异构推理场景中,任务类型差异极大,应构建运行时 QoS(Quality of Service)模型 与调度等级体系,提升资源利用效率与服务隔离性。
级别 | 特征 | 应调度行为说明 |
---|---|---|
High | 实时性强,模型大,用户请求直接触发 | 固定部署在 A100/主力节点,独占调度 |
Medium | 计算密集,非实时,但需稳定响应 | 调度至任意 GPU 型节点,允许延迟容忍 |
Low | 异步任务、低频触发、冷启动可接受 | 可调度至低算力 GPU/NPU/CPU 节点 |
调度器应将 QoS 映射为调度策略,例如:
调度配置示例(Pod 标签):
metadata:
labels:
inference.qos: "high"
model.type: "transformer"
自定义调度器需从这些标签读取任务意图,并与节点标签比对,实现服务级的调度级别匹配。
为了在运行时实现真正“资源感知 + 策略驱动”的动态调度,需设计并实现一个具备以下能力的自定义调度器:
[Unscheduled Pods Queue]
↓
[调度主循环 Loop]
↓
1. 获取候选节点列表(Filter)
2. 拉取每个节点的动态资源指标
3. 执行打分函数(Score)
4. 选出最优节点
5. 进行调度绑定(Bind)
k8s.io/kubernetes/pkg/scheduler
提供的插件式接口;// Scheduler plugin scoring example
func (pl *GpuAwareScorer) Score(ctx context.Context, state *framework.CycleState,
pod *v1.Pod, nodeName string) (int64, *framework.Status) {
metrics := pl.metricCache.Get(nodeName)
score := calculateScore(metrics, pod)
return int64(score * 100), nil
}
pool=edge
)与 Pod 的服务意图对齐;最终构建出的自定义调度器可具备如下能力:
在多模型并行部署环境下,同一节点往往需要运行多个推理任务副本(如不同模型或不同版本)。如果不进行 GPU 亲和性与调度限制,很容易出现以下问题:
为此,需构建明确的 Pod ↔ GPU 显卡绑定策略,确保每个副本在独立 GPU 上运行,避免冲突。
nvidia.com/gpu
实现设备级调度隔离Kubernetes 原生支持通过 nvidia-device-plugin
将每块 GPU 显卡暴露为独立的 nvidia.com/gpu
资源,容器请求时将强制绑定到特定 GPU。
resources:
limits:
nvidia.com/gpu: 1
该配置在 kubelet 中生效,默认按设备顺序分配,每个 Pod 仅访问一张卡,物理隔离度高。
部署多个模型服务时,可利用 PodAntiAffinity
避免副本落在同一个节点:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- resnet50
topologyKey: "kubernetes.io/hostname"
此策略确保每个副本优先部署至不同物理节点,配合 GPU 资源隔离可最大限度避免资源争用。
在单节点多 GPU 场景下,如需手动指定 Pod 使用哪张显卡,可借助 NVIDIA 提供的 GPU Feature Discovery 为每张 GPU 打上 gpu-index
或 uuid
标签,再通过 NodeAffinity
实现精细调度。
nodeSelector:
nvidia.com/gpu.product: "A100-SXM4-40GB"
nvidia.com/gpu.uuid: "GPU-abcd-1234-5678"
此方式适用于对推理稳定性要求极高的模型(如大模型、多租户服务等)。
MPS 是 NVIDIA 提供的 GPU 多进程调度方案,允许多个进程共享同一 GPU,并实现资源隔离与并发执行优化,适用于小模型高并发场景。
export CUDA_MPS_ACTIVE_THREAD_PERCENTAGE=50
使用 MPS 时需在 GPU 上启动 MPS Daemon,并在容器启动前设置:
nvidia-cuda-mps-control -d
但 MPS 不具备硬件级隔离能力,不推荐用于多租户场景。
在 NVIDIA A100 / H100 GPU 上,推荐使用 MIG 技术将单张 GPU 划分为多个逻辑子设备(每个具备独立 SM、显存、Cache),并作为独立设备被 Kubernetes 调度。
启用 MIG:
sudo nvidia-smi -mig 1
sudo nvidia-smi mig -cgi 1g.10gb -C
此时,nvidia.com/gpu
将识别多个 MIG 实例为独立 GPU 资源,每个推理服务部署于独立 MIG 实例,完全隔离。
K8s 配置示例(假设已通过 Device Plugin 映射 MIG):
resources:
limits:
nvidia.com/mig-1g.10gb: 1
优点:
注意:MIG 实例需在 GPU 层事先规划好,资源调度粒度固定,不支持运行时动态重配。
在真实生产环境中,AI 平台通常需部署数十种模型服务,面临资源配置混乱、模型冷启动失败等问题,推荐引入以下控制机制:
使用 Koordinator 或自研 Operator,对关键模型服务预留资源,如:
结合 GPU 显存指标动态分配模型:
示例:
model.profile:
name: resnet50
memory_budget: 1400MB
expected_qps: 150
调度器结合实时 dcgm_fb_used
判断是否满足条件,避免加载失败或服务崩溃。
将模型服务的资源需求、QoS 策略、绑定规则通过 CRD 注册:
apiVersion: inference.io/v1
kind: ModelResourceProfile
metadata:
name: bert-large-v2
spec:
gpu: 1
memory: 12Gi
qos: high
nodeAffinity:
required:
- key: gpu.arch
operator: In
values: [ampere]
实现模型生命周期管理与资源统一调度策略集成。
通过 GPU 显卡绑定、MPS/MIG 隔离机制、任务标签与资源预留策略,推理系统在多模型部署下可实现:
在多模型服务协同运行的环境中,单一入口需要根据推理任务的模型类型、请求负载与资源适配性将请求分发至合适的模型副本与节点。核心目标包括:
路由条件 | 控制字段 | 分发策略 |
---|---|---|
模型名称 | model_name |
Hash 映射或 Header 匹配 |
模型版本 | version |
静态配置或动态热切换(A/B Testing) |
请求类型 | task_type |
多入口分流(图像 / 文本 / 视频) |
优先级等级 | priority |
高优任务直达主副本;低优延迟排队 |
部署建议使用 NGINX + Lua 或 Envoy + WASM 实现智能代理转发模块:
# 示例 Lua 脚本路由片段
if ngx.var.http_task_type == "text" then
ngx.var.upstream = "bert-infer-service"
elseif ngx.var.http_task_type == "image" then
ngx.var.upstream = "resnet-infer-service"
end
此方式可实现请求端零感知切换,确保服务稳定性与部署灵活性并存。
为了进一步提升资源利用效率与负载均衡精度,系统需在请求转发前引入资源状态感知机制,实现基于节点当前 GPU 利用率与队列压力的“最优副本”调度。
核心思路如下:
推荐使用 Redis / Etcd 构建节点状态缓存结构:
{
"resnet50-v1-pod-a": {
"gpu_util": 62.5,
"mem_used": 7832,
"pending": 12,
"latency_ms": 9.8
},
"resnet50-v1-pod-b": {
"gpu_util": 38.9,
"mem_used": 4120,
"pending": 4,
"latency_ms": 7.2
}
}
请求调度算法示例(可封装为服务):
def select_best_instance(instances):
return sorted(instances, key=lambda x: x['gpu_util'] + x['pending'])[0]
也可结合推理延迟预测模型(如 LightGBM 回归)对请求路径进行时延预估,从而在多个可选副本中选出预计耗时最低的目标。
[Client]
↓
[API Gateway / Ingress (NGINX/Envoy)]
↓ (Header / Payload 分析)
[Inference Router]
↓ (资源感知调度)
[Inference Service Pod (Triton/TensorRT/TVM)]
↓
[GPU / NPU 执行 → 输出]
建议在各个关键路径处加入链路追踪(Tracing)与延迟记录(Logging):
路径阶段 | 关键指标 |
---|---|
请求接入 | 请求数 QPS、Header 解析耗时 |
Router 调度 | 查询延迟、节点选择分布 |
模型推理执行 | GPU Util、显存占用、推理时延 |
全链路总延迟 | P50/P95/P99 延迟、异常率 |
指标类型 | 智能分发开启 | 智能分发关闭 |
---|---|---|
平均 GPU 利用率 | 72.3% | 56.8% |
副本间延迟方差(ms²) | 8.2 | 21.4 |
请求平均响应时延(ms) | 10.8 | 14.9 |
推理失败率(%) | 0.04 | 0.23 |
结果表明,引入资源状态感知的智能请求调度系统可显著提升 GPU 资源利用率,降低延迟波动,提升整体系统稳定性与可观测性。
为验证自定义调度策略在多 GPU 异构集群中的性能与资源分配效果,我们基于以下配置进行了对比测试:
项目 | 配置/参数 |
---|---|
节点数量 | 6(3 × A100,2 × T4,1 × Jetson Xavier) |
GPU 类型 | A100 40GB × 3、T4 16GB × 2、Jetson NPU × 1 |
调度器方案 | 默认 kube-scheduler vs 自定义 GPU-aware 调度器 |
模型 | ResNet50(中等计算型)、BERT(重型)、YOLOv5(轻型) |
调度策略 | 多维打分函数:GPU 利用率 + 显存占用 + 架构匹配度 |
路由入口 | NGINX + Lua 脚本路由 |
请求生成方式 | Locust / 自研压测服务,100 并发,固定 RPS 150 |
节点类型 | 默认调度副本数 | 自定义调度副本数 | GPU 利用率(默认) | GPU 利用率(优化) |
---|---|---|---|---|
A100 | 2 | 3 | 61.2% | 89.7% |
T4 | 3 | 2 | 78.5% | 70.1% |
Jetson | 1 | 1 | 92.4%(瓶颈) | 55.3%(回退执行) |
结论:
本轮测试以每秒 200 条图像推理请求 + 80 条 BERT 文本推理请求模拟业务混合流量。对比如下三种策略:
指标类型 | 策略 A | 策略 B | 策略 C(推荐) |
---|---|---|---|
A100 GPU 平均利用率 (%) | 51.3 | 85.7 | 82.1 |
T4 GPU 利用率波动幅度 | ±24.6% | ±11.8% | ±9.4% |
请求平均响应延迟 (ms) | 16.7 | 11.5 | 10.3 |
95 分位延迟 P95 (ms) | 29.3 | 18.1 | 15.2 |
副本总数(稳定态) | 12 | 12 | 动态 8~14 |
资源闲置率(GPU <30%) | 42% | 18% | 7% |
结论:
node-a
在运行中被强制停止;Taints
标记 node-a
为不可调度;node-b
;Permit + PreBind
插件,支持最后阶段取消绑定。指标 | 故障前 | 故障发生后 | 恢复稳定时间 |
---|---|---|---|
副本数 | 12 | 13(+1 扩容) | 32 秒 |
请求失败率(5xx) | < 0.05% | 峰值 1.8% | 恢复后 0.07% |
GPU 平均利用率(除故障节点) | 72.1% | 88.4%(回退上升) | 82.5%(均衡回落) |
结论:
通过完整架构设计与调度链条部署,该异构推理系统实现了:
个人简介
作者简介:全栈研发,具备端到端系统落地能力,专注人工智能领域。
个人主页:观熵
个人邮箱:[email protected]
座右铭:愿科技之光,不止照亮智能,也照亮人心!
观熵系列专栏导航:
AI前沿探索:从大模型进化、多模态交互、AIGC内容生成,到AI在行业中的落地应用,我们将深入剖析最前沿的AI技术,分享实用的开发经验,并探讨AI未来的发展趋势
AI开源框架实战:面向 AI 工程师的大模型框架实战指南,覆盖训练、推理、部署与评估的全链路最佳实践
计算机视觉:聚焦计算机视觉前沿技术,涵盖图像识别、目标检测、自动驾驶、医疗影像等领域的最新进展和应用案例
国产大模型部署实战:持续更新的国产开源大模型部署实战教程,覆盖从 模型选型 → 环境配置 → 本地推理 → API封装 → 高性能部署 → 多模型管理 的完整全流程
Agentic AI架构实战全流程:一站式掌握 Agentic AI 架构构建核心路径:从协议到调度,从推理到执行,完整复刻企业级多智能体系统落地方案!
云原生应用托管与大模型融合实战指南
智能数据挖掘工程实践
Kubernetes × AI工程实战
TensorFlow 全栈实战:从建模到部署:覆盖模型构建、训练优化、跨平台部署与工程交付,帮助开发者掌握从原型到上线的完整 AI 开发流程
PyTorch 全栈实战专栏: PyTorch 框架的全栈实战应用,涵盖从模型训练、优化、部署到维护的完整流程
深入理解 TensorRT:深入解析 TensorRT 的核心机制与部署实践,助力构建高性能 AI 推理系统
Megatron-LM 实战笔记:聚焦于 Megatron-LM 框架的实战应用,涵盖从预训练、微调到部署的全流程
AI Agent:系统学习并亲手构建一个完整的 AI Agent 系统,从基础理论、算法实战、框架应用,到私有部署、多端集成
DeepSeek 实战与解析:聚焦 DeepSeek 系列模型原理解析与实战应用,涵盖部署、推理、微调与多场景集成,助你高效上手国产大模型
端侧大模型:聚焦大模型在移动设备上的部署与优化,探索端侧智能的实现路径
行业大模型 · 数据全流程指南:大模型预训练数据的设计、采集、清洗与合规治理,聚焦行业场景,从需求定义到数据闭环,帮助您构建专属的智能数据基座
机器人研发全栈进阶指南:从ROS到AI智能控制:机器人系统架构、感知建图、路径规划、控制系统、AI智能决策、系统集成等核心能力模块
人工智能下的网络安全:通过实战案例和系统化方法,帮助开发者和安全工程师识别风险、构建防御机制,确保 AI 系统的稳定与安全
智能 DevOps 工厂:AI 驱动的持续交付实践:构建以 AI 为核心的智能 DevOps 平台,涵盖从 CI/CD 流水线、AIOps、MLOps 到 DevSecOps 的全流程实践。
C++学习笔记?:聚焦于现代 C++ 编程的核心概念与实践,涵盖 STL 源码剖析、内存管理、模板元编程等关键技术
AI × Quant 系统化落地实战:从数据、策略到实盘,打造全栈智能量化交易系统
大模型运营专家的Prompt修炼之路:本专栏聚焦开发 / 测试人员的实际转型路径,基于 OpenAI、DeepSeek、抖音等真实资料,拆解 从入门到专业落地的关键主题,涵盖 Prompt 编写范式、结构输出控制、模型行为评估、系统接入与 DevOps 管理。每一篇都不讲概念空话,只做实战经验沉淀,让你一步步成为真正的模型运营专家。
点个赞,给我一些反馈动力
⭐ 收藏起来,方便之后复习查阅
关注我,后续还有更多实战内容持续更新