【gRPC】gRPC拦截器使用指南(客户端、服务端拦截器、拦截器链设置顺序) |
您所在的位置:网站首页 › shiro拦截器顺序 › 【gRPC】gRPC拦截器使用指南(客户端、服务端拦截器、拦截器链设置顺序) |
1.拦截器是什么?
gRPC拦截器(interceptor)是一种函数,它可以在gRPC调用之前和之后执行一些逻辑,例如认证、授权、日志记录、监控和统计等。拦截器函数是gRPC中非常重要的概念,它允许我们在服务端和客户端添加自定义逻辑,以满足业务需求和运维需求。 在gRPC中,拦截器函数通常通过实现grpc.UnaryServerInterceptor和grpc.StreamServerInterceptor接口来定义。UnaryServerInterceptor用于拦截一元RPC请求,而StreamServerInterceptor用于拦截流式RPC请求。在客户端中,我们可以使用grpc.UnaryClientInterceptor和grpc.StreamClientInterceptor来拦截gRPC调用。 在gRPC中,拦截器函数可以被链接起来,形成一个拦截器链。在这个拦截器链中,每个拦截器函数都可以处理请求并将其转发给下一个拦截器函数,或者直接返回响应。因此,我们可以在拦截器函数中编写不同的逻辑,例如实现认证、授权、监控和统计等。 以下是一些常见的gRPC拦截器: 认证和授权拦截器:用于对gRPC调用进行身份验证和权限控制,例如检查token、验证用户名和密码、检查访问控制列表等; 日志记录拦截器:用于记录gRPC调用的日志,例如记录请求的方法、参数、响应状态等; 监控和统计拦截器:用于监控gRPC调用的性能和吞吐量,例如记录调用次数、响应时间、错误率等; 缓存拦截器:用于在服务端或客户端缓存一些数据,例如缓存计算结果、缓存数据库查询结果等。开源的gRPC拦截器库: go-grpc-middleware 2.客户端拦截器在gRPC客户端中,可以使用拦截器来记录日志,客户端的拦截器可以在每个gRPC调用前后执行一些逻辑,例如记录请求和响应的信息。 下面是一个示例,说明如何使用拦截器来记录gRPC调用的日志: 注意,这里使用的是grpc.WithUnaryInterceptor(),与服务器的拦截器方法不同。可以使用ctrl 按住方法直接复制要写的 UnaryInterceptor 函数体 import ( "context" "log" "google.golang.org/grpc" ) func UnaryInterceptor(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error { log.Printf("method=%s, request=%+v", method, req) err := invoker(ctx, method, req, reply, cc, opts...) if err != nil { log.Printf("method=%s, error=%v", method, err) } else { log.Printf("method=%s, response=%+v", method, reply) } return err } func main() { // 创建一个grpc连接,拨号时添加注册拦截器 conn, err := grpc.Dial( "localhost:50051", grpc.WithUnaryInterceptor(UnaryInterceptor), ) if err != nil { log.Fatalf("failed to connect: %v", err) } defer conn.Close() // 创建一个客户端 client := pb.NewMyServiceClient(conn) // 发起一个gRPC调用 resp, err := client.MyMethod(context.Background(), &pb.MyRequest{}) if err != nil { log.Fatalf("failed to call MyMethod: %v", err) } log.Printf("response=%+v", resp) } 复制代码客户端打印结果: 服务端打印结果: 在gRPC中,拦截器的优先级取决于它们被添加到拦截器链中的顺序。在ChainUnaryInterceptor方法中,第一个拦截器函数将是最外层的函数,而最后一个拦截器函数将是最内层的函数。因此,如果我们想要设置拦截器的优先级,可以通过调整它们的添加顺序来实现。 以下是一个示例,说明如何为两个拦截器函数设置优先级: import ( "context" "log" "google.golang.org/grpc" ) func LoggingInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { log.Printf("logging interceptor: method=%s, request=%+v", info.FullMethod, req) resp, err := handler(ctx, req) if err != nil { log.Printf("logging interceptor: method=%s, error=%v", info.FullMethod, err) } else { log.Printf("logging interceptor: method=%s, response=%+v", info.FullMethod, resp) } return resp, err } func AuthInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { log.Printf("auth interceptor: method=%s, request=%+v", info.FullMethod, req) resp, err := handler(ctx, req) if err != nil { log.Printf("auth interceptor: method=%s, error=%v", info.FullMethod, err) } else { log.Printf("auth interceptor: method=%s, response=%+v", info.FullMethod, resp) } return resp, err } func main() { // 创建一个grpc服务器 s := grpc.NewServer( grpc.ChainUnaryInterceptor( LoggingInterceptor, AuthInterceptor, ), ) // 注册服务 pb.RegisterMyServiceServer(s, &server{}) // 启动服务器 s.Serve(listener) } 复制代码在这个例子中,我们为gRPC服务器添加了两个拦截器函数:LoggingInterceptor和AuthInterceptor。在拦截器链中,LoggingInterceptor将会是最外层的函数,而AuthInterceptor将会是最内层的函数。这意味着LoggingInterceptor将首先被调用,然后再调用AuthInterceptor。 如果我们想要改变它们的顺序,例如将AuthInterceptor放在LoggingInterceptor之前,可以通过调整拦截器的添加顺序来实现。例如,将ChainUnaryInterceptor方法中的拦截器函数列表修改为: grpc.ChainUnaryInterceptor( AuthInterceptor, LoggingInterceptor, ) 复制代码这样,AuthInterceptor将会是最外层的函数,而LoggingInterceptor将会是最内层的函数,这样我们就为拦截器函数设置了优先级。 |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |