Huoying recommender serializes 20 spring cloud service load balancing and calls Ribbon and OpenFeign

1,Ribbon

Spring Cloud Ribbon is a set of client-side load balancing tools based on Netflix Ribbon.
In short, Ribbon is an open source project released by Netlix. Its main function is to provide software load balancing algorithms and service calls on the client. The Ribbon client component provides a series of complete configuration items, such as connection timeout, Retry, etc. To put it simply, list all the machines behind the load balancer (LB) in the configuration file. The Ribbon will automatically help you connect these machines based on certain rules (such as simple polling, random connection, etc.). We can easily use Ribbon to implement a custom load balancing algorithm.

At present, Ribbon and Eureka are in maintenance mode. Stop and do not stop

Load balancing:

What is LB load balance?
Simply put, it is to distribute the user's requests equally to multiple services, so as to achieve the ha (high availability) of the system. one
Common load balancing include software Nginx, LVS, hardware F5, etc.
Ribbon local load balancing client VS Nginx server load balancing difference
Nginx is server load balancing. All client requests will be handed over to nginx, and then nginx will forward the requests. Load balancing is realized by the server.
Ribbon local load balancing: when calling the micro service interface, it will obtain the registration information service list on the registry and cache it to the VM local, so as to realize RPC remote control locally
Process service invocation technology.

1. Centralized LB
That is, an independent LB facility (which can be hardware, such as F5, or software, such as nginx) is used between the service consumer and the service provider, and the facility is responsible for forwarding the access request to the service provider through some policy;

2. In process LB
Integrate LB logic into the consumer. The consumer knows which addresses are available from the service registry, and then selects a suitable server from these addresses. Ribbon belongs to in-process lb, which is just a class library integrated into the consumer process, through which the consumer obtains the address of the service provider.

Load balancing + RestTemplate

framework

Summary: Ribbon is actually a client component of soft load balancing. It can be used in combination with other clients requiring requests. The combination with eureka is just one example

Ribbon works in two steps
The first step is to select Eureka server, which gives priority to servers with less load in the same region
The second step is to select an address from the service registration list obtained from the server according to the policy specified by the user.
Among them, Ribbon provides a variety of strategies: such as polling, random and weighting according to response time.

pom rely on 
spring-cloud-starter-netflix-eureka-client
 It integrates itself ribbon . 

Description of RestTemplate:

Ribbon load balancing rules

Inheritance structure

Comes with 7 kinds:

How to use? Load balancing policy replacement.

The official document clearly gives a warning:
This custom configuration class cannot be placed under the current package and sub package scanned by @ ComponentScan,
Otherwise, the configuration class we customized will be shared by all Ribbon clients, and the purpose of customization will not be achieved.

Add rule configuration class

Package path: com.fage.rules
    
@Configuration
public class MyRibbonRule {
    @Bean
    public IRule randomRule() {
        return new RandomRule();
    }

}

Add annotation to boot class

@RibbonClient(name = "cloud-payment-service", configuration = {MyRibbonRule.class})

Principle of load balancing polling algorithm

