Ribbon

An overview,

Spring Cloud Ribbon is a set of client load balancing tools based on the Netflix Ribbon.

Simply put, the Ribbon is an open source project released by Netflix. Its main function is to provide software load balancing algorithms and service invocation on the client side. The Ribbon client component provides a wide range of configuration options such as connection timeout and retry. Simply put, the Ribbon lists all the machines following the Load Balancer (LB) in the configuration file. The Ribbon automatically helps you connect them based on certain rules (simple polling, random connections, etc.). It’s easy to use the Ribbon to implement custom load balancing algorithms.

Official document: github.com/Netflix/rib…

LB Load balancing (LB) is a Load balancing system that distributes user requests to multiple services to achieve high availability (HA). Common Load balancing systems include software Nginx, LVS, and hardware F5.

Ribbon Local LB clients (in-process LB) vs. Nginx Server LB Differences (centralized LB) : Nginx is a SERVER LB. All client requests are forwarded to Nginx. That is, load balancing is implemented on the server side.

The Ribbon provides local load balancing. When a microservice interface is invoked, the Ribbon cache the list of registered services from the registry to the JVM. In this way, RPC remote service invocation technology is implemented locally.

Ribbon= Load balancing +RestTemplate calls

Ribbon Load balancing demo

1. Architecture description

The Ribbon works in two steps. The first step is to select EurekaServer. The first step is to select servers that have less load in the same area.

The second step is to select an address from the service registration list fetched from the server according to the policy specified by the user. The Ribbon provides a variety of strategies: such as polling, random, and weighting based on response time.

Conclusion: The Ribbon is a soft load-balancing client component that can be used with other clients that require it. Eureka is just one example.

2, POM

The Spring-cloud-starter – Netflix-Eureka-client comes with the Spring-cloud-starter -ribbon reference.

3. Use the RestTemplate

(1) official website

Docs. Spring. IO/spring – fram…

(2)getForObject method /getForEntity method

The returned object is the object converted from the data in the response body, which can be basically understood as Json.

The returned object is the ResponseEntity object, which contains important information about the response, such as the response header, the response status code, and the response body.

@GetMapping("/consumer/payment/getForEntity/{id}")
public CommonResult<Payment> getPayment2(@PathVariable("id") Long id){
    ResponseEntity<CommonResult> entity =  restTemplate.getForEntity(PAYMENT_URL+"/payment/get/"+id,CommonResult.class);
    if(entity.getStatusCode().is2xxSuccessful()){
        return entity.getBody();
    }else{
        return new CommonResult<>(444."Operation failed"); }}Copy the code

(3)postForObject/postForEntity

@GetMapping("/consumer/payment/create")
public CommonResult<Payment> create(Payment payment){
    return restTemplate.postForObject(PAYMENT_URL+"/payment/create",payment,CommonResult.class);
    //return restTemplate.postForEntity(PAYMENT_URL+"/payment/create",payment,CommonResult.class).getBody();
}
Copy the code

IRule, the core component of the Ribbon

1, IRule

Select a service to access from the list of services based on a particular algorithm:

Com.net flix. Loadbalancer. RoundRobinRule: polling

Com.net flix. Loadbalancer. RandomRule: random

Com.net flix. Loadbalancer. RetryRule: according to the first RoundRobinRule strategies for service, if failed to get the service within a specified time will retry, access to services available

WeightedResponseTimeRule: an extension of RoundRobinRule. The more responsive the instance is, the more likely it is to be selected

BestAvailableRule: Filters out the service that is in breaker trip state due to multiple access failures, and then selects the service with the least concurrency

AvailabilityFilteringRule: to filter out the first example, choose the instance of concurrent smaller again

ZoneAvoidanceRule: Default rule that selects a server based on compound judgments about performance and server availability in the zone where the server is located

2, how to replace

(1) to modify the cloud – consumer – order80

(2) Pay attention to configuration details

The official document gives a clear warning:

This custom configuration class cannot be placed under the current package or subpackage scanned by @ComponentScan. Otherwise, our custom configuration class will be shared by all the Ribbon clients, and will not serve the purpose of customization.

(3) the new package

com.atguigu.myrule

(4) Create the MySelfRule rule class

