基于grpc-java开发的普通工程在k8s内部署多实例,如何实现客户端流量的负载均衡

文章目录

    • [1. 前言](#1. 前言)
    • 2.实现方案要点
    • 3.具体实现步骤
      • [3.1 编写一个grpc服务端程序(详细实现步骤在此忽略,网上很多例子)](#3.1 编写一个grpc服务端程序(详细实现步骤在此忽略,网上很多例子))
      • [3.2 编写grpc客户端程序,注意指定负载均衡策略和dns:///这个URI前缀,如下图所示](#3.2 编写grpc客户端程序,注意指定负载均衡策略和dns:///这个URI前缀,如下图所示)
      • [3.3 在k8s中部署服务端和客户端](#3.3 在k8s中部署服务端和客户端)
        • [3.3.1 服务端部署2个实例](#3.3.1 服务端部署2个实例)
        • [3.3.2 通过headless服务将服务端服务暴露出来](#3.3.2 通过headless服务将服务端服务暴露出来)
      • [3.3.3 客户端部署一个实例](#3.3.3 客户端部署一个实例)
        • [3.3.4 进入客户端容器命令行进行测试](#3.3.4 进入客户端容器命令行进行测试)
        • [3.3.5 分别查看两个客户端接受到的请求流量](#3.3.5 分别查看两个客户端接受到的请求流量)

1. 前言

本文主要讨论通过grpc-java开发的普通的java grpc工程,以多实例的方式部署在容器编排平台kubernetes(以下简称k8s)上,如何能够实现让同样部署在k8s

集群内的客户端请求流量均衡的分发到多个grpc应用部署实例上去。

2.实现方案要点

  • grpc服务端程序在k8s内部署的多个实例通过headless service暴露服务
  • grpc客户端程序显示指定负载均衡策略为round_robin
  • grpc客户端程序在创建channel时显示在service名称前加上dns:///(比如 dns:///service.ns)
  • grpc-java的版本要不低于1.38

3.具体实现步骤

3.1 编写一个grpc服务端程序(详细实现步骤在此忽略,网上很多例子)

text 复制代码
  package com.example.grpcserver;
  
  import io.grpc.Server;
  import io.grpc.ServerBuilder;
  import java.io.IOException;
  public class ProductInfoServer {
  Server server;
  
      public static void main(String[] args) {
          ProductInfoServer productInfoServer = new ProductInfoServer();
          productInfoServer.startServer();
          productInfoServer.blockUntilShutdown();
      }
  
      private void startServer(){
  
          int port = 50501;
          try {
              server = ServerBuilder.forPort(port).addService(new ProductInfoImpl()).build().start();
              Runtime.getRuntime().addShutdownHook(new Thread( ()-> {
                  ProductInfoServer.this.stop();
              }));
          } catch (IOException e) {
              throw new RuntimeException(e);
          }
      }
  
      private void stop(){
          if(server != null){
              server.shutdown();
          }
      }
  
      private void blockUntilShutdown(){
          if (server != null){
              try {
                  System.out.println("begin =====server.awaitTermination();");
                  server.awaitTermination();
                  System.out.println("end =====server.awaitTermination();");
              } catch (InterruptedException e) {
                  throw new RuntimeException(e);
              }
          }
  
      }
  
  }

3.2 编写grpc客户端程序,注意指定负载均衡策略和dns:///这个URI前缀,如下图所示

部分源码:

text 复制代码
package com.example.grpccli;

import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
import org.javaboy.grpc.demo.Product;
import org.javaboy.grpc.demo.ProductId;
import org.javaboy.grpc.demo.ProductInfoGrpc;

public class ProductClient {

    public static void main(String[] args) {
        // 请注意此处是要连接的service暴露的端口
        int port = 50501;
        String serverAddr = "grpc-server-headless-srv.platform";
        String dnsAddr = "dns:///"+serverAddr+":"+port;
        System.out.println("dnsAddr: " + dnsAddr);
        ManagedChannel managedChannel = ManagedChannelBuilder.forTarget("dns:///"+serverAddr+":"+port)
                .defaultLoadBalancingPolicy("round_robin").usePlaintext().build();
        ProductInfoGrpc.ProductInfoBlockingStub stub = ProductInfoGrpc.newBlockingStub(managedChannel);

        // 循环分别创建和查询100次产品
        for(int i=0; i<100; i++){
            Product product = Product.newBuilder().setId("" + i).
                    setName("TH项目-" + i).
                    setPrice(i).
                    setDescription("grpc实战项目-" + i).
                    build();

            // 添加产品
            ProductId id = stub.addProduct(product);
            System.out.println("我是增加产品: "+ id.getValue());

            // 查询产品
            Product prd = stub.getProduct(ProductId.newBuilder().setValue("" + i).build());
            System.out.println("我是查询产品:" + prd.toString());
        }


    }

}

3.3 在k8s中部署服务端和客户端

此处直接使用Kubesphere平台进行部署

3.3.1 服务端部署2个实例
3.3.2 通过headless服务将服务端服务暴露出来

3.3.3 客户端部署一个实例

注意客户端代码此处URI配置为(dns:///service:port)

3.3.4 进入客户端容器命令行进行测试
3.3.5 分别查看两个客户端接受到的请求流量

服务端实例1和服务端实例2各接收到客户端50%的请求流量


相关推荐
东风微鸣22 分钟前
K8s 最佳实践已更新:请使用 Node Swap!
kubernetes
不得了zz27 分钟前
04-Spring AI Alibaba ReactAgent 生产级实践:工具调用、结构化输出、HITL 与上下文管理
java·ai编程·springaialibaba
猿究院_夏燊38 分钟前
SpringMVC 到底是怎么干活的?
java·网络·职场和发展
鶴哥只手遮天39 分钟前
Spring Framework 7.0.9 深度剖析-05-配置元数据解析:XML、注解与 JavaConfig
java·后端·开源
NGINX开源社区1 小时前
与我们交流:NGINX Gateway Fabric 与 NGINX Ingress Controller 社区会议
java·服务器·前端
鶴哥只手遮天1 小时前
Spring Framework 7.0.9 深度剖析-16-异步与调度
java·后端·开源
十年Java程序媛1 小时前
Java 多线程基础与锁机制|进程线程、synchronized、volatile、Lock 面试全梳理
java·spring boot·面试
弈栈录1 小时前
大模型服务抽象:兼容 OpenAI、通义千问与本地模型
java·后端·架构
鶴哥只手遮天1 小时前
Spring Framework 7.0.9 深度剖析-06-Bean 生命周期与依赖注入原理
java·后端·开源
唐钰小宝B1 小时前
深度解读 JDK 8、JDK 11、JDK 17 和 JDK 21 的区别
java·开发语言·windows