Load balancing algorithm: the number of requests of the rest interface% the total number of server clusters = the subscript of the actual calling server location. The count of the rest interface starts from 1 after each service restart.
List instances = discoveryClient.getlnstances(CLOUD-PAYMENT-SERVICE");
For example: List [o] instances = 127.0.0.1:8002
List [1] instances = 127.0.0.1:8001
8001 + 8002 are combined into clusters. There are 2 machines in total, and the total number of clusters is 2. According to the principle of polling algorithm:
When the total number of requests is 1: 1% 2 = 1 and the corresponding subscript position is 1, the service address obtained is 127.0.0.1:8001
When the total request digit is 2: 2%2=O and the corresponding subscript position is 0, the service address is 127.0.0.1:8002
When the total request digit is 3: 3% 2 = 1 and the corresponding subscript position is 1, the service address is 127.0.0.1:8001
When the total request digit is 4: 4% 2 = 0 and the corresponding subscript position is 0, the service address is 127.0.0.1:8002
And so on

Source code:

Start from 0 to get the provider service.

cas + spin lock is used internally.

Write a load balancing algorithm to realize polling

1. Service providers add interfaces

    @GetMapping("/payment/loadBalanced")
    public CommonResult<Object> getLoadBalanced() {
        return new CommonResult<>(200, "Call succeeded", port);
    }

2. Service consumer transformation

Remove the @ LoadBalanced annotation

Add the MyLoadBalanced interface. There is only one method serviceinstance (list serviceInstances); Used to obtain the instance object to be used after the current algorithm.

The source code of the implementation class MyLib is as follows:

@Component
@Slf4j
public class MyLib implements MyLoadBalanced {

    private final AtomicInteger nextServerCyclicCounter = new AtomicInteger(0);

    public final int getAndIncrement() {
        // Scenario 1 cas 
//        int current;
//        int next;
//        do {
//            current = this.nextServerCyclicCounter.get();
//            next = current >= 2147483647 ? 0 : current + 1;
//        } while (!this.nextServerCyclicCounter.compareAndSet(current, next));
//        log.info("********** number of visits, next:" + next);
//        return next;

        // Scheme 2 self increasing method provided by JUC 
        log.info("**********Number of visits next: " + nextServerCyclicCounter.getAndIncrement());
        return nextServerCyclicCounter.get();
    }

    /**
     * Load balancing algorithm: the number of requests of the rest interface% total number of server clusters = the subscript of the actual calling server location. The count of the rest interface starts from 1 after each service restart
     *
     * @param serviceInstances Service instance in cluster
     * @return An instance in the cluster
     */
    @Override
    public ServiceInstance instance(List<ServiceInstance> serviceInstances) {
        return serviceInstances.get(getAndIncre
  using TickEvent = std::function<void(std::int64_t elapsed_ms)>;
  
  using TickRunCallback = std::function<void()>
  
  using clock = std::chrono::high_resolution_clock;
  
  Tick(std::int64_www.jintianxuesha.com t tick_ms,
  
  std::int64_t life_ms =www.hengxinzhce.cn std::numeric_limits<std::int64_t>::max());
  
  Tick(TickEvent tick_event, www.feihongyul.cn std::int64_t tick_ms,
  
  std::int64_t life_ms = std::numeric_limits<www.uuedzc.cn std::int64_t>::max(),
  
  TickRunCallback run_beg = nullptr,
  
  TickRunCallback run_end = nullptr);
  
  virtual ~Tick(www.qiaoheibpt.com )www.jujinyule.com ;
  
  bool IsRunning(www.yachengyl.cn) const;
  
  void Start(www.baichuangyule.cn);
  
  void Stop(bool wait_life_over = false);
  
  const std::chrono::www.jinmazx.cn    www.bhylzc.cn time_point<clock> &GetTimeStart() const;
  
  void SetTickEvent(TickEvent &&tick_event);
  
  void SetTickEvent(www.zhuyngyule.cn const TickEvent &tick_event);
  
  void SetRunBegCallback(www.shicaiyulezc.cn    www.wyuleezc.cn TickRunCallback &&run_beg);
  
  void SetRunBegCallback(www.pingguoyul.cn     www.kunlunyxgw.com const TickRunCallback &run_beg);
  
  void SetRunEndCallback(TickRunCallback &&run_end);
  
ment() % serviceInstances.size());
    }
}

3. Transform consumer call method

    @GetMapping(value = "/consumer/payment/loadBalanced")
    public CommonResult getLoadBalanced() {
        ServiceInstance instance = myLoadBalanced.instance(discoveryClient.getInstances(PAYMENT_URL.split("//")[1]));
        return restTemplate.getForObject(instance.getUri()+"/payment/loadBalanced", CommonResult.class);
    }

2,OpenFeign

You only need one interface and add annotations on it.

feign is no longer updated. Learn openFeign directly. Are used for load balancing.

Feign is a declarative Web Service client. Using feign makes it easier to write a Web Service client.
It is used by defining a service interface and then adding annotations on it. Feign also supports pluggable codecs and decoders. Spring Cloud encapsulates feign to support Spring MVC standard annotations and HttpMessageConverters. Feign and ribbon are used in combination to support load balancing.

What can Feign do

Feign aims to make it easier to write Java Http clients.
When Ribbon+RestTemplate is used earlier, a set of template calling methods is formed by encapsulating http requests with RestTemplate. But in actual development
In, because there may be more than one call that depends on the service, and often an interface will be called in multiple places, it usually encapsulates some client classes for each micro service
These depend on the invocation of services. Therefore, Feign made further encapsulation on this basis to help us define and implement the definition of dependent service interfaces. Under the implementation of Feign
, we just need to create an interface and configure it with annotations (formerly Dao interface marked with Mapper annotation, now a microservice interface marked with one)
Feign annotation can complete the interface binding to the service provider, which simplifies the development of automatically encapsulating the service call client when using the Spring cloud Ribbon.

Feign integrates Ribbon

The Ribbon is used to maintain the service list information of Payment, and the load balancing of the client is realized through polling. Unlike Ribbon, feign only needs to define
The service is bound to the interface and implements the service invocation gracefully and simply with a declarative method

The difference between Feign and openFeign

Build openFeign module cloud-consumer-openfeign-order80

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

Add annotation @ EnableFeignClients to startup class

Add feign interface

@Component
@FeignClient(value = "cloud-payment-service")
public interface OpenFeignService {
    @GetMapping("/payment/loadBalanced")
    public CommonResult<Object> getLoadBalanced();
}

Add controller

@RestController
@Slf4j
public class OrderController implements OpenFeignService {
    @Resource
    OpenFeignService openFeignService;

    @Override
    @GetMapping("/consumer/payment/loadBalanced")
    public CommonResult<Object> getLoadBalanced() {
        return openFeignService.getLoadBalanced();
    }
}

The registry uses eureka. Same as before.

OpenFeign timeout control

The default waiting time of OpenFeign is 1ms.

Set timeout

###Set timeout mode 1
# Set feign client timeout (openFeign supports ribbon by default)
ribbon:
  # It refers to the time taken to establish the connection. When the network condition is normal, the time unit used for the connection between the two ends is seconds
  ReadTimeout: 6000
  # It refers to the time when the available resources are read from the server after the connection is established
  ConnectTimeout: 5000
  
  
###Set timeout mode 2
#feign:
#  client:
#    config:
#      default:
#        connectTimeout: 5000
#        readTimeout: 6000
#        loggerLevel: full  

OpenFeign log enhancement

Feign provides log printing function. We can adjust the log level through configuration to understand the details of Http requests in feign.
To put it bluntly, it is to monitor and output the call of Feign interface

Log level:

NONE: by default, no logs are displayed;
BASIC: only record the request method, URL, response status code and execution time;
HEADERS: in addition to the information defined in BASIC, there are also header information of request and response;
FULL: in addition to the information defined in HEADERS, there are also the body and metadata of the request and response.

Configure log bean:

    @Bean
    Logger.Level feignLoggerLevel() {
        return Logger.Level.FULL;
    }

yml open log

# Set feign client timeout (openFeign supports ribbon by default)
ribbon:
  # It refers to the time taken for the resume connection. It is applicable to the case that the network condition is normal. The time unit used for the connection between the two ends is seconds
  ReadTimeout: 8000
  # It refers to the time when the available resources are read from the server after the connection is established
  ConnectTimeout: 6000

# Enable feign log printing
logging:
  level:
    ## At what level does feign log monitor that interface
    com.fage.springcloud.feign.OpenFeignService: debug

result:

2020-08-25 17:55:26.667 DEBUG 56624 --- [p-nio-80-exec-2] c.f.springcloud.feign.OpenFeignService   : [OpenFeignService#getLoadBalanced] ---> GET http://cloud-payment-service/payment/loadBalanced HTTP/1.1
2020-08-25 17:55:26.667 DEBUG 56624 --- [p-nio-80-exec-2] c.f.springcloud.feign.OpenFeignService   : [OpenFeignService#getLoadBalanced] ---> END HTTP (0-byte body)
2020-08-25 17:55:26.682 DEBUG 56624 --- [p-nio-80-exec-2] c.f.springcloud.feign.OpenFeignService   : [OpenFeignService#getLoadBalanced] <--- HTTP/1.1 200 (14ms)
2020-08-25 17:55:26.682 DEBUG 56624 --- [p-nio-80-exec-2] c.f.springcloud.feign.OpenFeignService   : [OpenFeignService#getLoadBalanced] connection: keep-alive
2020-08-25 17:55:26.682 DEBUG 56624 --- [p-nio-80-exec-2] c.f.springcloud.feign.OpenFeignService   : [OpenFeignService#getLoadBalanced] content-type: application/json
2020-08-25 17:55:26.682 DEBUG 56624 --- [p-nio-80-exec-2] c.f.springcloud.feign.OpenFeignService   : [OpenFeignService#getLoadBalanced] date: Tue, 25 Aug 2020 09:55:26 GMT
2020-08-25 17:55:26.682 DEBUG 56624 --- [p-nio-80-exec-2] c.f.springcloud.feign.OpenFeignService   : [OpenFeignService#getLoadBalanced] keep-alive: timeout=60
2020-08-25 17:55:26.682 DEBUG 56624 --- [p-nio-80-exec-2] c.f.springcloud.feign.OpenFeignService   : [OpenFeignService#getLoadBalanced] transfer-encoding: chunked
2020-08-25 17:55:26.682 DEBUG 56624 --- [p-nio-80-exec-2] c.f.springcloud.feign.OpenFeignService   : [OpenFeignService#getLoadBalanced] 
2020-08-25 17:55:26.683 DEBUG 56624 --- [p-nio-80-exec-2] c.f.springcloud.feign.OpenFeignService   : [OpenFeignService#getLoadBalanced] {"code":200,"message": "call succeeded", "data":"8001"}
2020-08-25 17:55:26.683 DEBUG 56624 --- [p-nio-80-exec-2] c.f.springcloud.feign.OpenFeignService   : [OpenFeignService

Posted by JAM on Thu, 19 May 2022 16:17:52 +0300