开发者社区> 问答> 正文

如何使用 ASM 为网格内 gRPC 服务实现负载均衡?

如何使用 ASM 为网格内 gRPC 服务实现负载均衡?

展开
收起
小天使爱美 2020-03-20 20:16:17 917 0
1 条回答
写回答
取消 提交回答
  • 在使用 gRPC(基于 HTTP/2)的 Kubernetes 服务时,到目标的单个连接将在一个 Pod 处终止。如果从客户端发送了多条消息,则所有消息将由该 Pod 处理,从而导致负载不均衡。本文通过示例介绍 gRPC 服务间负载不均衡的问题以及如何实现负载均衡。

    背景信息 gRPC是一种基于 HTTP/2 的服务通信协议,使用基于 Protocol Buffers(简称为 PB)格式的服务定义。服务之间调用的数据可以被序列化为较小的二进制格式进行传输。使用 gRPC,可以从 .proto 文件生成多种语言的代码,这也就使得 gRPC 成为了多语言微服务开发的最佳选择之一。

    使用基于 HTTP/1.1 的 RPC 时,一个简单的 TCP 负载平衡器足以胜任,因为这些连接都是短暂的,客户端将尝试重新连接,不会保持与运行中的旧 Pod 之间的连接。但是使用基于 HTTP/2 的 gRPC 时,TCP 连接保持打开状态,这样将保持连接到即将失效的 Pod,亦或使集群失去平衡。

    gRPC 服务间调用的负载不均衡 通过一个示例了解下 Kubernetes 下的 gRPC 服务间调用的负载不均衡问题。

    前提条件 已创建至少一个 Kubernetes 集群。 已设置通过 kubectl 连接该集群,详情参见通过kubectl连接Kubernetes集群。 登录容器服务控制台,在左侧导航栏选择集群 > 命名空间。 在命名空间页面,从集群下拉列表中选择对应的集群。 单击右上方的创建,在创建命名空间窗口,输入命名空间的名称,例如grpc-nosidecar,单击确定。 在命名空间 grpc-nosidecar 下部署 gRPC 服务的服务端 istio-grpc-server。 假设,待创建的描述文件为 istio-grpc-server.yaml,请执行如下命令: kubectl apply -n grpc-nosidecar -f istio-grpc-server.yaml 其中,istio-grpc-server.yaml 文件的内容如下: apiVersion: apps/v1 kind: Deployment metadata: name: istio-grpc-server-v1 labels: app: istio-grpc-server version: v1 spec: replicas: 1 selector: matchLabels: app: istio-grpc-server version: v1 template: metadata: labels: app: istio-grpc-server version: v1 spec: containers: - args: - --address=0.0.0.0:8080 image: registry.cn-hangzhou.aliyuncs.com/aliacs-app-catalog/istio-grpc-server imagePullPolicy: Always livenessProbe: exec: command: - /bin/grpc_health_probe - -addr=:8080 initialDelaySeconds: 2 name: istio-grpc-server ports: - containerPort: 8080 readinessProbe: exec: command: - /bin/grpc_health_probe - -addr=:8080 initialDelaySeconds: 2

    apiVersion: apps/v1 kind: Deployment metadata: name: istio-grpc-server-v2 labels: app: istio-grpc-server version: v2 spec: replicas: 1 selector: matchLabels: app: istio-grpc-server version: v2 template: metadata: labels: app: istio-grpc-server version: v2 spec: containers: - args: - --address=0.0.0.0:8080 image: registry.cn-hangzhou.aliyuncs.com/aliacs-app-catalog/istio-grpc-server imagePullPolicy: Always livenessProbe: exec: command: - /bin/grpc_health_probe - -addr=:8080 initialDelaySeconds: 2 name: istio-grpc-server ports: - containerPort: 8080 readinessProbe: exec: command: - /bin/grpc_health_probe - -addr=:8080 initialDelaySeconds: 2

    apiVersion: v1 kind: Service metadata: name: istio-grpc-server labels: app: istio-grpc-server spec: ports: - name: grpc-backend port: 8080 protocol: TCP selector: app: istio-grpc-server type: ClusterIP

    在命名空间 grpc-nosidecar 下部署 gRPC 服务的服务端 istio-grpc-client。 假设,待创建的描述文件为 istio-grpc-client.yaml,请执行如下命令: kubectl apply -n grpc-nosidecar -f istio-grpc-client.yaml 其中,istio-grpc-client.yaml 文件的内容如下: apiVersion: apps/v1 kind: Deployment metadata: name: istio-grpc-client labels: app: istio-grpc-client spec: replicas: 1 selector: matchLabels: app: istio-grpc-client template: metadata: labels: app: istio-grpc-client spec: containers: - image: registry.cn-hangzhou.aliyuncs.com/aliacs-app-catalog/istio-grpc-client imagePullPolicy: Always command: ["/bin/sleep", "3650d"] name: istio-grpc-client

    apiVersion: v1 kind: Service metadata: name: istio-grpc-client spec: ports: - name: grpc port: 8080 protocol: TCP selector: app: istio-grpc-client type: ClusterIP

    执行以下命令,查看 Pod 运行状态: kubectl get pod -n grpc-nosidecar 示例输出如下: NAME READY STATUS RESTARTS AGE istio-grpc-client-dd56bcb45-hvmjt 1/1 Running 0 95m istio-grpc-server-v1-546d9876c4-j2p9r 1/1 Running 0 95m istio-grpc-server-v2-66d9b8847-276bd 1/1 Running 0 95m 执行以下命令,登录到客户端 Pod 容器。 kubectl exec -it -n grpc-nosidecar istio-grpc-client-dd56bcb45-hvmjt sh 进入容器后,执行以下命令: /bin/greeter-client --insecure=true --address=istio-grpc-server:8080 --repeat=100 可以看到所有的请求都指向了一个 Pod: 2020/01/14 14:37:14 Hello world from istio-grpc-server-v2-66d9b8847-276bd 2020/01/14 14:37:14 Hello world from istio-grpc-server-v2-66d9b8847-276bd 2020/01/14 14:37:14 Hello world from istio-grpc-server-v2-66d9b8847-276bd 2020/01/14 14:37:14 Hello world from istio-grpc-server-v2-66d9b8847-276bd 2020/01/14 14:37:14 Hello world from istio-grpc-server-v2-66d9b8847-276bd 2020/01/14 14:37:14 Hello world from istio-grpc-server-v2-66d9b8847-276bd 2020/01/14 14:37:14 Hello world from istio-grpc-server-v2-66d9b8847-276bd 2020/01/14 14:37:14 Hello world from istio-grpc-server-v2-66d9b8847-276bd 2020/01/14 14:37:14 Hello world from istio-grpc-server-v2-66d9b8847-276bd 2020/01/14 14:37:14 Hello world from istio-grpc-server-v2-66d9b8847-276bd 2020/01/14 14:37:14 Hello world from istio-grpc-server-v2-66d9b8847-276bd 由此可见,从客户端发送了所有消息都由一个 Pod 处理,从而导致负载不均衡。 使用 ASM 实现负载均衡 下面将示例说明如何通过 ASM 实现负载均衡。

    前提条件 已创建至少一个服务网格 ASM 实例,并已经添加至少一个集群到该实例中。 已设置通过 kubectl 连接到该集群,详情参见通过kubectl连接Kubernetes集群。 登录容器服务控制台,在左侧导航栏选择集群 > 命名空间。 在命名空间页面,从集群下拉列表中选择对应的集群。 单击右上方的创建,在创建命名空间窗口,输入命名空间的名称,例如grpc-nosidecar,并新增标签istio-injection:enabled,单击确定。 命名空间 grpc-nosidecar 下部署 gRPC 服务的服务端 istio-grpc-server。 假设,待创建的描述文件为 istio-grpc-server.yaml,请执行如下命令: kubectl apply -n grpc-nosidecar -f istio-grpc-server.yaml istio-grpc-server.yaml 文件的内容,参见上文示例。 命名空间 grpc-nosidecar 下部署 gRPC 服务的服务端 istio-grpc-client。 假设,待创建的描述文件为 istio-grpc-client.yaml,请执行如下命令: kubectl apply -n grpc-nosidecar -f istio-grpc-client.yaml istio-grpc-client.yaml 文件的内容,参见上文示例。 执行以下命令,查看 Pod 运行状态: kubectl get pod -n grpc-nosidecar 此时可以看到每个 Pod 中包含了 2 个容器,其中一个容器就是注入的 Sidecar代理,示例输出如下: NAME READY STATUS RESTARTS AGE istio-grpc-client-dd56bcb45-zhfsg 2/2 Running 0 1h15m istio-grpc-server-v1-546d9876c4-tndsm 2/2 Running 0 1h15m istio-grpc-server-v2-66d9b8847-99v62 2/2 Running 0 1h15m 执行以下命令,登录到客户端 Pod 容器。 kubectl exec -it -n grpc-sidecar istio-grpc-client-dd56bcb45-zhfsg sh 进入容器后,执行以下命令: /bin/greeter-client --insecure=true --address=istio-grpc-server:8080 --repeat=100 可以看到所有的请求分别指向了对应的 2 个 Pod,比例接近于50:50,即负载均衡中的 Round-Robin。 2020/01/14 14:37:14 Hello world from istio-grpc-server-v2-66d9b8847-276bd 2020/01/14 14:37:14 Hello world from istio-grpc-server-v2-66d9b8847-276bd 2020/01/14 14:37:14 Hello world from istio-grpc-server-v2-66d9b8847-276bd 2020/01/14 14:37:14 Hello world from istio-grpc-server-v2-66d9b8847-276bd 2020/01/14 14:37:14 Hello world from istio-grpc-server-v2-66d9b8847-276bd 2020/01/14 14:37:14 Hello world from istio-grpc-server-v2-66d9b8847-276bd 2020/01/14 14:37:14 Hello world from istio-grpc-server-v2-66d9b8847-276bd 2020/01/14 14:37:14 Hello world from istio-grpc-server-v2-66d9b8847-276bd 2020/01/14 14:37:14 Hello world from istio-grpc-server-v2-66d9b8847-276bd 2020/01/14 14:37:14 Hello world from istio-grpc-server-v2-66d9b8847-276bd 2020/01/14 14:37:14 Hello world from istio-grpc-server-v2-66d9b8847-276bd 配置服务网格 ASM 实例的控制平面。 登录 ASM 控制台,进入待配置 服务网格的详情页。 在控制平面区域,选择命名空间页签,创建名为 grpc-sidecar 的命名空间。 选择目标规则页签,在 grpc-sidecar 命名空间下新建目标规则。YAML 文件内容如下: apiVersion: networking.istio.io/v1alpha3 kind: DestinationRule metadata: name: dr-istio-grpc-server spec: host: istio-grpc-server trafficPolicy: loadBalancer: simple: ROUND_ROBIN subsets: - name: v1 labels: version: "v1" - name: v2 labels: version: "v2" 选择虚拟服务页签,在 grpc-sidecar 命名空间下新建虚拟服务。YAML 文件内容如下: apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: vs-istio-grpc-server spec: hosts: - "istio-grpc-server" http: - match: - port: 8080 route: - destination: host: istio-grpc-server subset: v1 weight: 90 - destination: host: istio-grpc-server subset: v2 weight: 10 执行以下命令,登录到客户端 Pod 容器。 kubectl exec -it -n grpc-sidecar istio-grpc-client-dd56bcb45-zhfsg sh 进入容器后,执行以下命令: /bin/greeter-client --insecure=true --address=istio-grpc-server:8080 --repeat=100 可以看到所有的请求分别指向了对应的 2 个 Pod,但比例接近于90:10,并非默认的 Round-Robin。

    选择虚拟服务页签,找到 grpc-sidecar 命名空间下名为 vs-istio-grpc-server 的虚拟服务,单击 YAML,调整虚拟服务的权重,以查看调用的不同结果。 修改内容如下: route: - destination: host: istio-grpc-server subset: v1 weight: 0 - destination: host: istio-grpc-server subset: v2 weight: 100 通过 Kubectl 登录容器,执行以下命令: /bin/greeter-client --insecure=true --address=istio-grpc-server:8080 --repeat=100 可以看到所有的请求分别指向了对应的 1 个 Pod,即版本 v2 对应的 Pod。

    2020-03-20 20:17:15
    赞同 展开评论 打赏
问答排行榜
最热
最新

相关电子书

更多
《应用型负载均衡ALB产品解读》 立即下载
阿里云网络-SLB负载均衡产品介绍 立即下载
负载均衡SLB热点问题解答 立即下载