简单地说,在分布式系统中,中间件(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 服务器的健康状态。在一个高可用的系统中,具有一个检查服务器健康状态的方法是至关重要的,这样能定期检查并采取措施来减少损害。