商城首页欢迎来到中国正版软件门户

您的位置:首页 >Golang gRPC拦截器使用与实战示例

Golang gRPC拦截器使用与实战示例

  发布于2025-10-06 阅读(0)

扫一扫,手机访问

拦截器在Go语言gRPC中用于实现日志、认证等通用逻辑,分为一元和流式两种类型。一元拦截器处理普通RPC调用,通过grpc.UnaryInterceptor注册,可在请求前后执行日志记录等操作;流式拦截器处理流式接口,通过grpc.StreamInterceptor注册,适用于客户端流、服务端流或双向流场景;实际应用中可结合go-grpc-middleware库使用ChainUnaryServer和ChainStreamServer组合多个拦截器,如日志、认证(从metadata提取token验证)和错误恢复,提升系统可维护性与安全性。

Golang gRPC拦截器实现与应用示例

在 Go 语言中使用 gRPC 时,拦截器(Interceptor)是一种非常强大的机制,可以在请求处理前后插入通用逻辑,比如日志记录、认证、限流、监控等。gRPC 支持两种类型的拦截器:一元拦截器(Unary Interceptor)和流式拦截器(Streaming Interceptor)。下面详细介绍其实现方式与实际应用示例。

一元拦截器(Unary Interceptor)

一元拦截器用于拦截普通的 RPC 调用(即非流式调用),它本质上是一个中间件函数,包裹在服务方法执行前后。

// 定义一个简单的日志一元拦截器

func LoggingUnaryInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) {
    log.Printf("Received unary request: %s", info.FullMethod)
    resp, err = handler(ctx, req)
    log.Printf("Finished unary request: %s, error: %v", info.FullMethod, err)
    return resp, err
}

该拦截器在每次调用前打印请求方法名,在调用完成后输出执行结果。通过 handler(ctx, req) 触发实际的服务逻辑。

注册到 gRPC 服务器

s := grpc.NewServer(grpc.UnaryInterceptor(LoggingUnaryInterceptor))

流式拦截器(Streaming Interceptor)

流式拦截器用于处理 gRPC 流(stream)类型的接口,如客户端流、服务端流或双向流。

// 定义一个基础的流式拦截器

func LoggingStreamInterceptor(srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
    log.Printf("Received stream request: %s", info.FullMethod)
    err := handler(srv, ss)
    log.Printf("Finished stream request: %s, error: %v", info.FullMethod, err)
    return err
}

注意,流式拦截器无法直接读取消息内容,因为数据是通过 Recv()Send() 在流上传输的。若需记录具体数据,可封装 ServerStream 实现包装器。

注册流式拦截器:

s := grpc.NewServer(grpc.StreamInterceptor(LoggingStreamInterceptor))

结合多个拦截器

实际项目中通常需要多个拦截器,例如同时做日志、认证和错误恢复。可以使用 go-grpc-middleware 库来组合多个拦截器。

// 安装中间件库

go get github.com/grpc-ecosystem/go-grpc-middleware

使用示例:

import "github.com/grpc-ecosystem/go-grpc-middleware"
import "github.com/grpc-ecosystem/go-grpc-middleware/auth"

s := grpc.NewServer(
    grpc.UnaryInterceptor(grpc_middleware.ChainUnaryServer(
        LoggingUnaryInterceptor,
        auth.UnaryServerInterceptor(myAuthFunc),
        recovery.UnaryServerInterceptor(),
    )),
    grpc.StreamInterceptor(grpc_middleware.ChainStreamServer(
        LoggingStreamInterceptor,
        auth.StreamServerInterceptor(myAuthFunc),
    )),
)

其中 myAuthFunc 是自定义认证函数,例如从 metadata 中提取 token 并验证。

实际应用场景示例

假设我们要实现一个基于 Token 的认证拦截器:

func myAuthFunc(ctx context.Context) (context.Context, error) {
    md, ok := metadata.FromIncomingContext(ctx)
    if !ok {
        return nil, status.Errorf(codes.Unauthenticated, "missing metadata")
    }
    tokens := md["token"]
    if len(tokens) == 0 {
        return nil, status.Errorf(codes.Unauthenticated, "missing token")
    }
    if tokens[0] != "secret" {
        return nil, status.Errorf(codes.PermissionDenied, "invalid token")
    }
    return ctx, nil
}

客户端调用时需带上 token:

ctx := metadata.AppendToOutgoingContext(context.Background(), "token", "secret")
resp, err := client.YourMethod(ctx, &request)

基本上就这些。拦截器让 gRPC 服务具备良好的可扩展性和维护性,合理使用能大幅提升系统健壮性。
本文转载于:互联网 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。

热门关注