大型分布式系统...原云生实践

Go 实现 gRPC 代理网关和流控功能

2023-05-04  本文已影响0人  codeandcode

今天给大家推荐一个 Go 语音实现的 gRPC 代理/网关,配置简单、开箱即用。先和大家介绍一下负载原理:

gRPC 负载均衡和反向代理

代理基本原理:

  1. 基于TCP启动一个gRPC代理服务 ;
  2. 将gRPC请求的服务拦截到转发代理的一个函数中执行 ;
  3. 接收客户端的请求,处理业务指标后转发给服务端 ;
  4. 接收服务端的响应,处理业务指标后转发给客户端 ;

gRPC的客户端将所有的请求都发给 gRPC Server Proxy,这个代理网关实现请求转发,将gRPC Client的请求流转发到gRPC 服务实现的节点上。并将服务处理结果响应返回给客户端 。

HandleStream 中 unknownService

在 gRPC 框架代码中的 HandleStream 存在两类服务,一类是已知服务 knownService, 第二类是 unknownService ;已知服务 knownService 就是 gRPC 服务端代码注册到 gRPC 框架中的服务,叫做已知服务,其他没有注册的服务叫做未知服务,这个未知服务 unknownService 就是我们实现 gRPC 服务代码的关键所在;


要实现 gRPC 服务代理,我们在创建 gRPC 服务 grpc.NewServer 时,传递一个未知服务的 Handler,将未知服务的处理进行接管,然后通过注册的这个 Handler 实现 gRPC 代理转发的逻辑.


GrpcProxyTransport 接口

GrpcProxyTransport 是自定义的 StreamDirector,将 unknownService 的请求由 GrpcProxyTransport 层处理(这里有实现比较负责的连接池 + 负载均衡 的设计),提供代理和负载的能力;

基于如上描述,gRPC 代理的原理如下:

  1. 创建 gRPC 服务时,注册一个未知服务处理器 Handler 和一个自定义的编码 Codec 编码和解码,此处使用 proto 标准的 Codec;
  2. 这个 Handle 给业务方预留一个 director 的接口,用于代理重定向转发的 gRPC 连接获取,这样 proxy 就可以通过 redirector 得到 gRPCServer 的 gRPC 连接。
  3. Proxy 接收 gRPC 客户端的连接,并使用 gRPC 的 RecvMsg 方法,接收客户端的消息请求 ;
  4. Proxy 将接收到的 gRPC 客户端消息请求,通过 SendHeader 和 SendMsg 方法发送给 gRPC 服务端 ;
  5. 同样的方法,RecvMsg 接收 gRPC 服务端的响应消息,使用 SendMsg 发送给 gRPC 客户端。

至此 gRPC 代理服务就完成了消息的转发功能,限流,权限等功能可以通过转发的功能进行拦截处理 ;
如图所示
gRPC Proxy:


grpc-proxy.png

gRPC Proxy 流程图:


grpc-proxy-2.png

均衡策略

目前支持 gRPC 均衡策略是:

  1. 加权随机 ;
  2. 最小连接数 ;

配置说明

proxy:
  setting:
    LISTEN_PROXY_ADDR: '0.0.0.0'
  proxy_list: 
    - PROXY_NAME: 'default'
      ENABLED: true
      POOL_ENABLED: true
      DIAL_TIMEOUT: 5             # second
      BACKOFF_MAX_DELAY: 3        # second
      KEEPALIVE_TIME: 5           # second
      KEEPALIVE_TIMEOUT: 10       # second
      REQUEST_IDLE_TIME: 10       # second
      REQUEST_MAX_LIFE: 60        # second
      REQUEST_TIMEOUT: 3          # second
      POOL_MODEL: 1               # default 0 : STRICT_MODE, 1: LOOSE_MODE
      PROXY_MODEL: 'randomWeight'       # minConn or randomWeight
      GRPC_REQUEST_REUSABLE: true # 连接是否复用
      DEFAULT_GRPC_CONN_NUM: 10   # 默认创建的连接数
      PROXY_PORT: '30880'
      GRPC_PROXY_ENDPOINTS:       # 负载的 endpoints 列表, "#" 号后面是权重
        - 172.18.160.84:30880#10
        - 172.18.160.84:30880#10

支持多个端口负载多个 endpoint 列表

gRPC 网关 - synapsor

拉取代码后即可运行

运行

配置好 proxy endpoints 后,执行下面命令
docker

docker-compose up -d

k8s

kubectl apply -f deployments/kubernetes/

FAQ

Q: received prior goaway: code: ENHANCE_YOUR_CALM, debug data: “too_many_pings”
A: grpc client 的keepalive 用来检测 client 创建的grpc channel 连接是不是可用的,如果超时,就会关掉这个channel 的连接 ;grpc server 的keepalive 用来检测 server 创建的grpc channel 连接是不是可用的,如果超时,就会关掉这个channel 的连接 ;在这里还需要特别注意一个问题, grpc client 的keepalive 的 时间设定 需要在server 允许范围内,否则,server 会发送一个GOAWAY 消息,把和client 的连接强制关掉 。

Q: code = Cancelled desc = Cancelled on the server side
A: 客户端建立连接后,超过一定时间没有发送数据 (包括 ping 数据) 会被 server 端主动断开连接 ;

上一篇下一篇

猜你喜欢

热点阅读