Go‑Zero Load Balancing Explained: Stateless vs Stateful Algorithms and gRPC Integration
This article explores the fundamentals of load balancing in microservice architectures, detailing both stateless and stateful strategies such as round‑robin, random, hash, and weighted algorithms, and demonstrates how go‑zero and gRPC implement these mechanisms through custom balancers, service discovery, and request scheduling.
1. What is Load Balancing
In microservice and distributed cluster contexts, load balancing ensures high availability by distributing traffic across multiple service instances.
For example, a user service may be deployed on two machines; logging the request configuration helps verify which instance handles the request.
/apps/user/rpc/logic/loginlogic.go
During startup, modify the configuration file /rpc/etc/local/user.yaml to specify the two services.
When the API is called, go‑zero selects one of the two services, demonstrating load balancing.
Load balancing distributes traffic evenly across multiple services.
2. Load Balancing Implementation Methods
Load balancing can be classified into stateless and stateful approaches; the state refers to server conditions such as busy, stopped, or idle.
Stateless Load Balancing
Most projects adopt this method, where the balancer does not consider server health but distributes requests based on an algorithm.
Round‑Robin
A simple algorithm that assigns requests sequentially to each server, looping back after the last one.
Advantages: simple implementation, fair distribution, suitable when servers have similar performance.
Disadvantages: cannot adjust dynamically based on server load, may cause overload on some servers.
Random
Selects a server randomly from the pool for each request.
Advantages: simple, fair, works when servers have comparable capacity.
Disadvantages: no dynamic load awareness, possible overload.
Hash
Uses hashing (e.g., IP hash, URL hash) to map a request to a specific server.
Advantages: same request consistently reaches the same server, useful for stateful applications.
Disadvantages: adding or removing servers changes hash values, causing request redistribution.
Weight
Applies weights to servers in algorithms like round‑robin or random; a server with weight 80 receives 80% of traffic, while weight 20 receives 20%.
Advantages: can adjust distribution based on server performance and load, improving reliability.
Disadvantages: requires manual weight configuration, less flexible.
Stateful Load Balancing
Considers runtime status of service instances (e.g., CPU usage, request success count) to make routing decisions, often using information recorded by the service or returned by the server.
P2C+EWMA
go‑zero’s default algorithm selects two random nodes, evaluates their load based on weight, CPU, success count, etc., and picks the less loaded node. It also employs EWMA (exponential weighted moving average) to smooth load measurements.
Advantages: allocates requests based on real‑time service conditions.
Disadvantages: requires deeper understanding of the algorithm to implement correctly.
Note: servers can also be filtered by low load using the stateless algorithms described earlier.
3. How the Framework Loads and Uses Load Balancing
Before execution, a theoretical analysis is performed.
Method 1
Combine service discovery with a lightweight record of load information; the balancer is invoked as needed.
Each request fetches the latest service list via discovery and obtains load data for selection.
Method 2
Improves performance by asynchronously updating the service list and caching the balancer state, reducing discovery calls per request. gRPC adopts this approach.
4. Source Code Analysis
4.1 Custom Registration
In gRPC, balancers and resolvers can be registered via a Register method.
/grpc/balancer/balancer.go
go‑zero registers its balancer in go-zero/zrpc/internal/balancer/p2c/p2c.go:36 using base.baseBuilder .
/grpc/balancer/base/base.go
4.2 gRPC Loads Custom Balancer
Analysis starts from clientConn.maybeApplyDefaultServiceConfig , which creates the balancer (default is balancer/base/baseBuilder ).
/grpc/pricker_wrapper.go
The custom picker is initialized via ccBalancerWrapper.updateClientConnState .
4.3 Request Dispatch
During request dispatch, the picker’s Pick method obtains a pickResult that contains the chosen connection, invoking go‑zero’s P2C algorithm.
/go-zero/zrpc/internal/balancer/p2c/p2c.go
5. Summary
Both gRPC’s load balancing and service discovery share similar design principles, employing the decorator pattern. Core mechanisms are exposed via interfaces, allowing custom implementations to be injected and later decorated for further processing.
Overall, gRPC centers on clientConn as the core object, requiring custom mechanisms to initialize, decorate, and integrate their parameters after construction.
360 Zhihui Cloud Developer
360 Zhihui Cloud is an enterprise open service platform that aims to "aggregate data value and empower an intelligent future," leveraging 360's extensive product and technology resources to deliver platform services to customers.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.