@Configuration
public class MySelfRule{
    @Bean
    public IRule myRule(a){
        return new RandomRule();// Defined as random, the default is polling}}Copy the code

(5) Add @RibbonClient to the main boot class

@RibbonClient(name = "CLOUD-PAYMENT-SERVICE",configuration=MySelfRule.class)
Copy the code

(6) test

http://localhost/consumer/payment/get/31

Ribbon load balancing algorithm

1, the principle of

Load balancing algorithm: Number of REST interface requests % Total number of server clusters = the subscript of the actual calling server. The rest interface count starts from 1 after each service restart.

List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");
Copy the code

For example, List [0] Instances = 127.0.0.1:8002 List [1] Instances = 127.0.0.1:8001

8001+ 8002 is combined into a cluster. There are two machines in total, and the total number of the cluster is 2. According to the polling algorithm principle:

If the total number of requests is 1: 1%2 =1, then the service address is 127.0.0.1:8002. If the total number of requests is 2:2%2 =0, then the service address is 127.0.0.1:8002. If the total number of requests is 3, then the service address is 127.0.0.1:8002. 3%2 =1 corresponds to the subscript position is 1, then the service address is 127.0.0.1:8001. When the total number of requests is 4:4%2 =0 corresponds to the subscript position is 0, the service address is 127.0.0.1:8002 and so on……

2. RoundRobinRule source code

3. Write the local load balancer

(1) Cluster 7001/7002 starts

(2)8001/8002 micro-service transformation

controller

@GetMapping(value = "/payment/lb")
public String getPaymentLB(a){
    return serverPort;
}
Copy the code

(3) micro-service transformation of 80 orders

Remove @loadBalanced annotation from ApplicationContextBean

(2) the LoadBalancer interface

public interface LoadBalancer{
    ServiceInstance instances(List<ServiceInstance> serviceInstances);
}
Copy the code

(3) MyLB

@Component
public class MyLB implements LoadBalancer{
    private AtomicInteger atomicInteger = new AtomicInteger(0);
    public final int getAndIncrement(a){
        int current;
        int next;
        do{
            current = this.atomicInteger.get();
            next = current >= 2147483647 ? 0 : current + 1;
        } while(!this.atomicInteger.compareAndSet(current, next));
        System.out.println("*****next: "+next);
        return next;
    }
    @Override
    public ServiceInstance instances(List<ServiceInstance> serviceInstances){
        int index = getAndIncrement() % serviceInstances.size();
        returnserviceInstances.get(index); }}Copy the code

(4) OrderController

@RestController
public class OrderController{
    //public static final String PAYMENT_SRV = "http://localhost:8001";
    public static final String PAYMENT_SRV = "http://CLOUD-PAYMENT-SERVICE";

    @Resource
    private RestTemplate restTemplate;
    // You can get a list of services on the registry
    @Resource
    private DiscoveryClient discoveryClient;
    @Resource
    private LoadBalancer loadBalancer;

    @GetMapping("/consumer/payment/create")
    public CommonResult<Payment> create(Payment payment){
        return restTemplate.postForObject(PAYMENT_SRV+"/payment/create",payment,CommonResult.class);
    }

    @GetMapping("/consumer/payment/get/{id}")
    public CommonResult<Payment> getPayment(@PathVariable("id") Long id){
        return restTemplate.getForObject(PAYMENT_SRV+"/payment/get/"+id,CommonResult.class);
    }

    @GetMapping("/consumer/payment/getForEntity/{id}")
    public CommonResult<Payment> getPayment2(@PathVariable("id") Long id){
        ResponseEntity<CommonResult> entity = restTemplate.getForEntity(PAYMENT_SRV+"/payment/get/"+id, CommonResult.class);
        if(entity.getStatusCode().is2xxSuccessful()){
            return entity.getBody();
        }else{
            return new CommonResult(444."Operation failed"); }}@Resource
    private LoadBalancer loadBalancer;

    @GetMapping("/consumer/payment/lb")
    public String getPaymentLB(a){
        List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");
        if(instances == null || instances.size()<=0) {
            return null;
        }
        ServiceInstance serviceInstance = loadBalancer.instances(instances);
        URI uri = serviceInstance.getUri();
        return restTemplate.getForObject(uri+"/payment/lb",String.class); }}Copy the code

(5) test

http://localhost/consumer/payment/lb

OpenFeign

An overview,

What is OpenFeign

Feign is a declarative Web services client that makes it easy to write Web services clients by simply creating an interface and adding annotations to it.

GitHub:github.com/spring-clou…

2. What can I do

What can Feign do

Feign aims to make it easier to write Java Http clients. When using the Ribbon+RestTemplate, the RestTemplate encapsulates HTTP requests and forms a set of template calling methods. However, in actual development, because service dependencies may be called in more than one place, often an interface will be called in multiple places, so it is common to encapsulate some client classes for each microservice to wrap the invocation of these dependent services. So, Feign took this one step further by helping us define and implement the definition of a dependent service interface. With Feign, we simply create an interface and configure it with an annotation (formerly a Dao interface with a Mapper annotation, now a microservice interface with a Feign annotation) to bind the interface to the service provider. Simplifies the use of Spring Cloud Ribbon to automatically wrap development for service invocation clients.

Feign integrates the Ribbon

The Ribbon is used to maintain the Payment service list information, and the client load balance is realized through polling. Unlike the Ribbon, feign only defines the service binding interface and implements service invocation in a declarative way with elegance and simplicity.

3. Differences between Feign and OpenFeign

Feign OpenFeign
Feign is a lightweight RESTful HTTP service client in the Spring Cloud component. Feign has built-in Ribbon for client load balancing and calling services in the service registry. Feign is used by using Feign annotations to define an interface that can be invoked to invoke services in the service registry OpenFeign is Spring Cloud’s support for SpringMVC annotations, such as @requesMapping, on the basis of Feign. OpenFeign’s @FeignClient can parse the interface under SpringMVC’s @RequestMapping annotation and use dynamic proxy to generate implementation classes that perform load balancing and invoke other services

org.springframework.cloud

spring-cloud-starter-feign


org.springframework.cloud

spring-cloud-starter-openfeign

Second, OpenFeign use steps

Interface + annotations: Microservice invocation interface +@FeignClient

1, create cloud-consumer-Feign-order80

Feign is available on the consumer side

2, POM

<! --openfeign--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> <! --eureka client--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency>Copy the code

3, YML

server:
  port: 80

eureka:
  client:
    register-with-eureka: false
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/
Copy the code

4. Main startup

@SpringBootApplication
@EnableFeignClients/ / open
public class OrderFeignMain80 {
    public static void main(String[] args) { SpringApplication.run(OrderFeignMain80.class,args); }}Copy the code

5. Business

Service logic interface + @feignClient Configures to invoke the Provider service

(1) Create PaymentFeignService interface and add annotation @feignClient

@Component
@FeignClient(value = "CLOUD-PAYMENT-SERVICE")/ / use
public interface PaymentFeignService {
    @GetMapping(value = "/payment/get/{id}")
    CommonResult<Payment> getPaymentById(@PathVariable("id") Long id);
}
Copy the code

(2) Control layer Controller

@Slf4j
@RestController
public class OrderFeignController {
    @Resource
    private PaymentFeignService paymentFeignService;

    @GetMapping(value = "/consumer/payment/get/{id}")
    public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id) {
        returnpaymentFeignService.getPaymentById(id); }}Copy the code

6, test,

To start the first two had 7001/7002 cluster, and then start two micro service 8001/8002, start OpenFeign start, http://localhost/consumer/payment/get/31

Feign Provides load balancing configuration items

Three, OpenFeign timeout control

1, timeout Settings, intentionally set timeout demo error

(1) Service Provider 8001 intentionally writes the pause program

@GetMapping(value = "/payment/feign/timeout")
public String paymentFeignTimeOut(a){
	System.out.println("*****paymentFeignTimeOut from port: "+serverPort);
	// Pause the thread for a few seconds
	try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); }
	return serverPort;
}
Copy the code

