第一章:Go语言微信支付开发全景概览
微信支付作为国内主流的移动支付基础设施,其生态完善、文档成熟、SDK覆盖全面,而Go语言凭借高并发、强类型、部署轻量等特性,正成为构建高性能支付服务后端的首选语言之一。本章将系统梳理Go开发者接入微信支付所需的关键认知维度:从协议演进、签名机制、API分层,到工程实践中的安全边界与可观测性设计。
核心协议与版本演进
微信支付当前主推V3版API(基于HTTPS+JSON+平台证书),全面替代老旧的V2版(XML+MD5签名)。V3强制要求双向证书认证、敏感字段AES-256-GCM加密、所有请求携带Authorization头(含时间戳、随机串、签名摘要),显著提升传输安全性与防重放能力。
Go生态关键依赖组件
github.com/wechatpay-apiv3/wechatpay-go:官方维护的Go SDK,内置自动证书管理、签名生成、HTTP客户端封装;golang.org/x/crypto/acme/autocert:可选用于动态获取并续签平台证书;go.uber.org/zap+prometheus/client_golang:支撑支付链路日志审计与指标监控。
快速初始化示例
import "github.com/wechatpay-apiv3/wechatpay-go/core"
// 初始化客户端(需提前下载平台证书并保存至本地)
opts := []core.ClientOption{
core.WithWechatPayAutoAuth("your_mch_id", "your_mch_certificate_sn",
"path/to/apiclient_key.pem", "path/to/apiclient_cert.pem"),
}
client, err := core.NewClient(opts...)
if err != nil {
panic("failed to init wechatpay client: " + err.Error())
}
// 此client已自动完成证书加载、签名中间件注入、HTTP超时配置
该初始化过程隐式完成平台证书校验、私钥加载及签名上下文预置,开发者无需手动拼接签名字符串或管理证书有效期。
安全实践要点
- 商户私钥必须通过文件系统权限(如
0600)隔离,严禁硬编码或存入环境变量; - 所有异步通知(如支付结果回调)必须严格校验
Wechatpay-Signature与Wechatpay-Timestamp; - 敏感操作(退款、转账)需启用二次验证(如操作员API证书绑定);
- 建议使用
context.WithTimeout为每个支付请求设置独立超时,避免goroutine泄漏。
第二章:微信支付API接入与安全认证体系构建
2.1 微信商户平台配置与APIv3证书体系详解(含Go代码生成与加载)
微信 APIv3 强制使用双向 HTTPS 认证:商户需上传平台证书,调用接口时用私钥签名,并验证微信响应的 Wechatpay-Serial 与 TLS 证书链。
证书体系核心组件
- 商户 APIv3 私钥(
apiclient_key.pem)——用于生成签名 - 商户平台证书(
apiclient_cert.pem)——含公钥,上传至商户平台 - 微信平台证书(动态获取)——用于验签响应
Go 加载与签名示例
package main
import (
"crypto/rsa"
"crypto/x509"
"io/ioutil"
)
// LoadPrivateKey 从 PEM 文件加载 RSA 私钥
func LoadPrivateKey(path string) (*rsa.PrivateKey, error) {
data, err := ioutil.ReadFile(path)
if err != nil {
return nil, err // 如文件不存在或权限不足
}
block, _ := pem.Decode(data)
return x509.ParsePKCS1PrivateKey(block.Bytes) // 仅支持 PKCS#1 格式
}
该函数读取 PEM 编码的私钥文件,经 pem.Decode 提取 DER 数据后,用 x509.ParsePKCS1PrivateKey 解析为 *rsa.PrivateKey。注意:微信 V3 仅接受 PKCS#1(非 PKCS#8),若生成时使用 openssl pkcs8 -topk8 需先转换。
微信证书生命周期管理
| 阶段 | 操作方式 | 有效期 |
|---|---|---|
| 初始获取 | 商户平台手动下载 | 2年 |
| 自动轮转 | 调用 /v3/certificates 接口 |
每月更新 |
graph TD
A[商户控制台配置APIv3密钥] --> B[下载apiclient_key.pem + apiclient_cert.pem]
B --> C[Go程序加载私钥签名请求]
C --> D[调用/v3/certificates获取微信平台证书]
D --> E[缓存并定期刷新证书]
2.2 基于Go的HTTP客户端封装:支持自动签名、验签与敏感字段加密
核心能力设计
- 自动为请求头注入
X-Signature和X-Timestamp - 敏感字段(如
idCard,phone)在序列化前 AES-GCM 加密 - 响应体自动验签并解密敏感字段
签名流程(mermaid)
graph TD
A[构造请求参数] --> B[按字典序拼接键值对]
B --> C[追加密钥与时间戳]
C --> D[SHA256哈希生成签名]
D --> E[注入Header]
关键代码片段
func (c *SecureClient) Do(req *http.Request) (*http.Response, error) {
signData := c.buildSignPayload(req) // 构建待签名原始数据
sig := hmacSHA256(signData, c.secretKey) // 使用服务端共享密钥签名
req.Header.Set("X-Signature", sig)
req.Header.Set("X-Timestamp", strconv.FormatInt(time.Now().Unix(), 10))
return c.httpClient.Do(req)
}
buildSignPayload 提取 req.URL.Query() 与 req.Body JSON 字段(排除 file 等二进制字段),确保幂等性;hmacSHA256 采用标准 HMAC-SHA256,兼容 Java/Python 服务端。
| 能力 | 实现方式 | 安全保障 |
|---|---|---|
| 自动签名 | 请求发送前拦截 | 防重放、防篡改 |
| 敏感字段加密 | JSON Marshal 前递归处理 | AES-GCM,带认证加密 |
| 响应验签 | X-Signature 回溯校验 |
确保响应未被中间人劫持 |
2.3 微信回调通知的幂等性设计与Go语言原子化处理实践
微信支付、公众号事件等回调通知存在重复推送风险,需在业务层实现幂等保障。
核心设计原则
- 唯一标识提取:
mch_id + out_trade_no + event_type + timestamp组合生成幂等键 - 状态机校验:仅允许
pending → success/fail单向流转 - 存储层原子写入:避免先查后写(race condition)
Go原子化处理实践
使用 Redis Lua 脚本保证「校验+写入」原子性:
const idempotentScript = `
if redis.call("GET", KEYS[1]) == false then
redis.call("SET", KEYS[1], ARGV[1], "EX", ARGV[2])
return 1
else
return 0
end`
// 参数说明:
// KEYS[1]:幂等键(如 "idemp:wx:123456:pay_789")
// ARGV[1]:业务状态快照(如 JSON {"status":"success","ts":171xxxx})
// ARGV[2]:TTL 秒数(建议 24h,覆盖微信最长重试窗口)
幂等键策略对比
| 策略 | 优点 | 风险 |
|---|---|---|
仅用 out_trade_no |
简单通用 | 多商户/多事件类型冲突 |
appid+event_id |
微信端唯一 | 无业务上下文,难追溯 |
| 组合键(推荐) | 业务语义清晰+防碰撞 | 需统一规范字段拼接逻辑 |
graph TD
A[微信回调到达] --> B{幂等键生成}
B --> C[Redis Lua 原子校验]
C -->|首次| D[执行业务逻辑]
C -->|已存在| E[直接返回成功响应]
D --> F[更新DB + 发送MQ]
F --> G[返回200]
2.4 敏感凭证安全存储方案:Go中集成Vault/KMS与内存安全缓存策略
Vault动态凭据集成示例
// 使用Vault Go SDK获取短期数据库凭据
client, _ := api.NewClient(&api.Config{Address: "https://vault.example.com"})
secret, _ := client.Logical().Read("database/creds/my-role")
dbUser := secret.Data["username"].(string)
dbPass := secret.Data["password"].(string)
database/creds/my-role 触发Vault后端动态生成带TTL的唯一凭据;username/password 为临时凭证,自动轮换,避免硬编码或长期泄露。
内存安全缓存策略
- 使用
sync.Map替代全局变量存储解密后的凭证片段 - 凭据解密后仅在内存中存活 ≤30s(基于
time.AfterFunc清理) - 所有敏感字段在GC前显式覆写:
for i := range pwd { pwd[i] = 0 }
KMS加密流程(AWS)
graph TD
A[Go应用请求密钥] --> B[AWS KMS GenerateDataKey]
B --> C[用Plaintext Key加密凭证]
C --> D[将CipherTextBlob持久化]
D --> E[运行时Decrypt + 零拷贝内存加载]
| 方案 | 密钥生命周期 | 内存驻留风险 | 适用场景 |
|---|---|---|---|
| Vault动态凭据 | 秒级TTL | 极低 | 数据库/服务间认证 |
| KMS信封加密 | 用户托管 | 中(需及时擦除) | 配置文件/静态密钥 |
2.5 微信沙箱环境全链路联调:Go测试驱动开发(TDD)验证支付闭环
沙箱配置与凭证注入
微信沙箱需显式启用,并通过 sandbox_signkey 替换生产密钥。Go 测试中使用 testify/mock 模拟 http.Client,确保不触达真实 API。
TDD 驱动的支付闭环验证
func TestWeChatSandboxPayFlow(t *testing.T) {
// 初始化沙箱客户端(含自动 signkey 刷新逻辑)
client := NewSandboxClient("mch_id", "api_v3_key")
// 1. 创建沙箱预支付订单 → 2. 调用统一下单接口 → 3. 模拟用户支付 → 4. 主动查询结果
resp, err := client.UnifiedOrder(context.Background(), &UnifiedOrderReq{
Body: "TDD-Test-Goods",
OutTradeNo: "tdd_" + time.Now().Format("20060102150405"),
TotalFee: 1, // 沙箱仅支持 1 分
NotifyURL: "https://example.com/callback",
})
assert.NoError(t, err)
assert.NotEmpty(t, resp.PrepayID)
}
逻辑说明:
UnifiedOrderReq.TotalFee=1是沙箱强制要求;OutTradeNo必须全局唯一,否则沙箱返回ORDERPAID错误;PrepayID是后续 JSAPI 调起支付的关键凭证。
关键参数对照表
| 字段 | 沙箱值 | 生产值 | 说明 |
|---|---|---|---|
mchid |
同生产 | 同沙箱 | 商户号不变 |
signkey |
sandbox_signkey 返回值 |
APIv3 密钥 | 每次调用 /v3/payments/sandbox/signkey 获取 |
notify_url |
支持 localhost | 需备案域名 | 沙箱允许非 HTTPS 回调 |
全链路状态流转
graph TD
A[发起统一下单] --> B[沙箱返回 prepay_id]
B --> C[构造 JSAPI 参数并签名]
C --> D[模拟前端调起支付]
D --> E[沙箱自动标记为 SUCCESS]
E --> F[主动查单确认 status==success]
第三章:高并发场景下的核心支付流程实现
3.1 统一下单接口的Go高性能封装与上下文超时控制实战
统一下单是支付链路的核心入口,高并发下需兼顾一致性、可观测性与快速失败。
上下文超时封装设计
使用 context.WithTimeout 显式约束整个调用生命周期,避免 goroutine 泄漏:
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()
resp, err := client.UnifiedOrder(ctx, req)
ctx透传至 HTTP 客户端与下游 RPC,驱动全链路超时;cancel()必须 defer 调用,确保资源及时释放;- 超时值需结合 P99 延迟与业务容忍度动态配置(如支付类建议 ≤3s)。
关键参数校验清单
- ✅
appid/mch_id格式合法性 - ✅
out_trade_no幂等性前置校验 - ✅
total_fee为正整数且 ≤100万元
超时传播示意
graph TD
A[API Gateway] -->|ctx.WithTimeout 3s| B[OrderService]
B -->|ctx passed| C[WeChat Pay SDK]
C -->|ctx deadline| D[HTTP Transport]
| 场景 | 默认超时 | 推荐调整 |
|---|---|---|
| 预下单校验 | 800ms | 可缩至 500ms |
| 微信侧签名生成 | 200ms | 保持不变 |
| 全链路兜底 | 3s | 不建议 >5s |
3.2 支付结果轮询与异步通知双通道保障机制(Go channel + timer组合)
双通道设计动机
支付系统需应对网络抖动、回调丢失、服务宕机等不确定性。单一依赖异步通知(如微信/支付宝 HTTP 回调)存在漏收风险;仅靠轮询又增加资源开销。双通道协同可兼顾实时性与可靠性。
核心实现:channel + timer 协同调度
// 启动轮询协程,同时监听通知 channel 和超时 timer
func startPollingWithNotify(ctx context.Context, orderID string, notifyCh <-chan *PaymentResult) {
ticker := time.NewTicker(3 * time.Second)
defer ticker.Stop()
for {
select {
case result := <-notifyCh: // 异步通知优先抵达
handleSuccess(result)
return
case <-ticker.C: // 定期轮询
if res, ok := queryPaymentStatus(orderID); ok {
handleSuccess(res)
return
}
case <-time.After(60 * time.Second): // 全局超时兜底
log.Warn("payment polling timeout", "order", orderID)
return
case <-ctx.Done():
return
}
}
}
逻辑分析:
notifyCh接收外部 HTTP 回调经http.HandlerFunc转发的结构化结果,零延迟响应;ticker.C触发幂等性轮询(含重试指数退避),避免高频请求;time.After提供最终超时边界,防止 goroutine 泄漏;- 所有分支均
return,确保单次执行终结。
通道状态对比表
| 维度 | 异步通知通道 | 轮询通道 |
|---|---|---|
| 触发时机 | 支付平台主动推送 | 客户端定时发起 |
| 延迟 | ~100ms–2s | 3s–30s(可配) |
| 可靠性保障 | 依赖网络+接收方ACK | 本地可控,失败可重试 |
| 资源消耗 | 极低(事件驱动) | 中等(HTTP连接+解析) |
数据同步机制
轮询结果与通知结果统一写入内存 channel → 持久化层(如 Redis + MySQL),通过 sync.Once 保证状态更新原子性。
3.3 订单状态机建模与Go泛型状态流转引擎实现
订单生命周期需严格遵循“创建→支付中→已支付→发货→已完成→已取消”等不可逆约束。传统 switch 嵌套易导致状态跃迁失控,我们采用事件驱动+泛型约束构建可复用的状态引擎。
核心状态定义
type OrderStatus string
const (
StatusCreated OrderStatus = "created"
StatusPaid OrderStatus = "paid"
StatusShipped OrderStatus = "shipped"
StatusCancelled OrderStatus = "cancelled"
)
// 状态迁移规则表(仅允许合法跃迁)
// | 当前状态 | 事件 | 目标状态 |
// |----------|--------------|----------|
// | created | pay | paid |
// | paid | ship | shipped |
// | * | cancel | cancelled|
泛型流转引擎
type StateMachine[T comparable, E any] struct {
current T
rules map[T]map[E]T // 规则:state → event → next state
}
func (sm *StateMachine[T, E]) Transition(event E) error {
next, ok := sm.rules[sm.current][event]
if !ok {
return fmt.Errorf("invalid transition: %v → %v", sm.current, event)
}
sm.current = next
return nil
}
逻辑分析:
T为状态类型(如OrderStatus),E为事件类型(如string或自定义PayEvent)。rules使用双层 map 实现 O(1) 跃迁校验;Transition原子更新状态并拒绝非法路径。
graph TD
A[created] -->|pay| B[paid]
B -->|ship| C[shipped]
A -->|cancel| D[cancelled]
B -->|cancel| D
C -->|cancel| D
第四章:生产级容灾、可观测性与性能优化
4.1 微信支付失败重试策略:指数退避+抖动+Go错误分类熔断实践
核心重试逻辑设计
采用 baseDelay × 2^n + jitter 指数退避模型,避免雪崩式重试。抖动范围设为 [0, 100ms),防止多实例同步冲击。
func backoffDuration(attempt int) time.Duration {
base := 100 * time.Millisecond
// 指数增长 + 均匀抖动
jitter := time.Duration(rand.Int63n(100)) * time.Millisecond
return base*time.Duration(1<<uint(attempt)) + jitter
}
attempt从 0 开始计数;1<<uint(attempt)实现 2ⁿ;rand.Int63n(100)生成 0–99ms 随机抖动,降低协同重试概率。
错误分类熔断阈值
| 错误类型 | 是否可重试 | 熔断条件(5min内) |
|---|---|---|
ErrNetwork |
✅ | 连续 3 次失败 |
ErrInvalidSign |
❌ | 立即熔断 |
ErrPayClosed |
❌ | 永久跳过 |
状态流转示意
graph TD
A[发起支付] --> B{HTTP 502/Timeout?}
B -->|是| C[应用指数退避]
B -->|否| D[解析微信err_code]
D --> E[匹配熔断规则]
C --> E
E -->|熔断中| F[返回ServiceUnavailable]
E -->|允许重试| G[延迟后重试]
4.2 分布式事务一致性保障:基于Go的本地消息表+Saga模式落地
核心设计思想
本地消息表确保业务与消息写入原子性,Saga通过补偿操作维护最终一致性。二者结合规避了XA性能瓶颈,适配高并发微服务场景。
数据同步机制
- 业务操作与消息记录在同一数据库事务中提交
- 消息服务轮询本地消息表,异步投递至消息队列
- 下游服务消费后触发回调,更新消息状态为
processed
Go实现关键片段
// 插入订单并写入本地消息(事务内)
tx, _ := db.Begin()
_, _ = tx.Exec("INSERT INTO orders (...) VALUES (...)")
_, _ = tx.Exec("INSERT INTO local_msg (topic, payload, status) VALUES (?, ?, 'pending')", "order.created", payload)
tx.Commit()
逻辑分析:
payload为JSON序列化的业务数据(如{"order_id":"ORD123","amount":99.9});status初始为pending,由独立消息处理器更新;事务失败则全部回滚,保证强一致性边界。
Saga补偿流程
graph TD
A[创建订单] --> B[扣减库存]
B --> C[支付结算]
C --> D[发货通知]
B -.->|失败| B2[恢复库存]
C -.->|失败| C2[退款]
D -.->|失败| D2[取消物流单]
| 阶段 | 参与方 | 补偿动作 |
|---|---|---|
| 扣减库存 | 库存服务 | 增加对应SKU数量 |
| 支付结算 | 支付网关 | 调用退款API |
| 发货通知 | 物流平台 | 调用取消运单接口 |
4.3 Go pprof + OpenTelemetry集成:微信支付链路全栈性能剖析
在高并发支付场景中,需同时捕获运行时性能画像(CPU/heap/block)与分布式追踪上下文。Go 原生 pprof 与 OpenTelemetry SDK 协同可实现指标、追踪、日志三合一观测。
集成核心步骤
- 注册
pprofHTTP handler 到 OTel trace-aware mux - 使用
otelhttp.NewHandler包装支付路由,自动注入 span - 启用
runtime/pprof采集并导出至 OTel Collector
关键代码示例
import "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
mux := http.NewServeMux()
mux.Handle("/pay", otelhttp.NewHandler(http.HandlerFunc(payHandler), "pay"))
// 自动注入 trace context,并关联 pprof label: trace_id=xxx
该 handler 将 HTTP 请求生命周期纳入 Span 生命周期,使 /pay 的 CPU profile 可按 trace_id 关联到具体支付流水。
性能数据关联维度
| 维度 | 来源 | 用途 |
|---|---|---|
| trace_id | OTel context | 跨服务链路聚合 |
| goroutine_id | pprof runtime | 定位协程级阻塞点 |
| sample_rate | pprof.SetGoroutineProfileRate | 平衡精度与开销 |
graph TD
A[微信App] --> B[API Gateway]
B --> C[Pay Service]
C --> D[WeChat Pay SDK]
C -.-> E[pprof CPU Profile]
C -.-> F[OTel Span]
E & F --> G[OTel Collector]
G --> H[Jaeger + Grafana]
4.4 日志审计与合规性增强:符合PCI DSS的Go日志脱敏与结构化输出
PCI DSS 要求禁止在日志中明文记录持卡人主账号(PAN)、CVV、完整磁道数据等敏感字段。Go 应用需在日志写入前完成实时脱敏与结构化。
敏感字段识别与正则脱敏
使用 regexp 预编译 PAN 模式,兼顾 Luhn 校验前的模糊匹配:
var panRegex = regexp.MustCompile(`\b(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|6(?:011|5[0-9])[0-9]{12}|3[47][0-9]{13})\b`)
func sanitizePAN(logStr string) string {
return panRegex.ReplaceAllStringFunc(logStr, func(pan string) string {
return "XXXX-XXXX-XXXX-" + pan[len(pan)-4:]
})
}
逻辑分析:预编译正则提升性能;ReplaceAllStringFunc 精准定位独立 PAN 字符串;脱敏保留末四位(DSS §2.2 允许),符合最小必要原则。
结构化 JSON 输出(含审计元数据)
| 字段 | 类型 | 说明 |
|---|---|---|
| timestamp | string | RFC3339 格式时间戳 |
| level | string | “INFO”/”WARN”/”ERROR” |
| service_name | string | 服务标识(如 “payment-api”) |
| masked_pans | []string | 自动提取并脱敏的 PAN 列表 |
graph TD
A[原始日志字符串] --> B{含PAN?}
B -->|是| C[正则提取→脱敏→存入masked_pans]
B -->|否| D[空masked_pans]
C & D --> E[注入timestamp/service_name]
E --> F[JSON序列化输出]
第五章:从单体到云原生的演进路径总结
关键决策点回顾
某国内头部在线教育平台在2021年启动架构升级,初始单体应用由Spring Boot 2.3构建,部署于VMware私有云,日均请求峰值达120万。团队未直接切入Service Mesh,而是分三阶段推进:先完成模块解耦与数据库垂直拆分(用户中心、课程中心、订单中心独立DB),再基于Kubernetes 1.20搭建多租户集群,最后引入Istio 1.12实现灰度发布与熔断策略。其中,订单服务迁移时采用“双写+读流量镜像”方案,在生产环境同步写入MySQL与TiDB,通过Canal解析binlog比对数据一致性,耗时47天完成零故障切换。
技术债治理实践
遗留系统中存在大量硬编码配置与HTTP直连调用。团队建立自动化检测流水线:使用OpenRewrite扫描Java代码库,识别出386处new URL(...)调用;结合Argo CD的ConfigMap Diff功能,发现12类环境变量在dev/staging/prod间存在命名不一致。所有问题纳入Jira技术债看板,按SLA影响度分级处理——高危项(如证书过期硬编码)强制48小时内修复,中低风险项纳入季度重构计划。
组织协同模式转型
实施“康威定律反向驱动”:将原15人后端大组重组为4个跨职能小队(API网关组、可观测性组、安全合规组、业务域组),每组配备专职SRE。采用GitOps工作流,所有基础设施变更必须经PR评审,Terraform模块通过Sentinel策略引擎校验(如禁止public_ip = true在生产环境出现)。2023年Q3审计显示,配置漂移事件下降92%,平均故障恢复时间(MTTR)从47分钟压缩至6分18秒。
成本优化实证数据
迁移到云原生后资源利用率显著提升,但初期因过度分配引发新问题。通过Prometheus+VictoriaMetrics采集节点级指标,结合Kube-state-metrics分析发现:73%的Pod内存request设置高于实际使用峰值200%以上。启用Vertical Pod Autoscaler(VPA)并配合自定义推荐算法(基于过去14天P99内存使用率×1.3安全系数),6个月内集群总成本降低31.7%,具体数据如下:
| 环境 | 迁移前月均成本(万元) | 迁移后月均成本(万元) | 节省比例 |
|---|---|---|---|
| 生产 | 286.5 | 195.8 | 31.7% |
| 预发 | 42.3 | 28.9 | 31.7% |
| 开发 | 18.6 | 12.7 | 31.7% |
安全加固关键动作
在CI/CD流水线嵌入Trivy扫描所有容器镜像,同时要求Helm Chart必须通过OPA Gatekeeper策略验证。核心策略包括:禁止使用latest标签、要求镜像签名验证、限制特权容器创建。2023年全年拦截高危漏洞镜像1,247次,其中Log4j2相关漏洞占比达63%。所有通过验证的镜像自动注入SPIFFE身份证书,实现mTLS全链路加密。
graph LR
A[单体应用] --> B{解耦评估}
B -->|模块边界清晰| C[领域驱动设计建模]
B -->|依赖复杂| D[数据库读写分离+缓存层]
C --> E[独立服务部署]
D --> E
E --> F[服务网格接入]
F --> G[混沌工程常态化]
G --> H[多集群联邦管理]
监控体系演进路线
放弃传统Zabbix监控,构建以OpenTelemetry为核心的数据采集层:Java应用通过Byte Buddy无侵入注入trace,前端通过Web SDK采集RUM数据,基础设施指标由eBPF探针采集。所有数据统一转换为OTLP格式,经Jaeger Collector路由至Loki(日志)、Tempo(链路)、Prometheus(指标)三存储。告警规则全部基于PromQL编写,例如:sum(rate(http_server_requests_total{status=~\"5..\"}[5m])) by (service) > 10 触发P1级告警。
