gRPC(可选)
内置拦截器
一元/流式拦截器、服务级中间件分发机制
内置拦截器
bamboo-base-go 将拦截器按类型拆分到独立包,并提供服务级中间件分发机制。
// 一元拦截器
import xGrpcIUnary "github.com/bamboo-services/bamboo-base-go/plugins/grpc/interceptor/unary"
// 流式拦截器
import xGrpcIStream "github.com/bamboo-services/bamboo-base-go/plugins/grpc/interceptor/stream"一元拦截器(Unary)
1) Trace(默认启用)
func Trace() grpc.UnaryServerInterceptor作用:
- 从 incoming metadata 读取
x_request_uuid;若不存在则自动生成 UUID。 - 将请求 ID 写入
context(xCtx.RequestKey)。 - 记录请求开始时间(
xCtx.UserStartTimeKey)。 - 将
x_request_uuid写入 gRPC Trailer,便于全链路追踪。
xGrpcRunner.New(...)默认会把Trace()放到拦截器链首位。
2) Recover(可选挂载)
func Recover() grpc.UnaryServerInterceptor作用:
- 捕获 handler 中的 panic,避免服务进程崩溃。
- 将 panic 转换为统一 gRPC 错误响应(内部使用
ServerInternalError)。 - 记录方法名与 panic 内容,便于排障。
3) InitContext(可选挂载)
func InitContext(mainCtx context.Context) grpc.UnaryServerInterceptor作用:
- 从主上下文提取
xCtx.RegNodeKey(节点初始化结果集合)。 - 注入到每个 gRPC 请求上下文,便于业务逻辑复用已注册组件(如数据库、Redis 等)。
4) ResponseBuilder(可选挂载)
func ResponseBuilder() grpc.UnaryServerInterceptor作用:
- 统一处理 handler 返回值,自动完成错误转换与响应元数据注入。
- 应放在拦截器链末端(最接近 handler),以捕获所有上游行为。
三种处理路径
| 场景 | 条件 | 行为 |
|---|---|---|
| 错误转换 | handler 返回 error | 提取 *xError.Error,映射为 gRPC status error |
| 成功注入 | handler 返回响应对象 | 提取 BaseResponse,注入 context(追踪 ID)和 overhead(耗时) |
| 防御性处理 | 既无响应也无错误 | 返回 DeveloperError,提示检查代码逻辑 |
HTTP → gRPC 状态码映射
ResponseBuilder 内部通过 xGrpc.ToGrpcStatusCode 将业务错误码映射为 gRPC 状态码:
| HTTP 状态码 | gRPC Status Code |
|---|---|
| 400 | InvalidArgument |
| 401 | Unauthenticated |
| 403 | PermissionDenied |
| 404 | NotFound |
| 405 | Unimplemented |
| 406 | FailedPrecondition |
| 408 | DeadlineExceeded |
| 409 | Aborted |
| 410 | NotFound |
| 413 | ResourceExhausted |
| 415 | InvalidArgument |
| 422 | FailedPrecondition |
| 429 | ResourceExhausted |
| 500 | Internal |
| 502 | Unavailable |
| 503 | Unavailable |
| 504 | DeadlineExceeded |
| 其他 | Unknown |
5) Middleware(服务级中间件分发)
func Middleware() grpc.UnaryServerInterceptor作用:
- 根据
FullMethod解析出服务名,在全局注册表中查找对应的中间件链并依次执行。 - 若服务未注册中间件,直接透传到下一个 handler。
- 中间件链执行遵循洋葱模型。
流式拦截器(Stream)
流式拦截器与一元拦截器功能对应,用于处理 gRPC 流式请求。
1) Trace
func Trace() grpc.StreamServerInterceptor2) Recover
func Recover() grpc.StreamServerInterceptor3) InitContext
func InitContext(mainCtx context.Context) grpc.StreamServerInterceptor4) Middleware
func Middleware() grpc.StreamServerInterceptor流式拦截器没有
ResponseBuilder,因为流式响应由业务代码直接控制。
服务级中间件分发
概述
xGrpcMiddle 包提供按服务注册中间件的能力,支持将中间件精确绑定到特定 gRPC 服务。
import xGrpcMiddle "github.com/bamboo-services/bamboo-base-go/plugins/grpc/middleware"注册函数
// 注册一元中间件
func UseUnary(desc grpc.ServiceDesc, middlewares ...UnaryMiddlewareFunc)
// 注册流式中间件
func UseStream(desc grpc.ServiceDesc, middlewares ...StreamMiddlewareFunc)查找函数
// 查找一元中间件链
func LookupUnary(serviceName string) []UnaryMiddlewareFunc
// 查找流式中间件链
func LookupStream(serviceName string) []StreamMiddlewareFunc
// 从 FullMethod 提取服务名
func ExtractServiceName(fullMethod string) string洋葱模型执行顺序
注册顺序 [A, B, C] 的执行顺序为:
A-enter → B-enter → C-enter → handler → C-exit → B-exit → A-exit使用示例
1. 定义中间件:
func UnaryAppVerify(mainCtx context.Context) grpc.UnaryServerInterceptor {
log := xLog.WithName(xLog.NamedMIDE, "UnaryAppVerify")
appLogic := logic.NewAppLogic(mainCtx)
return func(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (any, error) {
// 从 metadata 提取认证信息
appIDStr, xErr := xUtil.ExtractMetadata(ctx, xGrpcConst.MetadataAppAccessID)
secretKey, xErr := xUtil.ExtractMetadata(ctx, xGrpcConst.MetadataAppSecretKey)
if xErr != nil {
return nil, xErr
}
// 验证逻辑...
return handler(ctx, req)
}
}2. 注册到服务:
func NewNormalUploadProto(ctx context.Context, server grpc.ServiceRegistrar) *NormalUploadProto {
handler := &NormalUploadProto{
log: xLog.WithName(xLog.NamedGRPC, "NormalUploadProto"),
// ...
}
// 注册 gRPC 服务
bGrpcApi.RegisterNormalUploadServiceServer(server, handler)
// 绑定服务级中间件(只对此服务生效)
xGrpcMiddle.UseUnary(bGrpcApi.NormalUploadService_ServiceDesc, middleware.UnaryAppVerify(ctx))
return handler
}3. 启用分发拦截器:
grpcTask := xGrpcRunner.New(
xGrpcRunner.WithRegisterService(registerGrpcService),
xGrpcRunner.WithUnaryInterceptors(
xGrpcIUnary.InitContext(reg.Init.Ctx),
xGrpcIUnary.Recover(),
xGrpcIUnary.Middleware(), // 服务级中间件分发
xGrpcIUnary.ResponseBuilder(), // 放在最后
),
)推荐挂载顺序
xGrpcRunner.WithUnaryInterceptors(
xGrpcIUnary.InitContext(reg.Init.Ctx), // 1. 注入上下文
xGrpcIUnary.Recover(), // 2. Panic 捕获
xGrpcIUnary.Middleware(), // 3. 服务级中间件分发
xGrpcIUnary.ResponseBuilder(), // 4. 响应构建(最后)
)
Trace()由 Runner 默认添加,位于链首。
完整链路顺序:
Trace()(Runner 默认)InitContext(...)(你追加)Recover()(你追加)Middleware()(你追加)- 服务级中间件链(若有)
ResponseBuilder()(你追加)- 业务 Handler