必须在http handler或grpc interceptor入口手动注入x-test-flag等不可伪造业务标识,并通过context.withvalue全程透传,下游服务据此动态路由至影子库或mock依赖,避免依赖可复用的trace id。

怎么让压测流量被下游服务准确识别
压测流量必须带不可伪造的业务标识,不能只靠 X-B3-TraceId 或 X-Request-ID 判断——这些 ID 可能被复用、重放或由非压测路径生成。真实有效的识别方式只有一种:在入口(HTTP handler 或 gRPC interceptor)手动注入独立字段,并全程透传。
- HTTP 层:检查请求 header 中是否存在
X-Test-Flag: 1或X-Env-Type: stress,存在则用context.WithValue(ctx, testKey, true)注入上下文 - gRPC 层:在 unary interceptor 中调用
metadata.FromIncomingContext(ctx)提取X-Test-Flag,再通过context.WithValue保存;发起下游调用前,用metadata.AppendToOutgoingContext(ctx, "X-Test-Flag", "1")回写 - 注意 Nginx 默认 header 大小限制为 4KB,避免在 header 里塞 base64 编码的完整测试上下文,否则请求直接被 400 拦截
数据库和 Redis 怎么做到读写隔离不污染生产
不能靠配置开关切换连接池,也不能在 SQL 里拼接 stress_ 前缀——ORM(如 GORM)会解析失败,且无法覆盖所有 DAO 调用路径。正确做法是让 DAO 层根据 context 动态路由。
- DB:初始化时创建两个
*sql.DB实例(prodDB和stressDB),DAO 方法接收ctx context.Context,通过ctx.Value(testKey)判断是否压测,再选择对应连接池执行db.Query - Redis:封装
redis.Client,在Get/Set方法内检查ctx.Value(testKey),若为真,则对 key 自动加前缀,例如"user:1001"→"stress_user_1001" - Elasticsearch/Kafka 同理:
orders_stresstopic、stress_ordersindex、消费者 group id 改为order-consumer-stress
第三方依赖(支付/短信)如何安全 mock
压测期间调用真实第三方服务既不合规也不可控,mock 必须在编译期或运行期彻底切断链路,而不是“返回假数据但还走网络”。两种方式可选,优先级分明。
- 接口抽象 + 依赖注入:定义
SmsClient interface,启动时根据环境变量ENV=stress注入 mock 实现(返回固定 JSON),真实 client 完全不初始化 - HTTP 拦截兜底:若无法改结构,用自定义
http.RoundTripper,在RoundTrip中匹配req.URL.Host == "sms-api.example.com",直接构造响应并 return,不发任何真实请求 - 别用
gock做压测 mock——它只拦截 outgoing 请求,不校验响应契约,字段缺失或类型错不会报错,容易掩盖真实兼容性问题
为什么不能用 go test -bench 替代全链路压测
go test -bench 测的是单函数吞吐和延迟,跟线上真实压测完全不是一回事。它不经过网关、不透传 header、不走 gRPC metadata、不触发 JWT 验签、不模拟超时级联,更不会暴露熔断器打满、日志刷屏、连接池耗尽这些关键问题。
- 真正要验证的,是请求从入口到 DB 全路径上的可观测性埋点是否完整、trace 是否丢帧、各层 timeout 是否合理传导
- 录制回放才是逼近真实的方案:用
kitex的GenericInvoke+ 中间件捕获原始 protobuf payload,HTTP 层用io.TeeReader双写 body,同时给下游 handler 和存档 buffer - 录制时必须剥离敏感字段:
Authorization、手机号、身份证号等,否则回放会触发风控或写脏生产数据
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











