Spring cloud -- getting started with service invocation

For each service configured to the registry, we need a technology to make these services call each other. In the original service invocation, httpclient is adopted, and then it evolves into restTemplate (the template tool set for accessing rest services provided by spring).

Ribbon

1.Ribbon: a set of client load balancing tools based on Netflix Ribbon. The main function is to provide the software load balancing algorithm and service call of the client. Ribbon client component provides a series of perfect configuration items, such as connection timeout, Retry, etc.
2.Ribbon workflow: first select EurekaServer and give priority to servers with less load in the same area. Then select an address from the service registration list obtained from the server according to the policy specified by the user.
3.Ribbon adopts LB (Load Balance) load balancing: the multiple requests of users are evenly distributed to multiple services. Different from the nginx load balancing we know, nginx is the debt balancing of the server. The client gives all requests to nginx, and then nginx forwards the requests, that is, the load balancing is completed by the server.
4.DiscoveryClient: for the micro service registered in eureka, you can obtain the information of the service through service discovery. You need to add @ EnableDiscoveryClient to the main startup class

 @GetMapping("/payment/discovery")
    public Object discovery(){
        // Get the service of the registry
        List<String> services = discoveryClient.getServices();
        for(String element: services){
            log.info("***element***"+element);
        }
        // Gets the service information of the specified service name
        List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");
        for(ServiceInstance instance:instances){
            log.info(instance.getServiceId()+"\t"+instance.getHost()+"\t"+instance.getPort()+"\t"+
                    instance.getUri());
        }
        return this.discoveryClient;
    }

5.RestTemplate has two methods to call service: postforebject and postForEntity

  //static final String PAYMENT_URL = "http://localhost:8081";

 static final String PAYMENT_URL = "http://CLOUD-PAYMENT-SERVICE";

@GetMapping("/consumer/payment/get/{id}")
    public CommonResult<Payment> getPayment(@PathVariable("id") Long id){
        /** postForObject(The returned object is the data in the response body (converted to object: Jason)
         * 1.url: Request address
         * 2.responseType: Returned data
         */
        return  restTemplate.getForObject(PAYMENT_URL+"/payment/get/"+id,CommonResult.class);
    }

@GetMapping("/consumer/payment/getForEntity/{id}")
    public CommonResult<Payment> getPaymentEntity(@PathVariable("id") Long id){
        /** getForEntity(The returned responseEntity object contains some corresponding information (response header and response status code). The getBody method needs to be added to the return
         * 1.url: Request address
         * 2.responseType: Returned data
         */
        ResponseEntity<CommonResult> entity = restTemplate.getForEntity(PAYMENT_URL+"/payment/get/"+id,CommonResult.class);
        if(entity.getStatusCode().is2xxSuccessful()){
            log.info("ResponseEntity{}",entity);
            return entity.getBody();
        }else{
            return new CommonResult<>(400,"operation failed");
        }
    }

Add: for Eureka cluster, the consumer should no longer write the dead address, but write the service name (registry name; uppercase), and add @ LoadBalanced annotation (polling mechanism by default)

6.Ribbon comes with seven load rules:
①com. netflix. loadbalancer. Roundrobin rule (polling)
②com.netflix.loadbalancer.RandomRule (random)
③com.netflix.loadbalancer.RetryRule (first obtain the service according to the roundrobin rule policy. If the service acquisition fails, retry within the specified time to obtain the available service)
④ WeightedResponseTimeRule (an extension of roundrobin rule. The faster the response speed, the greater the instance selection weight, and the easier it is to be selected)
⑤ BestAvailableRule (it will filter out the services in the circuit breaker tripping state due to multiple access faults, and then select a service with the least concurrency)
⑥ Availability filtering rule (filter out failed instances first, and then select less concurrent instances)
⑦ ZoneAvoidanceRule (default rule, which determines the performance of the region where the server is located and the availability of the server, and selects the server)
7.Ribbon replacement rule: this custom configuration class cannot be placed under the current package and sub package scanned by @ ComponentScan, otherwise our custom configuration class will be shared by all ribbon clients and the purpose of special customization will not be achieved. @ LoadBalanced cannot be removed

