I. Ribbon load balancing principle
The underlying SpringCloud actually utilizes a component called Ribbon to implement load balancing functionality.
The underlying SpringCloudRibbon uses an interceptor that intercepts requests sent by RestTemplate to make changes to the address. The following figure:
The basic process is as follows:
- Intercept our RestTemplate request http://userservice/user/1
- RibbonLoadBalancerClient will get the service name from the request url, which is user-service
- DynamicServerListLoadBalancer pulls list of services from eureka based on user-service
- eureka return list, localhost:8081, localhost:8082
- IRule utilizes the built-in load balancing rules and selects one from the list, e.g. localhost:8081
- RibbonLoadBalancerClient modifies the request address, replaces userservice with localhost:8081, gets http://localhost:8081/user/1, and launches the real request
--Source Trace Analysis
You can see here that the intercept method, which intercepts the user's HttpRequest request, then does a couple of things:
`()`: get the request uri, in this case http://user-service/user/8
`()`: get the hostname of the uri path, which is actually the service id, `user-service`
`()`: handles service ids, and user requests.
The `` here is of type `LoadBalancerClient`.
Continue to follow the execute method:
The code looks like this:
- getLoadBalancer(serviceId): get ILoadBalancer based on the service id, and ILoadBalancer will take the service id and go to eureka to get the list of services and save it.
- getServer(loadBalancer): selects a service from the list of services using the built-in load balancing algorithm. In this example, you can see that the service on port 8082 is obtained
After releasing it, I visited and traced it again and found that it was fetching 8081: sure enough, load balancing was achieved.
3. Load balancing policy IRule
In the code just shown, you can see that getting the service enables load balancing via a `getServer` method:.
Ribbon load balancing strategy
The irule interface determines the load balancing policy, what are the implementations of the irule interface implementation and how to modify the implementation?
Load Balancing Policy
The rules for load balancing are defined in the IRule interface, which has many different implementation classes: as follows:
The meaning of the different rules is as follows:
Built-in Load Balancing Rule Class : Rule Description
: Simply poll the list of services to select a server. It is the default load balancing rule for Ribbon.
: Ignore the following two servers: (1) By default, if this server fails to connect 3 times, the server will be set to "short-circuit" status. The short-circuit state lasts for 30 seconds, and if the connection fails again, the duration of the short-circuit increases geometrically. (2) Servers with too many concurrent connections. If the number of concurrent connections of a server is too high, clients configured with the AvailabilityFilteringRule rule will also ignore it. The upper limit of concurrent connections can be set by the client's <clientName>. <clientConfigNameSpace>.ActiveConnectionsLimit property.
: A weight value is assigned to each server. The longer the response time of a server, the smaller the weight of that server. This rule randomizes the selection of servers, and this weight value affects the selection of servers.
4.-- ZoneAvoidanceRule --: The selection of servers is based on the servers available in the zone. The servers are categorized using a Zone, which can be interpreted as a server room, a rack, and so on. And then multiple services within the Zone are polled.
: Ignore servers that are short-circuiting and choose servers with lower concurrency counts.
: Randomly select an available server.
: Selection logic for the retry mechanism
The default implementation is ZoneAvoidanceRule, a polling scheme
III. Modifying load balancing policies
Custom load balancing policies:
The load balancing rules can be modified by defining an IRule implementation in two ways:
1. Code way: in the order-service in the OrderApplication class, define a new IRule: (global configuration )
In the OrderApplication class in order-service, define a new IRule:
@Bean public IRule randomRule(){ return new RandomRule(); }
2. Configuration file method: in the file of order-service, add a new configuration can also modify the rules: (for a particular microservice configuration)
The rules can also be modified by adding new configurations in the order-service's file:
userservice: # Configure load balancing rules for a microservice, in this case the userservice service
ribbon: # Configure a load balancing rule for a microservice.
NFLoadBalancerRuleClassName: # Load balancing rule.
Note: The default load balancing rules are generally used without modification.
IV. Lazy loading and starvation loading
Ribbon uses lazy loading by default, i.e., it will create LoadBalanceClient only on the first visit, and the request time will be very long.
Instead, starvation loading will be created at project startup to reduce the time consuming first visit, enable starvation loading by configuring it below:
ribbon:
eager-load:
enabled: true
clients: userservice