Docker Swarm - gRPC 基于 DNS 的負載均衡

? 背景

后端兩個服務 ServiceA、ServiceB,ServiceA 通過 gRPC 遠程調用 ServiceB。在 Docker Swarm 集群下每個服務部署多個副本,假設部署兩個副本,即 ServiceA 的實例為 A1 和 A2,ServiceB 的實例為 B1 和 B2。Swarm 集群內部通過 Overlay 網絡實現容器間通信,ServiceA 訪問 ServiceB 通過服務名稱來連接,即 A1 調用 ServiceB 時,會隨機調用到 B1 或者 B2;同理,A2 也是如此。

上述流程,看似合理且正常,然而實際效果是:假設 A1 連通 B1,A2 連通 B1,那么 ServiceA 的請求會一直被 B1 接收并處理,直至 TCP 連接超時,或者 B1 服務終止。gRPC 的核心概念中有 Channel ,描述 Client 與 Server 之間的連接,即 A1 與 B1 建立連接之后, Channel 會被復用。

面對這種負載不均衡的場景,我們希望 ServiceA 的每個請求能被均衡到 ServiceB 的每個實例去處理。

? GRPC 負載均衡

官方資料 Load Balancing in gRPC

工作流程

  • 1、Client 請求解析 server name,獲取一個或多個實際 IP 地址,例如 ServiceB 解析為 10.0.0.10、10.0.0.11
  • 2、Client 實例化負載均衡策略,可選策略為 round_robingrpclb。注意:如果解析程序返回的地址是均衡器地址,無論 Client 配置什么負載均衡策略,都將使用 grpclb 策略。否則,會使用 Client 配置的負載均衡策略。如果未配置,則 Client 將默認選用第一個可用服務器地址的策略
  • 3、負載均衡衡策略為每個服務器地址創建一個子通道
  • 4、對于每個 RPC 請求,負載均衡策略決定應將 RPC 請求發送到哪個子通道(即哪個服務器)

針對上述場景,在 Swarm 集群中,我們應該選擇 dnsrr 模式,并且 gRPC 客戶端配置負載均衡策略為 round_robin(輪訓)即可。

? 配置 Load Balance Policy

不同語言配置方式不同,以下列舉常用語言:

grpc-java 配置

ManagedChannel channel = ManagedChannelBuilder.forAddress(server.getHost(), server.getPort())
                                              .defaultLoadBalancingPolicy("round_robin")
                                              .usePlaintext().build();

其他語言

有待完善。。。

配置 Docker Swarm dnsrr

Docker Swarm 默認的模式是 vip,使用 dnsrr 只需將 endpoint_mode 設置為 dnsrr 即可,相關資料:

示例:

version: '3.7'
services:
  server:
    image: "server:latest"
    stop_grace_period: 20s
    networks:
      - idp_network
    deploy:
      replicas: 2
      endpoint_mode: dnsrr
networks:
  idp_network:
    external: true

Spring Boot gRPC Load Balance 案例

1、獲取案例源碼

git clone https://github.com/ChinaSilence/spring-boot-starter-grpc.git

2、Install 相關包

3、構建相關鏡像

4、初始化 Swarm 集群

docker swarm init

5、添加 Overlay 網絡

docker network create -d overlay --attachable idp_network

6、部署 gRPC server 和 client

docker stack deploy -c stack.yml grpc

stack.yml 文件所在路徑下執行

7、查看 server 端日志

docker service logs -f grpc_server

8、持續通過 client 發送請求,并觀察日志信息

curl http://localhost:8081/v1/user/list
日志輸出

從日志中可以看出,server 能均衡處理 client 的請求。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容