(2) Service consumer 80 Add timeout method PaymentFeignService

@GetMapping(value = "/payment/feign/timeout")
String paymentFeignTimeOut(a);
Copy the code

(3) The service consumer 80 adds the timeout method OrderFeignController

@GetMapping(value = "/consumer/payment/feign/timeout")
public String paymentFeignTimeOut(a){
    // OpenFeign -ribbon. Clients usually wait one second by default
    return paymentFeignService.paymentFeignTimeOut();
}
Copy the code

(4) test

http://localhost/consumer/payment/feign/timeout

By default, OpenFeign will wait 1 second and then report an error

By default, OpenFeign supports the Ribbon

By default, the Feign client waits only one second, but the server takes more than one second to process, causing the Feign client to stop waiting and return an error. To avoid this, sometimes we need to set the Feign client timeout control.

3. OpenFeign client timeout control needs to be enabled in YML files

# Set the feign client timeout period (OpenFeign supports the ribbon by default)
ribbon:
# refers to the time it takes to read the available resources from the server after the connection is established
  ReadTimeout: 5000
# refers to the time it takes to establish a connection, which applies to the time it takes for both ends to connect if the network is normal
  ConnectTimeout: 5000
Copy the code

Four, OpenFeign log printing function

1. What is it

Feign provides log printing capabilities, which can be configured to adjust the log level to see the details of Http requests in Feign. Basically, it monitors and outputs calls to the Feign interface.

2. Log level

NONE: The default value. No logs are displayed.

BASIC: Records only the request method, URL, response status code, and execution time.

HEADERS: Request and response HEADERS in addition to the information defined in BASIC;

FULL: In addition to the information defined in HEADERS, there is the body and metadata of the request and response.

3. Configure the log bean

@Configuration
public class FeignConfig {
    @Bean
    Logger.Level feignLoggerLevel(a) {
        returnLogger.Level.FULL; }}Copy the code

4. YML files need to enable Feign client for logging

logging:
  level:
    # Feign Logs monitor which interface at what level
    com.atguigu.springcloud.service.PaymentFeignService: debug
Copy the code

5. View background logs