SpringCloud (Hoxton.SR3) basics: Chapter 2, the client provides load balancing service (Ribbon)

1. Introduction to Ribbon:

  Ribbon is a service that provides load balancing functions for clients. It internally provides an interface called ILoadBalance to represent the operations of the load balancer, such as adding server operations, selecting server operations, obtaining all server lists, and obtaining available server lists. and many more.

issues that need resolving:

  • ① How to not hard-code the address of Eureka Server when configuring Eureka Client registration center?
  • ② When communicating between different modules of a microservice, how do you not hard-code the address of the service provider?
  • ③ When deploying multiple same microservices, how to achieve load balancing at request?

What is Ribbon?

  Ribbon is a cloud middle-tier service open source project released by Netflix. Its main function is to provide clients to implement load balancing algorithms. Ribbon client component provides a series of perfect configuration items such as connection timeout, retry, etc. Simply put, Ribbon is a client load balancer. We can configure all the machines behind Load Balancer in the configuration file. Ribbon will automatically help you connect to these machines based on certain rules (such as simple polling, random connection, etc.) , We are also very easy to use Ribbon to implement a custom load balancing algorithm.
The following figure shows the general architecture of Eureka when using Ribbon:

 

Second, SpringCloud's Ribbon entry case

① First introduce the Ribbon dependency, the use of Ribbon depends on Eureka
<!-- eureka包含Ribbon依赖jar包  spring-cloud-netflix-ribbon-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

② How to use Ribbon

Use RestTemplate to communicate between Eureka Clients (including service providers and service consumers, in this case, service consumers use RestTemplate), add @LoadBalanced annotation to the RestTemplate configuration class , as shown below: 
 
@Bean 
@LoadBalanced
 public RestTemplate restTemplate () {
     return  new RestTemplate (); 
}

③ How to solve hard coding

 When using RestTemplate with the @LoadBalanced annotation to call the service provider's interface, you can use the virtual IP instead of the real IP address . The so-called virtual IP is the value of the spring.application.name property configured by the service provider in the application.properties or yml file . Examples are as follows:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import com.qxj.cloud.entity.User;

@RestController
public class MovieController {

    @Autowired
    private RestTemplate restTemplate;

    @RequestMapping(value="/movie/{id}",method = RequestMethod.GET,produces="application/json;charset=UTF-8")
    public User findById(@PathVariable Long id) {
     //微服务的虚拟id http://provider-user User user
= this.restTemplate.getForObject("http://provider-user:7900/simple/" + id, User.class); return user; } }

Small summary: After the integration of Ribbon and Eureka, Consumer can directly call the service without caring about the ip address and port number

Microservice (service provider) cluster construction:
Machine 1 
server: 
   port: 7900 
spring: 
   application: 
      name: provider-user 
#eureka client connection configuration 
eureka: 
   client: 
      service-url: 
         #Registration 
         center address defaultZone: http: // user: password123 @ localhost: 8761 / eureka 
   instance : 
      #Register ip to eureka 
      prefer-ip-address: true 
      #Microservice registers eureka with instance name $ {spring.cloud.client.ip-address} means ip address 
      instance-id: $ {spring.application.name} : $ {spring.cloud.client.ip-address}: $ {spring.application.instance_id: $ {server.port}} 

Machine 2 
server: 
   port: 7901 
spring: 
   application: 
      name: provider-user 
#eurekaClient connection configuration 
eureka:
   client: 
      service-url: 
         #Registration 
         center address defaultZone: http: // user: password123 @ localhost: 8761 / eureka 
   instance: #Register 
      ip to eureka 
      prefer-ip-address: true 
      #Micro service registers instance name with eureka $ {spring.cloud.client.ip-address} indicates the ip address 
      instance-id: $ {spring.application.name}: $ {spring.cloud.client.ip-address}: $ {spring.application.instance_id: $ { server.port)) 

Machine 3 
server: 
   port: 7902 
spring: 
   application: 
      name: provider-user 
#eureka client connection configuration 
eureka: 
   client: 
      service-url: 
   instance: 
         center address
         defaultZone: http: // user: password123 @ localhost: 8761 / eureka #Register
      #Register ip to eureka 
      prefer-ip-address: true 
      #Microservice registers eureka with instance name $ {spring.cloud.client.ip-address} means ip address 
      instance-id: $ {spring.application.name}: $ {spring.cloud.client.ip-address}: $ {spring.application.instance_id: $ {server.port}}

The {Spring.application.name} is the same and cannot be changed.

 

 

 

Three, Ribbon component IRule

The default is RoundBobinRule (Poll)

 

