网关观测与分层排障:从一次失败请求定位责任层
客户端报告订单接口返回 503,网关错误率也同时上升,应用日志里却找不到对应请求。有人准备扩容业务 Pod,有人想把上游超时调大,还有人发现控制面刚发布过一条 Route。三种动作都可能让现场更乱,因为 503 可以由网关本地无健康端点、连接失败、策略依赖故障、重试耗尽或业务上游主动返回。
排障的第一步不是打开最详细日志,而是确定请求最远走到了哪一层。客户端、入口 TLS、路由 revision、身份策略、上游连接、业务响应和控制面同步各自留下不同证据;request ID、日志、指标与 Trace 只有在字段语义和信任来源一致时,才能把这些证据拼成同一次请求。
先建立七层责任模型
一条请求可按最早失败点分成七层。状态码只缩小范围,不能直接指定 owner。
| 层 | 要证明的事实 | 第一证据 |
|---|---|---|
| 客户端 | DNS、代理、超时、请求格式与发送时刻 | curl -v、客户端错误类型、外部请求标识 |
| 入口 TLS | 目标 IP、SNI、证书链、协议协商与 listener | openssl s_client、TLS alert、listener 指标 |
| 路由 revision | Host/Path/Header 命中哪条规则,数据面加载哪版配置 | route ID、配置 revision、Gateway/Route condition |
| 身份策略 | 认证、授权、配额或外部策略为何放行/拒绝 | policy ID、消费者伪名、拒绝 reason、依赖状态 |
| 上游连接 | 选择哪个 endpoint,连接、TLS、超时和重试如何结束 | upstream cluster/endpoint、attempt、response-code detail |
| 业务响应 | 上游是否真正收到请求并返回业务状态 | 上游 server span、应用日志、upstream status |
| 控制面同步 | 期望配置是否被接受、转换、分发并由每个数据面加载 | generation、condition、数据面 revision/hash、节点同步指标 |
404 既可能是没有路由,也可能是应用资源不存在;401/403 既可能来自网关身份策略,也可能来自业务;429 要知道是哪个计数器;502/503/504 要区分本地生成和上游返回。可靠日志必须同时保存 gateway_status 与 upstream_status,没有发起上游尝试时后者应为空,而不是伪造为 0 或复制最终状态码。
关联标识要区分可关联与可信审计
外部客户端可以发送 X-Request-ID,也可以伪造别人的值。入口应把外部值保存为 client_request_id,经过格式、长度和字符集校验后,仅用于客服关联;网关另外生成不可预测的内部 request_id,用于日志检索和审计。两者不能互相覆盖。
拒绝、截断还是哈希不合格的外部值必须形成明确策略。最容易验证的反例是连续发送重复值、超长值和控制字符编码值:它们可以得到相同的 client_request_id 处理结论,却必须各自产生新的内部 request_id;内部值不能由客户端响应 Header 覆盖,也不能因为外部值不合法就把原文写进日志。
W3C Trace Context 的 traceparent 用于分布式追踪传播,不是身份或授权凭证。合法的外部 trace context 可以继续传播,也可以按边界策略新建 trace 并使用 span link 关联;无论哪种方式,审计都应依赖内部 request ID、认证身份与不可变日志,而不是相信客户端指定的 trace ID。格式要求和传播规则应从 W3C Trace Context 核对。
团队可以把产品字段映射到下面的语义合同,不要求每个网关原生输出同一 JSON:
{
"request_id": "req_internal_7f3a",
"client_request_id": "support_case_demo",
"trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
"listener": "public-https",
"route": "orders-read",
"route_revision": "obs-r1",
"consumer_subject": "hmac:demo-value",
"policy": "orders-reader",
"upstream_cluster": "orders-v1",
"upstream_endpoint": "endpoint-pseudonym-2",
"attempt": 1,
"gateway_status": 200,
"upstream_status": 200,
"failure_layer": null,
"failure_reason": null
}消费者和 endpoint 使用受控伪名,不能把账号、完整证书主题、Token、Pod IP 或内网拓扑复制到共享日志。request ID 不进入指标标签;它只适合日志与 Trace 检索。
用隔离 Route 制造三种可判定结果
实验需要一个已安装兼容控制器的 Gateway API 集群、一个允许实验 namespace 附着的 HTTP listener,以及创建 Deployment、Service、HTTPRoute 的权限。观测平台沿用团队现有环境;数据面日志、指标和配置 revision 按目标产品做字段映射,不从一个实现外推另一个实现的字段名。
先填实际 Gateway 信息,创建一个能返回正常响应、业务错误并记录关联 Header 的上游:
export LAB_NS='gw-observe-lab'
export GATEWAY_NAME='<isolated-gateway-name>'
export GATEWAY_NS='<gateway-namespace>'
export LISTENER_NAME='<http-listener-name>'
export GATEWAY_ADDRESS='<reachable-gateway-address>'
kubectl create namespace "${LAB_NS}"
kubectl auth can-i create httproutes.gateway.networking.k8s.io -n "${LAB_NS}"
kubectl get gateway -n "${GATEWAY_NS}" "${GATEWAY_NAME}" -o yamlkubectl apply -f - <<'YAML'
apiVersion: apps/v1
kind: Deployment
metadata: {name: evidence-api, namespace: gw-observe-lab}
spec:
replicas: 1
selector: {matchLabels: {app: evidence-api}}
template:
metadata: {labels: {app: evidence-api}}
spec:
containers:
- name: api
image: python:3.13-alpine
command: [python, -u, -c]
args:
- |
from http.server import BaseHTTPRequestHandler, HTTPServer
import json
class H(BaseHTTPRequestHandler):
def do_GET(self):
client_rid=self.headers.get('x-request-id','missing')
tp=self.headers.get('traceparent','missing')
status=422 if self.path.startswith('/business-error') else 200
body=json.dumps({'source':'business','status':status,'client_request_id':client_rid}).encode()
print(json.dumps({'event':'request','path':self.path,'client_request_id':client_rid,'traceparent':tp,'status':status}), flush=True)
self.send_response(status)
self.send_header('content-type','application/json')
self.send_header('content-length',str(len(body)))
self.end_headers(); self.wfile.write(body)
def log_message(self, fmt, *args): pass
HTTPServer(('0.0.0.0',8080),H).serve_forever()
ports: [{name: http, containerPort: 8080}]
readinessProbe: {httpGet: {path: /ok, port: http}}
resources:
requests: {cpu: 20m, memory: 32Mi}
limits: {memory: 128Mi}
---
apiVersion: v1
kind: Service
metadata: {name: evidence-api, namespace: gw-observe-lab}
spec:
selector: {app: evidence-api}
ports: [{name: http, port: 80, targetPort: http}]
---
apiVersion: v1
kind: Service
metadata: {name: no-endpoints, namespace: gw-observe-lab}
spec:
selector: {app: deliberately-absent}
ports: [{name: http, port: 80, targetPort: http}]
YAML
kubectl rollout status -n "${LAB_NS}" deploy/evidence-api
kubectl get endpointslice -n "${LAB_NS}"evidence-api 应有 ready endpoint,no-endpoints 应没有 endpoint。接着创建正常、业务错误与无 endpoint 三条路径,并用响应 Header 暴露实验 revision。ResponseHeaderModifier 的支持度要从目标控制器的一致性报告确认;若不支持,就删除 filter,改从数据面配置或访问日志读取 revision,不能把 ResolvedRefs=True 冒充实现支持该 filter。
cat > /tmp/observe-route.yaml <<YAML
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: evidence
namespace: ${LAB_NS}
annotations:
lab.example/config-revision: obs-r1
spec:
parentRefs:
- name: ${GATEWAY_NAME}
namespace: ${GATEWAY_NS}
sectionName: ${LISTENER_NAME}
hostnames: [observe.example.test]
rules:
- matches:
- path: {type: PathPrefix, value: /ok}
- path: {type: PathPrefix, value: /business-error}
filters:
- type: ResponseHeaderModifier
responseHeaderModifier:
set: [{name: X-Route-Revision, value: obs-r1}]
backendRefs: [{name: evidence-api, port: 80}]
- matches:
- path: {type: PathPrefix, value: /no-endpoints}
filters:
- type: ResponseHeaderModifier
responseHeaderModifier:
set: [{name: X-Route-Revision, value: obs-r1}]
backendRefs: [{name: no-endpoints, port: 80}]
YAML
kubectl apply --server-side --dry-run=server -f /tmp/observe-route.yaml
kubectl apply -f /tmp/observe-route.yaml
kubectl get httproute -n "${LAB_NS}" evidence -o yaml确认目标 parent 的 Accepted=True、ResolvedRefs=True 且 observedGeneration 等于 metadata.generation 后,发送带外部关联值和合法 trace context 的请求。每个独立请求使用不同 trace ID;复用同一个 traceparent 会把本来无关的探针错误地拼进同一条 Trace:
export TRACEPARENT_OK='00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01'
export TRACEPARENT_BUSINESS='00-7a3f2c1e14d84c6aaef0e7336e2a9b41-32b48a14d3f501c2-01'
export TRACEPARENT_UPSTREAM='00-b28c6129f6eb4f95a68a726d284a807c-714f10bc325e78d0-01'
curl -sS -D - -o /tmp/ok.json \
-H 'Host: observe.example.test' \
-H 'X-Request-ID: client-demo-ok' \
-H "traceparent: ${TRACEPARENT_OK}" \
"http://${GATEWAY_ADDRESS}/ok"
curl -sS -D - -o /tmp/business.json \
-H 'Host: observe.example.test' \
-H 'X-Request-ID: client-demo-business' \
-H "traceparent: ${TRACEPARENT_BUSINESS}" \
"http://${GATEWAY_ADDRESS}/business-error"
curl -sS -D - -o /tmp/no-endpoints.json \
-H 'Host: observe.example.test' \
-H 'X-Request-ID: client-demo-upstream' \
-H "traceparent: ${TRACEPARENT_UPSTREAM}" \
"http://${GATEWAY_ADDRESS}/no-endpoints"
kubectl logs -n "${LAB_NS}" deploy/evidence-api --tail=20预期证据不同:/ok 的 gateway 与 upstream status 都是 200;/business-error 的上游日志明确记录 422,因此它是业务响应,不应归为网关连接失败;/no-endpoints 不会出现在应用日志,网关通常生成本地 5xx,并留下无可用 endpoint/cluster 的实现级 reason。具体状态码可能因实现而异,判责依据是“是否发起上游尝试、upstream status 是否存在、failure reason 是什么”。示例应用回显的是不可信的 client_request_id,不是内部 request_id;只有目标网关的访问日志同时出现新生成的内部值、外部值处理结果和对应 trace ID,才完成标识合同验证。
从客户端和入口 TLS 开始排除
客户端证据要保存解析到的地址、实际代理、连接阶段、总超时与发送的 Host,但不要保存 Authorization、Cookie 或完整 query。先绕开本地 shell alias 和隐式代理,确认请求确实到达目标入口:
curl --noproxy '*' -sv --connect-timeout 3 \
-H 'Host: observe.example.test' \
"http://${GATEWAY_ADDRESS}/ok" -o /dev/null若是 HTTPS,IP、SNI 与 HTTP Host 要同时正确。-H Host 不一定改变 TLS SNI,使用 --resolve 或目标 DNS 名验证:
curl --noproxy '*' -sv \
--resolve "observe.example.test:443:${GATEWAY_ADDRESS}" \
"https://observe.example.test/ok" -o /dev/null
openssl s_client -connect "${GATEWAY_ADDRESS}:443" \
-servername observe.example.test -showcerts </dev/null证书链、SAN、有效期、受信 CA、ALPN 与 TLS alert 都属于入口证据。客户端尚未完成 TLS 时不会有 HTTP Route、身份策略或业务日志;此时修改后端超时没有意义。反过来,TLS 成功只证明 listener 可达,不能证明 Host 已附着到正确 Route。
路由 revision 要连到真实数据面
控制面同步至少有四个状态:Git/发布系统期望 revision、API/管理面接受状态、数据面实际加载 revision、真实请求命中结果。Gateway API 的 Accepted=True 只说明目标 parent 接受 Route,ResolvedRefs=True 只说明引用可解析;两者都不能证明每个代理已经使用候选配置。
修改 Route 后立刻比较 generation 与 condition:
kubectl get httproute -n "${LAB_NS}" evidence \
-o jsonpath='{.metadata.generation}{"\n"}{range .status.parents[*].conditions[*]}{.type}{"\t"}{.status}{"\t"}{.reason}{"\t"}{.observedGeneration}{"\n"}{end}'observedGeneration 落后时,旧绿色状态是 stale evidence。目标实现若提供代理配置 hash、节点同步 ACK/NACK、admin config dump 或控制面指标,应按数据面实例检查;这些导出可能包含内部拓扑和 Secret 元数据,只能放受控临时目录。真实请求再用受控响应 Header、访问日志 route ID 或 Trace 属性确认命中 revision,不能仅依赖 Dashboard 颜色。
发布系统还应做一次 revision 切换反例:把期望值改为 obs-r2 后,在 condition 尚未观察到新 generation 时立即发探针,预期流水线因证据过期而阻断;等所有目标数据面加载 obs-r2 后,响应 Header、访问日志或 Trace 才允许报告新 revision。若同一时间窗仍同时出现 obs-r1 与 obs-r2,按数据面节点和连接拆分,不把控制面对象的新注解当成代理已加载证明。
配置已被控制面接受但部分代理仍旧时,常见现象是同一请求在不同连接上交替成功/失败。按数据面实例比较 loaded revision、最后同步时刻、NACK reason 和重启次数;不要先滚动重启全部代理,否则会抹掉“哪些节点未同步”的关键现场。
身份策略要保存结论而不是凭证
网关层 401 应能说明缺少、过期或不可验证的认证材料;403 应能说明身份已建立但授权拒绝。业务也能返回相同状态码,所以访问日志要标记 response source、policy ID 与 upstream status。外部授权服务或 JWKS 不可达时,还要记录依赖错误和 fail-open/fail-close 决策。
正反请求至少包括有效凭证、缺失凭证、错误 issuer/audience、已撤销消费者和策略依赖超时。日志只保存令牌指纹或签发者/受众的受控枚举,不保存完整 JWT、API Key、证书或外部授权响应。若策略在授权后改写 Path、身份 Header 或重新选路,应把授权资源与最终 route 一起记录,防止“授权通过”掩盖后续越权路由。
Gateway API 核心资源不定义统一身份策略,不能把某个控制器 CRD 或云产品 policy 字段写成跨产品标准。项目接入时为每种实现建立字段映射,并用相同正反请求验证语义,而不是跨产品复制配置名。
上游连接与业务响应用 span 边界拆开
网关接收请求时创建或继续 server span,向上游发起尝试时创建 client span,应用再创建 server span。若只有网关 server span,没有上游 client span,失败通常发生在路由、策略或本地容量保护;有 client span 但没有应用 server span,要检查 DNS、连接、上游 TLS、NetworkPolicy、连接池与超时;应用 span 和日志都存在,则进入业务响应层。
OpenTelemetry HTTP semantic conventions 区分客户端与服务端观察值。经代理后 Host、:authority、peer address 和 path 可能改变,网关与应用应各自记录观察到的值。语义约定会演进,instrumentation 升级要固定目标版本并按迁移指南双写,不能把某一组属性名当永久合同。
重试会产生多个上游 client span。访问日志至少记录 attempt、每次 endpoint、连接错误、upstream status 与最终选择;指标同时观察下游请求数和上游尝试数。若一次客户端请求对应三个上游尝试,容量和错误分析都不能只按最终 200 计算。
OpenTelemetry HTTP span 约定用 http.request.resend_count 标记同一逻辑调用中的再次发送,并把代理看到的 server.address、url.path、http.route 与真实网络 peer 分开。网关若为每次上游尝试建立 client span,首次发送不设置该属性,第一次重发设为 1,后续重发继续递增,并把这些 span 挂在同一个下游 server span 下;只创建一个覆盖全部重试的模糊 span,会把 DNS、连接、首字节与业务处理时间揉成一段,无法定位重试放大。
日志、指标和 Trace 各证明一类事实
访问日志适合回答“这一请求发生了什么”,指标适合回答“某类失败是否成片发生”,Trace 适合回答“跨进程时间花在哪里”。三者用 request/trace ID、route、revision、policy、upstream 和受控时间窗口关联,但不能互相替代。
访问日志字段先形成一个稳定合同,再映射到具体产品。下面是一条脱敏后的目标形态;upstream_status=null 明确表示没有收到上游响应,不能写成 503 冒充上游结果:
{
"request_id": "01J...",
"client_request_id_state": "accepted",
"trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
"listener": "public-https",
"route": "orders",
"route_revision": "obs-r2",
"policy": "orders-jwt-v4",
"response_source": "gateway",
"gateway_status": 503,
"upstream_status": null,
"upstream_cluster": "orders-v2",
"upstream_attempts": 1,
"failure_class": "no_healthy_upstream",
"duration_ms": 12
}在 Envoy 系数据面中,访问日志格式可提供 %RESPONSE_FLAGS%、%RESPONSE_CODE_DETAILS%、%UPSTREAM_TRANSPORT_FAILURE_REASON% 与上游时序。它们是定位线索,不是跨版本永久枚举:response_code_details 的值可能随实现演进,告警应先归一为 route、policy、connect、timeout、upstream_response 等稳定故障类,同时保留原值供排查。任何会暴露内部 cluster、证书失败细节或地址的字段都只能进入受限日志。
拿到一条 503 后,查询顺序应能形成反证。先按内部 request_id 找访问日志;若没有记录,回到 DNS、负载均衡器、TLS 或错误入口。若 response_source=gateway 且没有 upstream attempt,检查 Route、策略和本地限流;有 attempt 但 upstream_status 为空,则查 DNS、连接、上游 TLS、NetworkPolicy 与连接池;有 upstream_status=503 和应用 server span,则交给业务服务解释。最后再按 trace_id 展开每次尝试,并用应用日志证明最远到达层,不能从一个最终状态码直接跳到扩容结论。
低基数指标可以围绕这些语义建立:入口 TLS 握手失败;按 listener/route/status class 统计的请求;按 policy/reason 统计的拒绝;按 upstream/failure class 统计的连接错误、超时和尝试;按数据面节点统计的配置 revision 落后或 NACK。消费者、原始 path 参数、request ID、trace ID 和 endpoint IP 不进入 label。
告警先指向责任层:TLS 失败率配证书/listener owner,route 未接纳或 revision 落后配控制面 owner,身份拒绝异常配策略 owner,上游连接错误配平台与服务 owner,upstream 5xx 配业务 owner。一个“网关错误率高”告警无法指导行动,只会制造多人同时改配置。
告警还要有停止线和降级动作。配置 revision 落后、NACK、日志导出积压、Trace 丢弃和指标抓取失败不能与业务 5xx 混成一个比率;前两者阻止继续发布,后几者触发观测降级。若结构化日志让网关 p99 超过基线 10%、本地日志队列持续增长或 collector backpressure 达到容量上限,应先关闭高成本可选字段、降低成功 Trace 采样并保留错误样本,不能让观测系统拖垮数据面。安全审计记录不跟随普通调试日志一起降级,其可靠性预算与故障处置必须独立。
敏感诊断必须有到期时间和删除证明
请求 query、Authorization、Cookie、API Key、JWT、客户端证书主题、消费者 ID、异常消息、请求/响应体、配置 dump 和 Trace attributes 都可能包含敏感信息。默认采集使用允许列表:method、规范化 route template、状态码、受控 reason、字节数、延迟、revision 与伪名;原始 URL、Header 和 body 默认丢弃。
临时诊断采用“单 route、单实例、短窗口、低采样”的组合,并在启用前记录 owner、审批、字段、存储位置和自动到期。共享材料前扫描域名、租户、Token、Cookie、证书、内网地址和客户数据;诊断结束后恢复日志级别,删除专为本次调试创建且允许删除的临时索引、对象存储、Trace、配置 dump 与本地下载,并从查询和存储入口确认不可再检索。受合规保留或不可变存储约束的审计证据不得擅自删除,应按既定期限保留、撤销临时查询权限并记录到期处置。
高敏管理入口、admin/config dump、日志平台和 Trace UI 使用组织身份、最小权限与审计。生产数据不能为了方便复制到个人工单或聊天;真正需要保留的事故证据应加密、限权并按合规保留策略管理。
项目接入从字段合同和故障注入开始
网关配置仓库应为每个 route 保存 owner、服务、revision、身份策略和上游名称;发布流水线把期望 revision 写入配置,并在变更后检查控制面状态、数据面加载状态和真实请求。应用日志接入统一的 request/trace context,但拒绝客户端覆盖内部审计 ID。
每个服务至少维护一组无副作用探针:正常请求、错误 Host/Path、缺失身份、业务 4xx、无 endpoint、连接超时和旧 revision。故障注入一次只改变一层,保存客户端输出、Gateway/Route 状态、数据面日志、指标窗口、Trace 和应用日志。修复后重放原请求及对应反例,避免正常样本恢复却把拒绝策略一起放开。
观测机制按问题选型:只需本地开发定位时,结构化访问日志和应用日志已足够;需要趋势与告警时增加低基数指标;跨网关、策略服务和业务进程定位延迟时接入 Trace;需要证明配置传播时必须再接数据面 revision/ACK 证据。没有 owner、采样和保留预算时,不应默认全量 body 日志或全采样 Trace。
观测配置本身也要像路由一样可回退。采集器配置、访问日志格式、采样策略、脱敏规则、索引模板和告警规则使用同一个 telemetry_revision,先在单个数据面实例或单条 route 上验证,再逐批推广。正样本要证明请求能在日志、指标和 Trace 中关联;反样本要发送伪造 request ID、敏感 Header、无上游响应和多次重试,确认敏感值未落盘、upstream_status 为空且 attempt 数正确。
回退时恢复上一版 telemetry_revision,等待所有数据面与 collector 报告新旧配置收敛,再重放正反样本。若字段改名导致查询、告警或事故脚本失效,短窗口双写旧字段和新字段,确认消费者迁移后再删除旧字段;不要先删索引或旧告警,因为那会同时毁掉现场和回退入口。回退完成的证据是数据面延迟恢复、队列不再增长、日志/Trace 仍可关联、敏感反样本仍被丢弃,以及临时高采样数据按保留策略完成清理。
容量和费用是观测设计的一部分
日志写入速率约等于 RPS 乘单条日志字节,保留存储还要乘保留窗口与索引副本;Trace 成本受采样率、span 数、重试次数和属性大小影响;指标成本主要受时间序列基数影响。Header/body 采集、同步日志和复杂格式化还会消耗数据面 CPU 与内存,故障时流量和错误日志同时放大。
容量测试要同时观察网关延迟、日志丢弃/队列、collector backpressure、指标序列数量、Trace 导出失败和存储增长。采样不能只保留成功请求:策略拒绝、上游连接错误、慢请求与配置切换窗口需要独立规则,但采样决策也不能依赖敏感身份原值。
成本 owner 应能从 route/环境/数据类型归集用量,设置日志与 Trace 配额、保留和降级策略。观测后端不可用时,数据面应按已批准策略缓冲、丢弃或降采样,不能无限阻塞业务请求;安全审计日志与普通调试日志要使用不同可靠性和访问边界。
修复后清理实验与临时能力
kubectl delete -f /tmp/observe-route.yaml --ignore-not-found
kubectl delete namespace "${LAB_NS}" --wait=true
rm -f /tmp/observe-route.yaml /tmp/ok.json /tmp/business.json /tmp/no-endpoints.json
unset TRACEPARENT_OK TRACEPARENT_BUSINESS TRACEPARENT_UPSTREAM
kubectl get httproute -A | grep gw-observe-lab || true
kubectl get namespace "${LAB_NS}" 2>/dev/null || true共享 Gateway、控制器、CRD 和观测平台不属于实验,不应删除。随后在日志、指标和 Trace 后端删除实验 namespace、Host、request ID 与 trace ID 对应的临时数据,撤销临时查询权限和调试端口。若实验触发了云日志、托管 Trace、负载均衡器或对象存储费用,还要从资源清单和后续用量确认停止。
交接前让证据能够回答这些问题
外部 client request ID、内部 request ID 与 trace context 的信任来源明确。同一请求能关联 route、revision、policy、upstream attempts、gateway status 与 upstream status。客户端、TLS、路由、身份、连接、业务和控制面同步各有独立第一证据。
Gateway API condition 的 generation 新鲜,数据面 revision 和真实请求另行验证。日志、指标、Trace 的字段、低基数维度、采样和保留有明确合同。临时调试不会记录完整 Token、Cookie、query、body 或内部拓扑。
故障修复后重放正反样本,并清理调试级别、数据、权限、端口和费用资源。
