From b4227370fc8b84fdf8d11c3d1ba94492347da1a8 Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Wed, 18 Jan 2017 09:21:20 -0800 Subject: [PATCH] Code review changes and other improvements. --- doc/images/load-balancing.png | Bin 27733 -> 28073 bytes doc/images/load-balancing.svg | 2 +- doc/load-balancing.md | 67 +++++++++++++++++++++------------- doc/naming.md | 18 ++++++--- 4 files changed, 54 insertions(+), 33 deletions(-) diff --git a/doc/images/load-balancing.png b/doc/images/load-balancing.png index 18b68bfdad83d15b33f37eeeb98f582feb8ee0c0..7c70465e653dcf732875e96ab80e65331ff7c67d 100644 GIT binary patch literal 28073 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எ zovxofG6*vO=hi6X6wBzzQ)1kAT33g+Wv!i9Iv@lm476@HDZkg!OjcS>qWR1eK?#5RSML$IyG z2uyvO!4AY|XRKqWe#fzLY_1`rmC8DI#D3OY+l%QnND@|4ILAr%6Y-1vY`DRWtI2l} zx-|NHf!ClW^BQRw@MS-{%umF`h0!GNsCf`G;;7r4@psYx>Gmz-E%;x$0R;bcQ)2vw z%wGn^N2nVpW&>pZZw$59lUKiI0uwv>@N76z@n1eXVgc}%45#yCN_Ic`^4!0UOm`=F zf<9XSK=1FEk4C1g=(1t{-~SEPkN#&XG5#e3%%L5m#He*ZpzhZjy{%__qvE>DqyGYX>j7;5 literal 27733 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≶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 - + diff --git a/doc/load-balancing.md b/doc/load-balancing.md index c5e59331c2da4..1071961b1166b 100644 --- a/doc/load-balancing.md +++ b/doc/load-balancing.md @@ -1,17 +1,25 @@ Load Balancing in gRPC -======================= +====================== -# Objective +# Scope -To design a load balancing API between a gRPC client and a Load Balancer to -instruct the client how to send load to multiple backend servers. +This document explains the design for load balancing within gRPC. # Background +## Per-Call Load Balancing + +It is worth noting that load-balancing within gRPC happens on a per-call +basis, not a per-connection basis. In other words, even if all requests +come from a single client, we still want them to be load-balanced across +all servers. + +## Approaches to Load Balancing + Prior to any gRPC specifics, we explore some usual ways to approach load balancing. -## Proxy Model +### Proxy Model Using a proxy provides a solid trustable client that can report load to the load balancing system. Proxies typically require more resources to operate since they @@ -21,7 +29,7 @@ latency to the RPCs. The proxy model was deemed inefficient when considering request heavy services like storage. -## Balancing-aware Client +### Balancing-aware Client This thicker client places more of the load balancing logic in the client. For example, the client could contain many load balancing policies (Round Robin, @@ -41,7 +49,7 @@ It would also significantly complicate the client's code: the new design hides the load balancing complexity of multiple layers and presents it as a simple list of servers to the client. -## External Load Balancing Service +### External Load Balancing Service The client load balancing code is kept simple and portable, implementing well-known algorithms (e.g., Round Robin) for server selection. @@ -104,9 +112,7 @@ works: a load balancer address, and a [service config](service_config.md) that indicates which client-side load-balancing policy to use (e.g., `round_robin` or `grpclb`). -2. The client instantiates the load balancing policy, which is then - responsible for deciding which requests will be sent to which - addresses. +2. The client instantiates the load balancing policy. - Note: If all addresses returned by the resolver are balancer addresses, then the client will use the `grpclb` policy, regardless of what load-balancing policy was requested by the service config. @@ -114,19 +120,28 @@ works: by the service config. If no load-balancing policy is requested by the service config, then the client will default to a policy that picks the first available server address. -3. In the case of the `grpclb` policy, it opens a stream to one of the - balancer addresses returned by the resolver. It asks the balancer for - the server addresses to use for the server name originally requested by - the client (i.e., the same one originally passed to the name resolver). - - Note: Currently, the `grpclb` policy ignores any non-balancer - addresses returned by the resolver. However, in the future, it may - be changed to use these addresses as a fallback in case no balancers - can be contacted. -4. The gRPC servers to which the load balancer is directing the client - may report load to the load balancers, if that information is needed - by the load balancer's configuration. -5. The load balancer returns a server list to the gRPC client. If the - server list is empty, the call will block until a non-empty one is - received. -6. The gRPC client will send RPCs to the gRPC servers contained in - the server list from the Load Balancer. +3. The load balancing policy creates a subchannel to each server address. + - For all policies *except* `grpclb`, this means one subchannel for each + address returned by the resolver. Note that these policies + ignore any balancer addresses returned by the resolver. + - In the case of the `grpclb` policy, the workflow is as follows: + a. The policy opens a stream to one of the balancer addresses returned + by the resolver. It asks the balancer for the server addresses to + use for the server name originally requested by the client (i.e., + the same one originally passed to the name resolver). + - Note: The `grpclb` policy currently ignores any non-balancer + addresses returned by the resolver. However, in the future, it + may be changed to use these addresses as a fallback in case no + balancers can be contacted. + b. The gRPC servers to which the load balancer is directing the client + may report load to the load balancers, if that information is needed + by the load balancer's configuration. + c. The load balancer returns a server list to the gRPC client's `grpclb` + policy. The `grpclb` policy will then create a subchannel to each of + server in the list. +4. For each RPC sent, the load balancing policy decides which + subchannel (i.e., which server) the RPC should be sent to. + - In the case of the `grpclb` policy, the client will send requests + to the servers in the order in which they were returned by the load + balancer. If the server list is empty, the call will block until a + non-empty one is received. diff --git a/doc/naming.md b/doc/naming.md index 588f611f1633d..676aa9f298068 100644 --- a/doc/naming.md +++ b/doc/naming.md @@ -20,12 +20,18 @@ uses the syntax: scheme://authority/endpoint_name ``` -Here, `scheme` indicates the name-system to be used. Example schemes to -be supported include: +Here, `scheme` indicates the name-system to be used. Currently, we +support the following schemes: -* `dns` +- `dns` -* `etcd` +- `ipv4` (IPv4 address) + +- `ipv6` (IPv6 address) + +- `unix` (path to unix domain socket -- unix systems only) + +In the future, additional schemes such as `etcd` could be added. The `authority` indicates some scheme-specific bootstrap information, e.g., for DNS, the authority may include the IP[:port] of the DNS server to @@ -38,7 +44,7 @@ syntax of the endpoint name is dictated by the scheme in use. ### Resolver Plugins -The gRPC client library will switch on the scheme to pick the right +The gRPC client library will use the specified scheme to pick the right resolver plugin and pass it the fully qualified name string. Resolvers should be able to contact the authority and get a resolution @@ -46,7 +52,7 @@ that they return back to the gRPC client library. The returned contents include: - A list of resolved addresses, each of which has three attributes: - - The address itself, in IP:port form. + - The address itself, including both IP address and port. - A boolean indicating whether the address is a backend address (i.e., the address to use to contact the server directly) or a balancer address (for cases where [external load balancing](load-balancing.md)