【问题标题】:gRPC Load BalancinggRPC 负载均衡
【发布时间】:2017-09-30 21:58:42
【问题描述】:

我已经阅读了https://github.com/grpc/grpc/blob/master/doc/load-balancing.md 的负载平衡页面,但仍然对后端 GRPC 实例之间的负载平衡的正确方法感到困惑。我们正在部署多个 gRPC“微服务”实例,并希望我们的其他 gRPC 客户端能够在它们之间进行路由。我们将这些部署为 Kubernetes(实际上是 Google Container Engine)中的 pod。

谁能解释在 gRPC 服务器之间负载平衡 gRPC 客户端请求的“推荐”方法?客户似乎需要了解端点——难道不能利用 Container Engine 中内置的 LoadBalancer 来提供帮助吗?

【问题讨论】:

    标签: kubernetes google-kubernetes-engine grpc grpc-java


    【解决方案1】:

    您可能想查看nghttpxnghttpx Ingress controller 项目。这些项目使得为 HTTP/2 流执行 L7 负载平衡成为可能。

    还可以查看https://cloud.google.com/endpoints/docs/architecture-overview,了解有关捆绑在 Google Cloud Platform 中的端点管理的一些信息。

    【讨论】:

      【解决方案2】:

      我不能说kubernetes,但是关于gRPC负载均衡,基本上有两种做法:

      1. 对于简单的用例,您可以在为给定名称返回的地址列表(即为 service.foo.com 返回的 IP 列表)上启用循环。执行此操作的方法取决于语言。对于 C++,您可以使用带有“round_robin”作为参数的grpc::ChannelArguments::SetLoadBalancingPolicyName(将来也可以通过“service configuration”进行选择,但是如何在 DNS 记录中对该配置进行编码的设计还没有)尚未最终确定)。
      2. 使用 grpclb 协议。这适用于更复杂的部署。此功能需要c-ares DNS resolver#11237 引入(此 PR 非常接近合并)。这是使 grpclb 在开源中工作所缺少的部分。特别是:
        • 看看this document。它检查了控制哪些地址被标记为平衡器所需的 DNS 配置更改。它目前是一个“提案”,很快就会被提升为文档。可以相当权威地采用它,这就是 #11237 正在实施的平衡器发现。
        • 编写实现the load balancer protocol 的常规gRPC 服务器(使用任何语言)。这是要在您的 DNS 记录中标记为平衡器的服务器(如 the aforementioned document 中所述),客户端的 grpclb 将与之通信以获取后端地址列表(称为 server_lists)。您可以根据需要将该平衡器内部的逻辑设置为简单或复杂。
        • 客户端在创建通道时将使用 balancer 的 DNS 名称。另请注意,您的平衡器 DNS 名称可能指向多个地址。如果其中一个或多个被标记为平衡器,则将使用 grpclb。如果有多个平衡器,将拾取哪个平衡器?客户端连接的第一个。

      如果您有任何问题,请告诉我。

      【讨论】:

      • 使用Python时round_robin如何设置?
      • 尼尔,试试channel = grpc.insecure_channel("my.grpc.server.com", ("grpc.lb_policy_name", "round_robin"))
      【解决方案3】:

      对于 grpc 服务器之间的负载平衡,kubernates 默认负载平衡不会有帮助,因为它是 L4 负载平衡器。 您将需要 L7 负载均衡器。

      为什么是 L7?

      grpc 使用 http2,其中连接是持久的,请求将通过同一连接发送。 L4 负载平衡器将使用 tcp 连接进行负载平衡,但是您需要在请求级别进行负载平衡,因此我们需要 L7 负载平衡器。尤其是在 grpc 服务器之间进行通信时。

      有几个选项,您可以为此使用Linkered/Envoy,它们可以很好地与 kubernates 配合使用,并且还提供了良好的服务网格。

      要将您的服务公开给外部工作,您可以使用 nghttpx 和 nghttpx Ingress 控制器。

      您也可以使用客户端负载平衡,但我认为这没有什么好处。

      【讨论】:

        【解决方案4】:

        如果在 AWS/ECS 中,https://aws.amazon.com/blogs/aws/new-network-load-balancer-effortless-scaling-to-millions-of-requests-per-second/ 将用于在您的目标组之间循环连接。

        您确实需要做一些事情来监听 NLB 只能在 HTTP1 中执行的运行状况检查。您还可以终止自己的 SSL。

        【讨论】:

          【解决方案5】:

          正如萨马伦德拉所说的

          您可以查看Envoy,原产于 Lyft。

          它对传入和传出连接的 HTTP/2 和 gRPC 具有一流的支持。

          • gRPC 的 L7 负载平衡
          • 集群发现服务(例如 consul)

          我们一直在 gojek 为我们的 gRPC 服务使用 envoy,它在相当高的负载下为我们提供了良好的服务。

          【讨论】:

            【解决方案6】:

            在 Fulcrum,我们也遇到过类似的情况。

            我们还完全基于微服务架构构建了一个产品,并决定使用 gRPC 框架。然后,我们立即面临如何使用 Application Load Balancer(第 7 层)对流量进行负载平衡的问题。事实证明——AWS 还不支持 HTTP 2.0。

            我们为什么使用 Envoy

            ​​>

            正如上面的评论者所指出的,Envoy 是一个很好的选择。它是在 Lyft 开发的,非常棒。与其他替代方案相比,它非常轻量级,并且很容易整合到微服务架构中。

            基本上,我们使用标准的 Frontend Envoy 负载均衡器。此外,还有称为边车的负载均衡器。它们中的每一个都放置在每个服务实例附近。他们专门与附近的服务合作,并且彼此之间也有联系。

            因此,前端代理始终有一个连接,或者它可以在需要时创建一个。它使用“循环”模型来发送请求。

            这里是我们对 gRPC 负载平衡经验的完整描述> https://fulcrum.rocks/blog/load-balancer-grpc-aws 我们还创建了一个非常简单的服务,您可以从我们的 GitHub 下载并在您自己的机器上启动 Playground:https://github.com/fulcrum-rocks/grpc-load-balancing-playground

            这是我们配置前端代理的方式

            static_resources:
              listeners:
                - address:
                    socket_address:
                      address: 0.0.0.0
                      port_value: $LISTEN_PORT
                  filter_chains:
                    - filters:
                        - name: envoy.http_connection_manager
                          config:
                            codec_type: http2
                            stat_prefix: ingress_grpc
                            http2_protocol_options: {}
                            route_config:
                              name: service_route
                              virtual_hosts:
                                - name: service_host
                                  domains:
                                    - "*"
                                  routes:
                                    - match:
                                        prefix: "/"
                                        grpc: {}
                                      route:
                                        cluster: service_cluster
                                        timeout:
                                          seconds: 0
                                          nanos: 0
                            http_filters:
                              - name: envoy.router
                                config: {}
              clusters:
                - name: service_cluster
                  connect_timeout: 0.25s
                  type: strict_dns
                  lb_policy: round_robin
                  http2_protocol_options: {}
                  hosts:
                    - socket_address:
                        address: $SERVICE_DISCOVERY_ADDRESS
                        port_value: $SERVICE_DISCOVERY_PORT
            admin:
              access_log_path: "/dev/null"
              address:
                socket_address:
                  address: 0.0.0.0
                  port_value: 80

            【讨论】:

              猜你喜欢
              • 2017-07-29
              • 2022-01-17
              • 2021-03-18
              • 2018-10-30
              • 2020-05-26
              • 2021-12-07
              • 1970-01-01
              相关资源
              最近更新 更多