简单地说,在分布式系统中,中间件(middleware)是一个软件组件,用来连接不同的软件组件,从而将客户端生成的请求路由至后端服务器。在 gRPC 中间件中,我们讨论的也是在 gRPC 服务器端或客户端应用程序之前或之后运行代码。

实际上,gRPC 中间件基于第 5 章所介绍的拦截器的概念。它是基于 Go语言的一组拦截器、辅助器(helper)和工具的集合,在构建基于 gRPC的应用程序时,我们会用到它们。它允许在客户端或服务器端以拦截器链的形式应用多个拦截器。同时,因为拦截器经常用来实现通用的模式,如认证、日志、消息、校验、重试或监控,所以 gRPC 中间件项目是 Go 语言中实现这些可重用功能的首选方案。代码清单 8-4 展示了gRPC 中间件包常见的用法。在这里,一元消息和流消息都使用了多个
拦截器。

代码清单 8-4 在服务器端使用 Go gRPC 中间件实现的拦截器链

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

orderMgtServer := grpc.NewServer(
    grpc.Unaryinterceptor(grpc_middleware.ChainUnaryServer( ➊
        grpc_ctxtags.UnaryServerinterceptor(),
        grpc_opentracing.UnaryServerinterceptor(),
        grpc_prometheus.UnaryServerinterceptor,
        grpc_zap.UnaryServerinterceptor(zapLogger),
        grpc_auth.UnaryServerinterceptor(myAuthFunction),
        grpc_recovery.UnaryServerinterceptor(),
    )),

    grpc.Streaminterceptor(grpc_middleware.ChainStreamServer( ➋
        grpc_ctxtags.StreamServerinterceptor(),
        grpc_opentracing.StreamServerinterceptor(),
        grpc_prometheus.StreamServerinterceptor,
        grpc_zap.StreamServerinterceptor(zapLogger),
        grpc_auth.StreamServerinterceptor(myAuthFunction),
        grpc_recovery.StreamServerinterceptor(),
    )),
)
  • ❶ 为服务器端添加一元拦截器链。
  • ❷ 为服务器端添加流拦截器链。

这些拦截器会按照 Go gRPC 中间件注册的顺序进行调用。该项目还为通用的模式提供了一些可重用的拦截器。以下是一些通用的模式和拦截器实现。

认证

  • grpc_auth
    可自定义的(通过 AuthFunc)认证中间件。

日志

  • grpc_ctxtags
    添加 Tag map 到上下文的库,数据是通过请求体来填充的。

  • grpc_zap
    将 zap 日志库集成到 gRPC handler 中。

  • grpc_logrus
    将 logrus 日志库集成到 gRPC handler 中。

监控

  • grpc_prometheus
    Prometheus 客户端和服务器端的监控中间件。

  • grpc_opentracing
    OpenTracing 客户端和服务器端的拦截器,支持流和 handler返回的标签。

客户端

  • grpc_retry
    通用的 gRPC 响应码重试机制,客户端中间件。

服务器端

  • grpc_validator
    根据 .proto 选项生成入站消息校验。

  • grpc_recovery
    将 panic 转换成 gRPC 错误。

  • ratelimit
    通过自己的限制器对 gRPC 进行速度限制。

在客户端,Go gRPC 中间件的用法是完全相同的。代码清单 8-5 展示了使用 Go gRPC 中间件实现客户端拦截器链的代码片段。

代码清单 8-5 在客户端使用 Go gRPC 中间件实现的拦截器链

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

clientConn, err = grpc.Dial(
    address,
    grpc.WithUnaryinterceptor(grpc_middleware.ChainUnaryClient(
        monitoringClientUnary, retryUnary)), ➊
        grpc.WithStreaminterceptor(grpc_middleware.ChainStreamClient(
        monitoringClientStream, retryStream)), ➋
)
  • ❶ 客户端一元拦截器链。
  • ❷ 客户端流拦截器链。

与服务器端类似,拦截器会按照它们在客户端注册的顺序执行。

接下来将讨论如何暴露 gRPC 服务器的健康状态。在一个高可用的系统中,具有一个检查服务器健康状态的方法是至关重要的,这样能定期检查并采取措施来减少损害。

文档更新时间: 2023-09-02 08:06   作者:Minho