8. Load balancing algorithm: the number of rest requests% (remainder) the total number of service clusters = the subscript of the actual call server location, and each restart of rest starts from 1.
Note: the @ LoadBalanced annotation needs to be removed for handwriting algorithm call

public interface LoadBalancer {
    ServiceInstance serviceInstance(List<ServiceInstance> serviceInstances);
}


@Component
public class MyLB implements LoadBalancer {

    private AtomicInteger atomicInteger = new AtomicInteger(0);

    /**
     * Get current requests
     * @return
     */
    public final  int getAndIncrement(){
        int current;
        int next;
        do{
            current = this.atomicInteger.get();
            next = current >+ Integer.MAX_VALUE ? 0:current + 1;
        }while (!this.atomicInteger.compareAndSet(current,next));
        System.out.println("*********next Number of visits:"+next);
        return  next;
    }



    /**
     * Load balancing algorithm:
     *      The number of requests% (residual) the total number of service clusters = the subscript of the actual call server location, and each restart of rest starts from 1.
     * @param serviceInstances
     * @return
     */
    @Override
    public ServiceInstance serviceInstance(List<ServiceInstance> serviceInstances) {
        int index = getAndIncrement() % serviceInstances.size();
        return serviceInstances.get(index);
    }
}

controller layer code:

@GetMapping(value = "/consumer/payment/lb")
    public String getPaymentLB() {
        List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");

        if(instances == null || instances.size() <= 0) {
            return null;
        }
        ServiceInstance serviceInstance = loadBalancer.serviceInstance(instances);
        URI uri = serviceInstance.getUri();
        return restTemplate.getForObject(uri+"/payment/lb",String.class);
    }

Note that when a service here hangs up, you can also access the service, but an error will be reported.
Source code:

Service error and result:

OpenFeign


1.Feign: a declarative WebService client. Using feign makes it easier to write a Web Service client. Just create a service interface and annotate it. Feign also supports pluggable encoders and decoders. Spring Cloud encapsulates feign to support Spring MVC standard annotations and HttpMessageConverters. Feign can be used in combination with Eureka and Ribbon to support load balancing.
2.Ribbon+RestTemplate is a templated calling service (an interface is called in multiple places), while feign only needs to define the service binding interface to declare the method.
3.Feign is a declarative Web service client, which makes it very easy to write a Web service client. You only need to create an interface and add annotations on the interface
application.yml

server:
  port: 80

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

#Set feign client timeout (OpenFeign supports ribbon by default)
ribbon:
  #It refers to the time taken to establish a connection, which is applicable to the time taken to connect both ends under normal network conditions
  ReadTimeout: 5000
  #It refers to the time taken to read available resources from the server after the connection is established
  ConnectTimeout: 5000
logging:
  level:
    # At what level does feign log monitor which interface
    com.charon.springcloud.service.PaymentFeignService: debug

Main startup class:

@SpringBootApplication
@EnableFeignClients
public class OpenFeignMain80 {
    public static void main(String[] args) {
        SpringApplication.run(OpenFeignMain80.class,args);
    }
}

Feign call (Interface)

@Component
@FeignClient(value = "CLOUD-PAYMENT-SERVICE")
public interface PaymentFeignService {

    @GetMapping(value = "/payment/get/{id}")
    public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id);

    @GetMapping(value = "/payment/feign/timeout")
    public String paymentFeignTimeout();
}

4.openFeign generally defaults to 1 second and returns an error if it is not obtained. Therefore, timeout control is sometimes required.
5.OpenFeign provides the function of log printing to understand the details of Http requests in Feign. To put it bluntly, it refers to the monitoring and output of logs.
NULL: by default, the log is not displayed.
BASIC: only record the request method, url and response status code.
HEADERS: there are request and response information in addition to BASIC.
FULL: in addition to HEADERS, there is also the metadata of the request and response body.

@Configuration
public class FeignConfig {

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

Tags: Spring Cloud ribbon feign

Posted by llandudno on Sun, 01 May 2022 16:44:17 +0300