[SpringCloud] Ribbon load balancing

Currently between Spring Cloud service calls in two ways by Rest way:

  1. feign
  2. Rest Template + Ribbon

feign way more elegant and easier to use (ribbon inside also used to do load balancing), but the second scenario we use it, because Ribbon can be customized load balancing and load balancing algorithm

1. What is

  Netflix is released open source project, the main function is to provide the client software load balancing algorithm , an intermediate layer connecting the Netflix service together. Load Balancer listed in the configuration file (referred to as LB) all the back of the machine after automatically Ribbon help you to connect the machines based on a certain rule (such as simple polling, random connection, etc.), load balancing can be achieved from the definition algorithm.

  Dubbo and SpringCloud provides both load balancing, but SpringCloud load balancing algorithm can be customized

2. LB knowledge

  LB load balancing (Load Balance), an application or service in a distributed cluster of micro frequently used, the user will be amortized over a plurality of requests to the service, so as to achieve high availability system HA (High Available), commonly used there are load balancing software NGINX, LVS, F5 hardware and so on.
LB is divided into:

  1. Centralized LB
    that is separate between consumers and service providers LB facilities (hardware such as F5, software such as nginx), the facility is responsible for the access request is forwarded to the service provider through a strategy
  2. LB process within
    the upcoming LB logical succession to the service consumer, consumer to obtain what addresses are available from the service registry, and then himself in the choice of an appropriate server from these addresses. Ribbon belong to LB in the process, it's just a class library, integrated consumer process, consumer to obtain the address of the service provider through which

3. Ribbon in LB ideas

  1. First select EurekaServer, preference in the same area less load EurekaServer
  2. Then according to user-specified policy, select an address from the list of registered EurekaServer get to the service

4. The core components IRule

IRule: Select the service you want to access a service from the list based on a specific algorithm, provides seven strategies:

  1. RoundRobinRule: poll
  2. RandomRule: Random
  3. AvailabilityFilteringRule: will first filter out the service due to multiple access fault in the circuit breaker tripped state, as well as the number of concurrent connections exceeds the threshold value of the service, then the remaining list of services accessible according to polling policy
  4. WeightedResponseTimeRule: calculation of all services based on the average response time weighting, the higher the probability that the faster service response time greater the weight selected. Just start if statistics is insufficient, the use RoundRobinRule strategy, when sufficient statistical information, will switch to WeightedResponseTimeRule,
  5. RetryRule: first get the service in accordance with RoundRobinRule strategy if the service fails to obtain retry within a specified time, access to available services
  6. BestAvailableRule: will first filter out access service due to multiple failures in the short circuit trip state, and select a minimum amount of concurrent service
  7. ZoneAvoidanceRule: Compounding server performance and availability of a region where the server selection server

You can also customize policies, procedures as follows:

  1. Bean custom return type of configuration class IRule

    @Configuration
    public class MySelfRule
    {
    	@Bean
    	public IRule myRule()
    	{
    		//return new RandomRule();// Ribbon默认是轮询,我自定义为随机
    		//return new RoundRobinRule();// Ribbon默认是轮询,我自定义为随机
    		
    		return new RandomRule_ZY();// 我自定义为每台机器5次
    	}
    }
    //----------------------自定义路由策略类---------------
    public class RandomRule_ZY extends AbstractLoadBalancerRule
    {
    // total = 0 // 当total==5以后,我们指针才能往下走,
    // index = 0 // 当前对外提供服务的服务器地址,
    // total需要重新置为零,但是已经达到过一个5次,我们的index = 1
    // 分析:我们5次,但是微服务只有8001 8002 8003 三台,OK?
    // 
    
    
    private int total = 0; 			// 总共被调用的次数,目前要求每台被调用5次
    private int currentIndex = 0;	// 当前提供服务的机器号
    
    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) {
    		/*
    		 * No servers. End regardless of pass, because subsequent passes only get more
    		 * restrictive.
    		 */
    		return null;
    	}
    //			int index = rand.nextInt(serverCount);// java.util.Random().nextInt(3);
    //			server = upList.get(index);
    
    			
    //			private int total = 0; 			// 总共被调用的次数,目前要求每台被调用5次
    //			private int currentIndex = 0;	// 当前提供服务的机器号
                if(total < 5)
                {
    	            server = upList.get(currentIndex);
    	            total++;
                }else {
    	            total = 0;
    	            currentIndex++;
    	            if(currentIndex >= upList.size())
    	            {
    	              currentIndex = 0;
    	            }
                }					
    			if (server == null) {
    				/*
    				 * The only time this should happen is if the server list were somehow trimmed.
    				 * This is a transient condition. Retry after yielding.
    				 */
    				Thread.yield();
    				continue;
    			}
    
    	if (server.isAlive()) {
    		return (server);
    	}
    
    	// Shouldn't actually happen.. but must be transient or a bug.
    	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
    
    }
    

    }

  2. Custom configuration on startup class routing policy @RibbonClient, when it starts to load the configuration

    @SpringBootApplication
    @EnableEurekaClient
    //在启动该微服务的时候就能去加载我们的自定义Ribbon配置类,从而使配置生效
    //@RibbonClient(name="MICROSERVICECLOUD-DEPT",configuration=MySelfRule.class)
    @RibbonClient(name="MICROSERVICECLOUD-DEPT",configuration=MySelfRule.class)
    public class DeptConsumer80_App
    {
    	public static void main(String[] args)
    	{
    		SpringApplication.run(DeptConsumer80_App.class, args);
    	}
    }
    

