0x00 前言
Interceptor 机制极大的扩展了 gRPC 的功能。注意,服务器只能配置一个 Unary interceptor 和 Stream interceptor,否则会报错。客户端也类似,虽然不会报错,但是只有最后一个才起作用。 如果你想配置多个,可以使用这个 chain.go。
0x01 开源的 Interceptor
本文介绍的开源项目 grpc-ecosystem:go-grpc-middleware,提供了拦截器 Interceptor 链式的功能,即可以将多个拦截器组合成一个拦截器链。此外,该库还提供了常用拦截器的实现(可使用 chain 方式将它们打包起来),从官方文档看,有如下这些,涵盖了认证、日志、监控、客户端重连及服务端(参数校验 / recovery 恢复 / 限流等):
Auth
grpc_auth
- a customizable (viaAuthFunc
) piece of auth middleware
Logging
grpc_ctxtags
- a library that adds aTag
map to context, with data populated from request bodygrpc_zap
- integration of zap logging library into gRPC handlers.grpc_logrus
- integration of logrus logging library into gRPC handlers.grpc_kit
- integration of go-kit logging library into gRPC handlers.
Monitoring
grpc_prometheus
- Prometheus client-side and server-side monitoring middlewareotgrpc
- OpenTracing client-side and server-side interceptorsgrpc_opentracing
- OpenTracing client-side and server-side interceptors with support for streaming and handler-returned tags
Client
grpc_retry
- a generic gRPC response code retry mechanism, client-side middleware
Server
grpc_validator
- codegen inbound message validation from.proto
optionsgrpc_recovery
- turn panics into gRPC errorsratelimit
- grpc rate limiting by your own limiter
如果日常使用 gRPC 完成服务端项目需要使用拦截器的话,直接从现有的轮子里面寻找就可以了:)
0x02 chain 实现
go-grpc-middleware 的 拦截器链 实现。
0x03 go-grpc-middleware 使用
本小节列举一些拦截器的使用例子:
限流 Ratelimit
先简单看下限流拦截器的 实现:
需要开发者实现 Limiter
接口,此接口中包含了唯一的方法 Limit() bool
,也很好理解,返回 true
表示需要被拦截(限流生效),反之请求被 Pass。可以结合常见的限流方案使用。
PS:这里可以根据限流返回的结果做一些 额外的事情,参考 Kratos 项目的 BBR 限流方案,是一款自适应限流拦截器的实现。参见 Kratos 源码分析:限流器 Limiter 一文分析。
// Limiter defines the interface to perform request rate limiting.
// If Limit function return true, the request will be rejected.
// Otherwise, the request will pass.
type Limiter interface {
Limit() bool
}
// UnaryServerInterceptor returns a new unary server interceptors that performs request rate limiting.
func UnaryServerInterceptor(limiter Limiter) grpc.UnaryServerInterceptor {
return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
// 限流
if limiter.Limit() {
return nil, status.Errorf(codes.ResourceExhausted, "%s is rejected by grpc_ratelimit middleware, please retry later.", info.FullMethod)
}
// 不限流,进入下面的拦截器逻辑
return handler(ctx, req)
}
}
0x04 使用开源的 Interceptor 的心得
- 明确使用时客户端拦截器还是服务端拦截器
- 查看拦截器的功能
- 拦截器链中的先后顺序(摆放顺序),非常重要,比如一般
recovery
拦截器通常建议放置在首位 - 改造,融合到自己的框架中
0x05 参考
转载请注明出处,本文采用 CC4.0 协议授权
FEATURED TAGS
Latex
gRPC
负载均衡
OpenSSH
Authentication
Consul
Etcd
Kubernetes
性能优化
Python
分布式锁
WebConsole
后台开发
Golang
OpenSource
Nginx
Vault
网络安全
Perl
分布式理论
Raft
正则表达式
Redis
分布式
限流
go-redis
微服务
反向代理
ReverseProxy
Cache
缓存
连接池
OpenTracing
GOMAXPROCS
GoMicro
微服务框架
日志
zap
Pool
Kratos
Hystrix
熔断
并发
Pipeline
证书
Prometheus
Metrics
PromQL
Breaker
定时器
Timer
Timeout
Kafka
Xorm
MySQL
Fasthttp
bytebufferpool
任务队列
队列
异步队列
GOIM
Pprof
errgroup
consistent-hash
Zinx
网络框架
设计模式
HTTP
Gateway
Queue
Docker
网关
Statefulset
NFS
Machinery
Teleport
Zero Trust
Oxy
存储
Confd
热更新
OAuth
SAML
OpenID
Openssl
AES
微服务网关
IM
KMS
安全
数据结构
hashtable
Sort
Asynq
基数树
Radix
Crontab
热重启
系统编程
sarama
Go-Zero
RDP
VNC
协程池
UDP
hashmap
网络编程
自适应技术
环形队列
Ring Buffer
Circular Buffer
InnoDB
timewheel
GroupCache
Jaeger
GOSSIP
CAP
Bash
websocket
事务
GC
TLS
singleflight
闭包
Helm
network
iptables
MITM
HTTPS
Tap
Tun
路由
wireguard
gvisor
Git
NAT
协议栈
Envoy
FRP
DPI
gopacket
Cgroup
Namespace
DNS
eBPF
GoZero
Gost
Clash
gopsutil
HIDS
ELKEID
XDP
TC
Linux