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

今天给大家推荐一个 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
  • PROXY_NAME : 为 proxy 名称
  • ENABLED: 是否启用此 proxy
  • KEEPALIVE_TIME: 如果连接没有被激活,每隔多长时间发送 pings
  • KEEPALIVE_TIMEOUT: wait 1 second for ping ack before considering the connection dead
  • REQUEST_TIMEOUT: 请求超时设置
  • GRPC_REQUEST_REUSABLE: 是否复用连接
  • LISTEN_PROXY_ADDR: synapsor 本地监听 ip
  • DEFAULT_GRPC_CONN_NUM:建立连接的默认连接数 (会自动进行扩增)
  • EXPOSE_PROXY_PORT: synapsor 暴露的端口
  • GRPC_PROXY_ENDPOINTS: 负载的 endpoint 列表
  • PROXY_MODEL: 负载的模式(minConn:最小连接数,适用于流量控制,流式连接; randomWeight: 加权随机,适用于非流控场景)

支持多个端口负载多个 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 端主动断开连接 ;

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,185评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,445评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,684评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,564评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,681评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,874评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,025评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,761评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,217评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,545评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,694评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,351评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,988评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,778评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,007评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,427评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,580评论 2 349

推荐阅读更多精彩内容