Article Directory
1. What is Ribbon?
Ribbon is a load balancer released by Netflix, which helps control the behavior of HTTP and TCP clients. After configuring the service provider address for Ribbon, Ribbon can automatically help service consumers make requests based on a certain load balancing algorithm. Ribbon provides us with many load balancing algorithms by default, such as polling, random, etc. Of course, we can also implement custom load balancing algorithms for Ribbon.
In Spring Cloud, when Ribbon is used in conjunction with Nacos, Ribbon can automatically obtain a list of service provider addresses from Nacos Server, and request one of the service provider instances based on the load balancing algorithm. Shows the architecture when Ribbon is used in conjunction with Nacos.
2. Source code tracking
Why can we service
access it only by entering the name? Before getting the ip and port. Obviously someone helped us get the ip and port of the service instance based on the service name. It is LoadBalancerInterceptor
our source code tracking:
continue to follow the execute method: found that the service of port 8001 has been obtained
org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient
If you follow the next time, you will find 8002
2. Load balancing strategy
Ribbon's default load balancing strategy is simple polling, we can test it:
Write the test class. In the source code just now, we see that the interception is used RibbonLoadBalanceClient
for load balancing. One of the choose
methods is introduced like this:
Now this is the method for load balancing to obtain instances. We inject objects of this class, and then test them:
package com.bruceliu.test;
import com.bruceliu.SpringcloudDemoConsumerApplication;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient;
import org.springframework.test.context.junit4.SpringRunner;
/**
* @author bruceliu
* @create 2019-05-04 11:33
* @description 负载均衡算法测试
*/
@RunWith(SpringRunner.class)
@SpringBootTest(classes = SpringcloudDemoConsumerApplication.class)
public class LoadBalanceTest {
@Autowired
RibbonLoadBalancerClient client;
@Test
public void test1(){
for (int i = 0; i <10 ; i++) {
ServiceInstance instance = this.client.choose("SPRINGCLOUD-DEMO-SERVICE");
System.out.println(instance.getHost() + ":" + instance.getPort());
}
}
}
Operation result: It
conforms to our expected speculation, it is indeed a polling method .
Can we modify the load balancing strategy? Continue to trace the source code and find such a piece of code:
Let's see who this rule is:
The default value of the rule here is one RoundRobinRule
, see the introduction of the class:
this is the meaning of polling.
We noticed that this class actually implements the interface IRule. Check it out:
Define a rule interface for load balancing.
It has the following implementations:
SpringBoot also provides us with a configuration entry to modify the load balancing rules:
SPRINGCLOUD-DEMO-SERVICE:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
The format is:, the {服务名称}.ribbon.NFLoadBalancerRuleClassName
value is the implementation class of IRule.
Tested again and found that the result became random:
2.1 Ribbon core component IRule (interview questions)
Strategy name | The class name corresponding to the strategy | Realization principle |
---|---|---|
Polling strategy (default) | RoundRobinRule | The polling strategy means to take down a provider in order each time, for example, there are 5 providers in total, the first is the first, the second is the second, the third is the third, and so on |
Weighted polling strategy | WeightedResponseTimeRule | 1. Assign a weight according to the response time of each provider. The longer the response time and the smaller the weight, the lower the probability of being selected. 2. Principle: At the beginning, it is a polling strategy, and a timer is started. The average response time of each provider is collected every 30 seconds. When the information is sufficient, each provider is attached with a weight, and the provider is randomly selected according to the weight. A provider with a higher weight and a higher weight will be selected with a high probability. |
Random strategy | RandomRule | Randomly select a provider from the list of providers |
Minimum Concurrency Strategy | BestAvailableRule | Select the provider with the smallest number of concurrent requests being requested, unless the provider is in the fuse. |
Retry mechanism based on "selected load balancing strategy" | RetryRule | 1. The "selected load balancing strategy" strategy is the round robin rule. 2. The retry strategy first sets a threshold time period. If the provider fails to be selected within this threshold time period, it will always try to use the "selection" strategy. Set load balancing strategy: polling strategy" and finally select an available provider |
Usability Sensitive Strategy | AvailabilityFilteringRule | There are two kinds of providers with poor filtering performance: the first kind: filter out providers that have been failing to connect in eureka. The second kind: filter out providers with high concurrency. |
Regional Sensitivity Strategy | ZoneAvoidanceRule | 1. Use a region as a unit to examine the availability, discard the unavailable region, and select the available provider from the remaining regions. 2. If one or more instances in this ip area are unreachable or slow in response, the ip area will be reduced. The weight of other ips in the selected. |
2.2. Modify the algorithm for accessing the service
Method 1 : Modify the code to replace the load balancing strategy
Step 1: Create a new package that will not be scanned by the @ComponentScan component, such as: com.rules
Step 2: Create your own rule class of load balancing algorithm under this package
Step 3: Add a comment on the main startup class: @RibbonClient
package com.rules;
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import com.netflix.loadbalancer.RoundRobinRule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @BelongsProject: MicroService
* @BelongsPackage: com.rules
* @CreateTime: 2020-11-18 16:50
* @Description: TODO
*/
@Configuration
public class MyLoadBalanceRule {
/**
* @desc 自定义负载均衡规则,默认是轮询规则
* @return
*/
@Bean
public IRule myRule(){
//return new RandomRule(); // 改为随机算法规则
return new RoundRobinRule(); // 轮询
}
}
@EnableEurekaClient //开启客户端
@SpringBootApplication
@RibbonClient(name = "PRODUCT-SERVICE",configuration = MyLoadBalanceRule.class)
public class ProtalApp80 {
public static void main(String[] args) {
SpringApplication.run(ProtalApp80.class,args);
}
}
Note: This class here cannot be configured under the same level directory and subdirectories of the SpringBoot startup class, why? Because the Ribbon configuration must be marked with @Configuration annotation, and cannot be scanned by @Component annotation or @SpringBootApplication (because it contains @Component). Because if it is scanned by @ComponetScan, it will cause all RibbonClients to share this configuration.
Method 2 : Modify the configuration file to replace the load balancing strategy.
The second method is to set the assigned strategy in application.properties
springcloud-alibaba-provider:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
'springcloud-alibaba-provider' is the name of the called service, and the following components are fixed.
At the same time comment out the content in method one