Note: The custom configuration class can not be placed under the current package @ComponentScan scanned and the lower sub-package, or our custom configuration class will be shared by all clients Ribbon lock, that is not up to specialized custom the purpose of the

5. implementation

5.1 configuration file method

Configuring the format:<client>.<nameSpace>.<property>=<value>

  • client for the client name: the service provider of external exposure of the service name
  • nameSpace for the namespace: default is the ribbon
  • property to the property name: Our strategy is to configure load balancingNFLoadBalancerRuleClassName cloud-provider.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRule
### 针对单个服务的 Ribbon 配置
MICROSERVICECLOUD-DEPT:
  ribbon: 
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule

Configuring global load balancing policy, right in front of the name can be removed from service

5.2 annotation mode

示例如下6

6. project combat

6.1 rely lead

<!-- Ribbon相关 -->
<!-- Eureka -->
<dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<!-- Ribbon -->
<dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-ribbon</artifactId>
</dependency>
<!-- Eureka相关 -->
<dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-web</artifactId>
</dependency>

6.2 configuration files

eureka:
  client:
    register-with-eureka: false
    service-url: 
      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/  

6.3 Configuration startup items in the consumer (client)

@SpringBootApplication
@EnableEurekaClient
// name:要调用服务(提供者)的名称,针对单个该服务使用的LB策略,默认是轮询
@RibbonClient(name="MICROSERVICECLOUD-DEPT",configuration=RetryRule.class)
public class DeptConsumer80_App
{
	public static void main(String[] args)
	{
		SpringApplication.run(DeptConsumer80_App.class, args);
	}

    @Bean
   	@LoadBalanced//Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端 , 负载均衡的工具。
   	public RestTemplate getRestTemplate()
   	{
   		return new RestTemplate();
   	}

}

RestTemplate can also be written on the uniform distribution center, so that each client no longer have written

    @Bean
   	@LoadBalanced//Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端 , 负载均衡的工具。
   	public RestTemplate getRestTemplate()
   	{
   		return new RestTemplate();
   	}

6.4 service layer calls service


// 注意,这些的是注册到Eureka上服务的名称地址,不是通过ip调用的。
// 直接调用服务而不用在关心地址和端口号
//private static final String REST_URL_PREFIX = "http://localhost:8001";
private static final String REST_URL_PREFIX = "http://MICROSERVICECLOUD-DEPT";

	/**
	 * 使用 使用restTemplate访问restful接口非常的简单粗暴无脑。
	 *  (url, requestMap, ResponseBean.class)这三个参数分别代表 REST请求地址、请求参数、HTTP响应转换被转换成的对象类型。
	 */
	@Autowired
	private RestTemplate restTemplate;

	@RequestMapping(value = "/consumer/dept/add")
	public boolean add(Dept dept)
	{
		。。。逻辑代码
		// 请求地址:服务地址+方法路径,参数,返回类型,这样就实现了调用别的服务
		// 完成真正的通过微服务名字从Eureka萨汗找到服务并访问
		return restTemplate.postForObject(REST_URL_PREFIX + "/dept/add", dept, Boolean.class);
		。。。逻辑代码
	}

Guess you like

Origin blog.csdn.net/wrs120/article/details/91573056