1. The background
Today we’ll learn about SpringCloud’s client-side load balancing Ribbon
We continue to use the previous Eureka-Server as the service registry today
The following versions use Springboot and SpringCloud
- Springboot version: 2.3.5-release
- Springcloud version: Hoxton SR9
2. What is the Ribbon
The Ribbon is an open source client load balancer released by Netflix. It is an important part of SpringCloud-Netflix that connects Netflix’s mid-tier services together. The Ribbon client component provides a comprehensive set of configuration options, such as connection timeout and retry. Simply put, if the Ribbon lists all the services behind Load Balancer in the configuration file, the Ribbon will automatically connect these services based on certain rules (e.g. simple polling, random linking, etc.). You can easily implement custom Load balancing algorithms.
What are server side load balancing and client side load balancing
Server load balancing:
For example, Nginx/H5 carries out load balancing through Nginx. It sends requests first, and then selects one to access from multiple servers through load balancing algorithm. That is, load balancing algorithm is allocated on the server
Client load balancing:
For example, the Ribbon in Spring Cloud has a server address list on the client side. Before sending a request, a server is selected by load balancing algorithm and then accessed. This is client load balancing. That is, load balancing algorithm is allocated on the client.
3. The role of the Ribbon
The Ribbon is a key function point for load balancing access services on the client side
- 1 Service discovery Discover the list of dependent services
- 2 Service Selection Rules How to select a valid service among multiple services
- 3 Service monitoring Detect invalid services and eliminate invalid services efficiently
4. Springcloud Integrated Ribbon (RestTemplate+Ribbon)
Projects are divided into producers and consumers
Consumers are divided into three steps
Add dependencies inside the ribbon dependencies
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
Copy the code
Add annotations @ EnableDiscoveryClient
Add the configuration
@Configuration
public class Config {
@LoadBalanced
@Bean
public RestTemplate restTemplate(a){
return newRestTemplate(); }}Copy the code
Production is divided into 3 steps > Add dependencies which contain the ribbon dependencies
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
Copy the code
Add annotations @ EnableDiscoveryClient
Add the configuration
4.2 Service Code
consumers
@Data
public class User {
private String id;
private String name;
private int age;
private int port;
@Override
public String toString(a) {
return "User{" +
"id='" + id + '\' ' +
", name='" + name + '\' ' +
", age=" + age +
", port=" + port +
'} '; }}@RequestMapping("/api/comsumer/user")
@RestController
public class UserController {
@Autowired
RestTemplate restTemplate;
@GetMapping("/{id}")
public String selectUser(@PathVariable("id") String id){
ResponseEntity<String> responseEntity = restTemplate.getForEntity("http://ms-ribbon-producer/api/user/{id}",String.class,id);
returnresponseEntity.getBody(); }}Copy the code
producers
@RequestMapping("/api/user")
@RestController
public class UserController {
@Value("${server.port}")
Integer port;
@GetMapping("/{id}")
public String selectUser(@PathVariable("id") String id){
User user = new User();
user.setId(id);
user.setName("wangyunqi");
user.setPort(port);
returnuser.toString(); }}Copy the code
validation
- Producer: 8002,8003 port
- Customer: Port 8001
Using the consumer 8001 interface, it is found that the returned data is 8002,8003. Training in rotation mode
5.Ribbon load balancing algorithm
- 1RoundRobinRule default polling rule
- 2RandomRule Gets a service at random
- 3AvailabilityFilteringRule
This load balancer rule filters out the services that are tripping due to multiple access failures and the number of concurrent connections exceeds the threshold and then accesses the rest of the service list according to a polling policy
- 4 weightedresponsetimerule calculated according to the weight of all the services the average response time for the faster response time service is larger, the higher the probability of the selected weights. If the statistics are insufficient, the WeightedResponseTimeRule switches to the WeightedResponseTimeRule using RoundRobinRule.
- 5RetryRule Obtains the service based on the RoundRobinRule policy. If the service fails to be obtained, the system tries again to obtain available services within a specified period
- The load balancer first filters out services that are in the circuit breaker trip state due to multiple access failures and then selects the service with the least concurrency
- 7ZoneAvoidanceRule default rule selects a Server based on the performance of the zone where the Server is located and the availability of the Server
6 How do I modify the default load balancing algorithm
@Configuration
public class Config {
// Change the mode to random
@Bean
public IRule rule(a){
return newRandomRule(); }}Copy the code
6 How can I customize the load balancing algorithm
- Inheritance AbstractLoadBalancerRule
- Override the choose method
Public class CustomRandomRule extends AbstractLoadBalancerRule {Random rand; public CustomRandomRule() { rand = new Random(); } private int currentIndex = 0; private List<Server> currentChooseList = new ArrayList<Server>(); /** * Randomly choose from all living servers */ public Server choose(ILoadBalancer lb, Object key) { if (lb == null) { return null; } Server server = null; while (server == null) { if (Thread.interrupted()) { return null; } List<Server> upList = lb.getReachableServers(); List<Server> allList = lb.getAllServers(); int serverCount = allList.size(); if (serverCount == 0) { return null; } // select a random index int index = rand. NextInt (serverCount); / / the current poll less than or equal to 5 times the if (currentIndex < 5) {/ / save the currently selected list service IP if (currentChooseList. IsEmpty ()) { currentChooseList.add(upList.get(index)); } // The current ++ currentIndex+; // Return currentChooselist.get (0); }else { currentChooseList.clear(); currentChooseList.add(0,upList.get(index)); currentIndex=0; } if (server == null) { Thread.yield(); continue; } if (server.isAlive()) { return (server); } server = null; Thread.yield(); } return server; } @Override public Server choose(Object key) { return choose(getLoadBalancer(), key); } @Override public void initWithNiwsConfig(IClientConfig clientConfig) { // TODO Auto-generated method stub } }Copy the code