grpc-ecosystem/go-grpc-middleware

GitHub: grpc-ecosystem/go-grpc-middleware

该项目为 Go 语言的 gRPC 提供了一套开箱即用的拦截器中间件库,涵盖认证、可观测性、重试和限流等通用功能,帮助开发者以链式调用的方式统一管理微服务的横切关注点。

Stars: 6760 | Forks: 744

# Go gRPC Middleware [![go](https://static.pigsec.cn/wp-content/uploads/repos/cas/8e/8eb834cabb8636519e16b6855334abcf1caec8774e8bba436ebd79d4fe1606e5.svg)](https://github.com/grpc-ecosystem/go-grpc-middleware/actions?query=branch%3Av2) [![Go Report Card](https://goreportcard.com/badge/github.com/grpc-ecosystem/go-grpc-middleware)](https://goreportcard.com/report/github.com/grpc-ecosystem/go-grpc-middleware) [![GoDoc](http://img.shields.io/badge/GoDoc-Reference-blue.svg)](https://godoc.org/github.com/grpc-ecosystem/go-grpc-middleware/v2) [![Apache 2.0 License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](LICENSE) [![Slack](https://img.shields.io/badge/slack-%23grpc--middleware-brightgreen)](https://gophers.slack.com/archives/CNJL30P4P) 本仓库包含了 [gRPC Go](https://github.com/grpc/grpc-go) 中间件:拦截器、辅助工具和实用程序。 ## 中间件 [gRPC Go](https://github.com/grpc/grpc-go) 支持“拦截器”,即在 gRPC 服务器上将请求传递给用户应用程序逻辑之前执行,或者在 gRPC 客户端上围绕用户调用执行的[中间件](https://medium.com/@matryer/writing-middleware-in-golang-and-how-go-makes-it-so-much-fun-4375c1246e81#.gv7tdlghs)。这是实现通用模式的绝佳方式:认证、日志记录、链路追踪、指标监控、验证、重试、速率限制等,它们可以作为出色的通用构建块,让你能够轻松构建多个微服务。 特别是对于可观测性信号(日志记录、链路追踪、指标监控),拦截器提供了半自动化的插桩(instrumentation)功能,这不仅提高了可观测性的一致性,还允许使用出色的关联技术(例如,日志中的 exemplars 和 trace ID)。演示请参见[示例](examples)。 本仓库提供了实现 gRPC 拦截器的现成中间件及示例。在某些情况下,专门的项目已经提供了出色的拦截器,因此本仓库不再包含这些内容,我们会在[拦截器](#interceptors)列表中附上它们的链接。 拦截器的另一个出色特性是支持链式调用。例如,你可以在下面找到一个包含完整可观测性关联、认证和 panic 恢复的服务器端拦截器链示例: ``` grpcSrv := grpc.NewServer( grpc.StatsHandler(otelgrpc.NewServerHandler()), grpc.ChainUnaryInterceptor( srvMetrics.UnaryServerInterceptor( grpcprom.WithExemplarFromContext(exemplarFromContext), grpcprom.WithLabelsFromContext(labelsFromContext), ), logging.UnaryServerInterceptor(interceptorLogger(rpcLogger), logging.WithFieldsFromContext(logTraceID)), selector.UnaryServerInterceptor(auth.UnaryServerInterceptor(authFn), selector.MatchFunc(allButHealthZ)), recovery.UnaryServerInterceptor(recovery.WithRecoveryHandler(grpcPanicRecoveryHandler)), ), grpc.ChainStreamInterceptor( srvMetrics.StreamServerInterceptor( grpcprom.WithExemplarFromContext(exemplarFromContext), grpcprom.WithLabelsFromContext(labelsFromContext), ), logging.StreamServerInterceptor(interceptorLogger(rpcLogger), logging.WithFieldsFromContext(logTraceID)), selector.StreamServerInterceptor(auth.StreamServerInterceptor(authFn), selector.MatchFunc(allButHealthZ)), recovery.StreamServerInterceptor(recovery.WithRecoveryHandler(grpcPanicRecoveryHandler)), ), ) ``` 这种模式为你所有的 gRPC 方法提供了干净且显式的共享功能。完整的、可编译的示例可以在[示例](examples)目录中找到。 ## 拦截器 此列表涵盖了用户在 Go 微服务中使用的已知拦截器(包括本仓库内和外部项目)。点击每一项可以查看 `examples_test.go` 中的扩展示例(也可在 [pkg.go.dev](https://godoc.org/github.com/grpc-ecosystem/go-grpc-middleware/v2) 上找到)。 所有路径都应支持使用 `go get `。 #### 认证 - [`github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/auth`](interceptors/auth) - 可通过 `AuthFunc` 自定义的认证中间件。 - (外部) [`google.golang.org/grpc/authz`](https://github.com/grpc/grpc-go/blob/master/authz/grpc_authz_server_interceptors.go) - 更复杂、可通过认证策略(类似 RBAC)进行自定义的认证中间件。 #### 可观测性 - 指标: - [`github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus`⚡](providers/prometheus) - 客户端和服务器端的 Prometheus 监控中间件。支持 exemplars。现已从弃用的 [`go-grpc-prometheus`](https://github.com/grpc-ecosystem/go-grpc-prometheus) 迁移。 - (外部) [`go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc`](https://go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc) - 官方 OpenTelemetry 拦截器(指标和链路追踪)。 - 使用 [`github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/logging`](interceptors/logging) 进行日志记录 - 提供扩展按请求日志记录的可自定义日志中间件。它需要日志适配器,请参阅 [`interceptors/logging/examples`](interceptors/logging/examples) 中的示例,支持 `go-kit`、`log`、`logr`、`logrus`、`slog`、`zap` 和 `zerolog`。 - 注意:带有 [context](https://pkg.go.dev/context) 字段注入的拦截器需要在适配器函数之前进行链式调用。 - 链路追踪: - (外部) [`go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc`](https://go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc) - [示例](examples)中所使用的官方 OpenTelemetry 拦截器(指标和链路追踪)。 - (外部) [`github.com/grpc-ecosystem/go-grpc-middleware/tracing/opentracing`](https://pkg.go.dev/github.com/grpc-ecosystem/go-grpc-middleware@v1.4.0/tracing/opentracing) - 如果你仍然需要,可使用已弃用的 [OpenTracing](http://opentracing.io/) 客户端和服务器端拦截器! #### 客户端 - [`github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/retry`](interceptors/retry) - 通用的 gRPC 响应码重试机制,客户端中间件。 - 注意:grpc-go 也支持带有高级策略的本地重试 (https://github.com/grpc/grpc-go/blob/v1.54.0/examples/features/retry/client/main.go) - [`github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/timeout`](interceptors/timeout) - 通用的 gRPC 请求超时机制,客户端中间件。 #### 服务器端 - [`github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/validator`](interceptors/validator) - 基于 `.proto` 选项进行代码生成的入站消息验证。 - [`github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/recovery`](interceptors/recovery) - 将 panic 转换为 gRPC 错误(请确保将其用作“最后”一个拦截器,以确保 panic 不会跳过其他拦截器)。 - [`github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/ratelimit`](interceptors/ratelimit) - 通过自定义限流器进行 gRPC 速率限制。 - [`github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/protovalidate`](interceptors/protovalidate) - 通过 [protovalidate-go](https://github.com/bufbuild/protovalidate) 基于 `.proto` 选项进行消息验证。 #### 过滤拦截器 - [`github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/selector`](interceptors/selector) - 允许用户在特定条件下(如匹配服务方法)选择指定的一个或多个拦截器。 ## 前置条件 - **[Go](https://golang.org)**:支持最近**三个主要**[版本](https://golang.org/doc/devel/release.html)中的任意一个。 ## 本仓库结构 主要的拦截器位于 [`interceptors` 目录](interceptors)的子目录中,例如 [`interceptors/validator`](interceptors/validator)、[`interceptors/auth`](interceptors/auth) 或 [`interceptors/logging`](interceptors/logging)。 某些拦截器或拦截器工具需要依赖于大量依赖项的特定代码。这些代码作为独立的 Go 模块放置在 `providers` 目录中,并具有独立的版本控制。例如,[`providers/prometheus`](providers/prometheus) 提供了指标中间件(目前没有“interceptor/metrics”)。单独的模块在 `go.mod` 中可能稍微难以发现和管理版本,但它使得核心拦截器在依赖项方面变得极其精简。 [`interceptors` 目录](interceptors)还包含了接受 [`Reporter`](interceptors/reporter.go) 接口的通用拦截器,该接口让你能够轻松创建自定义中间件。 你可能已经注意到,本仓库包含多个不同版本的模块([Go 模块特性](https://github.com/golang/go/wiki/Modules#faqs--multi-module-repositories))。当前模块请参阅 [versions.yaml](versions.yaml)。我们拥有版本为 2.x.y 的主模块以及版本较低的 providers 模块。由于主模块是 v2,其模块路径以 `v2` 结尾: ``` go get github.com/grpc-ecosystem/go-grpc-middleware/v2/ ``` 对于 providers 模块和包,由于它们是 v1,路径中没有添加版本号,例如: ``` go get github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus ``` ## 相比 v1 的变更 [go-grpc-middleware v1](https://pkg.go.dev/github.com/grpc-ecosystem/go-grpc-middleware) 创建于 2015 年左右,并成为了 gRPC 用户的热门选择。然而,此后许多事情都发生了变化。v2 相比 v1 的主要变更如下: - 在“providers”中提供了独立、多个 Go 模块的路径。如果需要,这允许将来为特定的中间件添加专门的 providers。这使得拦截器可以在不依赖核心框架地狱的情况下进行扩展(例如,如果你使用其他指标 provider,你真的想导入 prometheus 吗?)。这提供了更高的可扩展性。 - 移除了 Loggers。[`interceptors/logging`](interceptors/logging) 得到了简化,为每个 logger 编写适配器变得非常简单。为了方便起见,我们将在 [`interceptors/logging/examples`](interceptors/logging/examples) 中维护流行 providers 的示例,但这些示例旨在供复制使用,而不是直接导入。 - 移除了 `grpc_opentracing` 拦截器。这是因为链路追踪插桩已经演进。OpenTracing 已被弃用,OpenTelemetry 现在提供了一个[更出色的链路追踪拦截器](https://go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc)。 - 移除了 `grpc_ctxtags` 拦截器。可以使用 `logging.InjectFields` 将自定义标签添加到日志字段中。在实践中,用于添加日志字段的 Proto 选项显得很笨重,而且我们如今没看到它的任何用途,因此将其移除了。 - 从 https://github.com/grpc-ecosystem/go-grpc-prometheus 引入了最强大的拦截器之一(该仓库现已弃用)。这种整合使得维护更容易、使用更便捷,并且 API 保持一致。 - 移除了链式拦截器,因为 `grpc` 已经实现了一个。 - 迁移到了新的 proto API (google.golang.org/protobuf)。 - 移除了所有的“deciders”,即那些根据 gRPC 服务名称和方法(又称“fullMethodName”)决定操作行为的函数(!)。请使用 [`github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/selector`](interceptors/selector) 拦截器来选择什么方法、类型或服务应使用什么拦截器。 - 不再使用蛇形(snake case)命名的包名。我们现在使用具有单一词汇且意义明确的包名。如果包名发生冲突,我们建议添加 grpc 前缀,例如 `grpcprom "github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus"`。 - 所有选项(如果有)均采用 `.With