Four, custom load balancing algorithm:

  The main function of the so-called custom Ribbon Client is to use a custom configuration to replace the Ribbon's default load balancing strategy. Note: The custom Ribbon Client is targeted. Generally, a custom Ribbon Client is for a service provider (including A series of copies with the same service name). A Ribbon Client has been customized. The load balancing strategy set by it is only valid for the service provider of a specific service name, but it cannot affect the strategy used by the service consumer to communicate with other service providers. According to the meaning of the official documentation, it is recommended to customize the configuration class outside the scope of the package scanned by the springboot main program . In fact, there are two ways to customize RibbonClient with pure code:

Method 1: Define the configuration class outside the package scanned by the springboot main program, and then add the @RibbonClient annotation to the springboot main program to introduce the configuration class .
 
Springboot main program:
import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 import org.springframework.cloud.client.loadbalancer.LoadBalanced;
 import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
 import org.springframework .cloud.netflix.ribbon.RibbonClient;
 import org.springframework.context.annotation.Bean;
 import org.springframework.web.client.RestTemplate; 

import com.qxj.configuration.MySelfRule; 

@SpringBootApplication 
// This annotation indicates that the application is both The eureka instance is the eureka client and can discover the registered service 
@EnableEurekaClient
 //When starting the 
microservice , we can load our custom Ribbon configuration class, so that the configuration takes effect @RibbonClient (name = "provider-user", configuration = MySelfRule. Class )
 public  class ConsumerMovieRibbonApplication { 
    
    @Bean 
    @LoadBalanced 
    public RestTemplate restTemplate () {
         return  new RestTemplate (); 
    } 
    
    public  static  void main (String [] args) { 
        SpringApplication.run (ConsumerMovieRibbonApplication. class , args); 
    } 
}

 

Rule configuration file, configuration, and should not be in the package path SpringBoot , by @RibbonClient comment Load:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.netflix.loadbalancer.IRule;

@Configuration
public class MySelfRule {
    @Bean
    public IRule MyRule() {
        return new RandomRule_QXJ();
    }
}

 

Custom LoadBalance:

import java.util.List; 

import com.netflix.client.config.IClientConfig;
 import com.netflix.loadbalancer.AbstractLoadBalancerRule;
 import com.netflix.loadbalancer.ILoadBalancer;
 import com.netflix.loadbalancer.Server; 

public  class RandomRule_QXJ extends AbstractLoadBalancerRule { 
    
    private  int total = 0;          // The total number of calls, currently requires each call 5 times 
    private  int currentIndex = 0;         // Currently provided service machine number 
    
    / ** 
     * Service selection algorithm, requires each call 5 times 
     * @param lb 
     * @paramkey 
     * @return 
     * / 
    public Server choose (ILoadBalancer lb, Object key) {
         if (lb == null ) {
             return  null ; 
        } 
        
        Server server = null ;
         while (server == null ) {
             // Determine whether the current thread is interrupted
             / / interrupted () is a static method: the internal implementation is called isInterrupted () of the current thread, and will reset the interruption status of the current thread 
            if (Thread.interrupted ()) {
                 return  null ; 
            } 
            // Activate available services
            List <Server> upList = lb.getReachableServers ();
             // All services 
            List <Server> allList = lb.getAllServers (); 
            
            int serverCount = allList.size ();
             if (serverCount == 0 ) {
                 return  null ; 
            } 
            
            if (total <5 ) { 
                server = upList.get (currentIndex); 
                total ++ ; 
            } else { 
                total = 0 ;
                 // Use the next machine service
                currentIndex ++ ;
                 // If the current service machine is the last one in the upList collection, reuse the first machine service 
                if (currentIndex> = upList.size ()) { 
                    currentIndex = 0 ; 
                } 
            } 
            System.out.println ( "currentIndex: "+ currentIndex +" --- total: "+ total);
             // When looping to the first service, server == null, you need to reacquire server 
            if (server == null ) { 
                Thread.yield (); 
                continue ; 
            } 
            
            if (server.isAlive ()) {
                 return server; 
            }
            
            // This code will not actually execute 
            server = null ; 
            Thread.yield (); 
        } 
        
        return server; 
    } 
    
    @Override 
    public Server choose (Object key) {
         return choose (getLoadBalancer (), key); 
    } 

    @Override 
    public  void initWithNiwsConfig (IClientConfig clientConfig) { 
    } 

}

 

Method 2: Application.yml file configuration method

 

# @ RibbonClient (name = "provider-user") Same as name, it means to use custom load balancing rules for this 
    microservice 
provider-user: 
  ribbon: NFLoadBalancerRuleClassName: com.qxj.configuration.RandomRule_QXJ

 

Configured priority

Priority of configuration file> Java code configuration method> netflix custom configuration method

 

————————————————
Copyright Statement: This article is an original article of CSDN blogger "An Xiaoyan said he is busy", following the CC 4.0 BY-SA copyright agreement, please attach the original text for reprint Source link and this statement.
Original link: https://blog.csdn.net/JinXYan/java/article/details/90726707

Guess you like

Origin www.cnblogs.com/wps54213/p/12701919.html