Spring Cloud-Ribbon load balancing & Feign declarative service call

Table of contents

1. Ribbon load balancing

        1.1 What is load balancing

         1.2 Custom implementation of load balancing

       1.3 Ribbon Introduction

        1.4 Load balancing based on ribbon

       1.5 Ribbon problems

2. Declarative service calls Feign

        2.1 Background

        2.2 Overview of Feign

         2.3 Feign Getting Started Program

         2.4 Overview of feign principle

        2.5 Three methods of feign interface parameter passing

         2.6 OpenFeign performance optimization

          1. Log enhancement

         2. http connection pool

         3. gzip compression

         4. feign timeout processing


1. Ribbon load balancing

 

        1.1 What is load balancing

        In layman's terms, load balancing is to distribute the load (work tasks, access requests) to multiple operating units (servers, components) for execution.

         1.2 Custom implementation of load balancing

          1.2.1 Create two service providers provider

           

           1.2.2 The configuration file application.yml sets different port numbers

#ribbon_provider_1
server:
  port: 9090
spring:
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.57.132 #nacos服务的地址
  application:
    name: ribbon-provider #向注册中心注册的名字

#ribbon_provider_2
server:
  port: 9091
spring:
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.57.132 #nacos服务的地址
  application:
    name: ribbon-provider #向注册中心注册的名字

         1.2.3 Create a service consumer consumer

        1.2.4 configuration file application.yml

server:
  port: 80
spring:
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.57.132 #nacos服务的地址
  application:
    name: ribbon-consumer #向注册中心注册的名字

           1.2.5 controller     

@RestController
@RequestMapping(value = "/consumer")
public class ConsumerController {
	
	//发送Rest请求的工具类
	@Autowired
	private RestTemplate restTemplate;
	//发现服务的工具类
	@Autowired
	private DiscoveryClient discoveryClient;

	private int index;

	@RequestMapping("/getService/{id}")
	public User getServic(@PathVariable Integer id){
		//获取所有服务
		List<String> serviceList = discoveryClient.getServices();
		//随机方式获得服务
		//int currentIndex = new Random().nextInt(serviceList.size());
		//轮询方式获得服务
		index=index + 1;
		int currentIndex = (index) % serviceList.size();

		ServiceInstance serviceInstance = discoveryClient.getInstances("ribbon-provider").get(currentIndex);
		String url = "http://"+serviceInstance.getHost()+":"+serviceInstance.getPort()+"/provider/getUserById/"+id;
		return restTemplate.getForObject(url, User.class);

	}
}

//RestTemplate工具类
@Configuration
public class ConfigBean {
	@Bean
	public RestTemplate restTemplate(){
		return new RestTemplate();
	}
}

        1.2.6 Test: Call the service provider using polling and random strategies respectively

       1.3 Ribbon Introduction

        1.3.1 What is Ribbon

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

        We don't need to introduce ribbon dependencies, because ribbon dependencies have been integrated in nacos  

        Ribbon provides many load balancing algorithms by default, such as round robin, random and so on.

        1.3.2 Load Balancing Strategy

        Load balancing interface:com.netflix.loadbalancer.IRule

        1.3.2 Random strategy 

Ribbon has 7 built-in load balancing strategies by default:

1、RoundRobinRule

  Polling strategy , the strategy adopted by Rabbon by default , if no available provider (provider) is found after one round of polling, it will poll up to 10 rounds, if finally

      If not found, NULL is returned.

      Example: There are currently 3 providers A, B, and C, first poll one by one, A, B, and C do not visit (1 round), visit A, B, and C once (2 rounds), try in total 10 rounds

                Returns NULL if not yet accessible.

2、RandomRule

  Random strategy, choose one from all available providers.

3、RetryRule

  Retry strategy, first obtain the provider (strategist) according to the RoundRobinRule strategy to get a direct return, if the acquisition fails, retry within the specified time limit,

       The default timeout is 500 milliseconds. [RoundRobinRule polling strategy, the default is 10 rounds, and RetryRule I will give you 500 milliseconds, you can keep retrying until you find it]

4、BestAvailableRule

  most available strategy. Choose the provider (provider) with the least amount of concurrency, that is, the provider with the least number of connected consumers.

5、AvailabilityFilteringRule

  Available filtering algorithms. The algorithm rules are: filter out providers in the fuse state and providers that have exceeded the connection limit, and use a polling strategy for the remaining providers.

6、ZoneAvoidanceRule

  zone avoidance strategy. Select the provider according to the zone where the provider is located and the availability of the provider.

7、WeightedResponseTimeRule

  "Weight Response Time" policy. The weight of each provider is calculated according to the average response time. The faster the response time, the greater the weight, and the higher the probability of being selected. 

     A round-robin strategy is used at startup. It will be selected according to the weight later.

        1.4 Load balancing based on ribbon

         1.4.1 ConfigBean

@Configuration
public class ConfigBean {

	@Bean
	/**
	 * 添加了@LoadBalanced注解之后,Ribbon会给restTemplate请求添加一个拦截器,在拦截器中获取
	 * 注册中心的服务列表,并使用Ribbon内置的负载均衡算法从服务列表里选中一个服务,通过获取到的服务信息        * (ip,port)替换 serviceId 实现负载请求。
	 */
	@LoadBalanced //开启负载均衡
	public RestTemplate getRestTemplate(){
		return new RestTemplate();
	}

	//随机策略
	@Bean
	public IRule iRule() {
		return new RandomRule();
	}
}

        1.4.2 Controller

@RestController
@RequestMapping(value = "/consumer")
public class ConsumerController {
	
	//发送Rest请求的工具类
	@Autowired
	private RestTemplate restTemplate;

    @RequestMapping("/get/{id}")
	public User getUser(@PathVariable Integer id){
        //ribbon-provider为服务要访问的名字即可,Ribbon会把服务名替换成ip和端口号
		String url = "http://ribbon-provider/provider/getUserById/"+id;
		return restTemplate.getForObject(url,User.class);
	}
}

        1.4.3 Testing 

        Invoke service providers using polling and random strategies respectively

       1.5 Ribbon problems

         ① It is troublesome to splice url and parameters

         ②Dead services cannot be removed by default (if one of the services is down, the browser will fail to access)

2. Declarative service calls Feign

        2.1 Background

        When we call the API of other services through RestTemplate, the required parameters must be spliced ​​in the URL of the request. If there are few parameters, maybe we can bear it. Once there are multiple parameters, then splicing the request string will be more efficient. Low and looking so silly .

So is there a better solution? The answer is yes, Netflix has provided us with a framework: Feign.

        2.2 Overview of Feign

        Feign is a declarative, templated HTTP client provided by Spring Cloud. It makes calling remote services as easy as calling local services. You only need to create an interface and add an annotation.

        Spring Cloud integrates Feign and enhances it, so that Feign supports Spring MVC annotations; Feign integrates Ribbon by default, so Fegin achieves the effect of load balancing by default.

         2.3 Feign Getting Started Program

          2.3.1 Create a service provider

           application.yml

server:
  port: 9090
spring:
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.57.132:8848 #nacos服务的地址
  application:
    name: feign-provider #向注册中心注册的名字

           Create controller and service

//controller
@RestController
@RequestMapping("/provider")
public class ProviderController {
    @Autowired
    private UserService userService;

    @RequestMapping("/getUserById")
    public User getUserById(@RequestParam("id") Integer id){
        return userService.getUserById(id);
    }
}
//servic接口
public interface UserService {
    User getUserById(Integer id);
}
//UserService 实现类
@Service
public class UserServiceImpl implements UserService {

    @Override
    public User getUserById(Integer id) {
        return new User(id,"彭于晏-1",23);
    }
}

        2.3.2 Create feign interface

         pom.xml dependencies

    <dependencies>
        <!--Spring Cloud OpenFeign Starter -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <dependency>
            <groupId>com.bjpowernode</groupId>
            <artifactId>springcloud_common</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>

        create interface

@FeignClient(value = "feign-provider")//value属性写服务名字
@RequestMapping("/provider")//对应提供者的requestmapping
public interface UserFeign {
    @RequestMapping("/getUserById")
    User getUserById(@RequestParam("id") Integer id);
}

         2.3.3 Create a consumer

 <dependencies>
        <!--nacos客户端-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--引入feign接口-->
        <dependency>
            <groupId>com.bjpowernode</groupId>
            <artifactId>feign_interface</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
</dependencies>

        Add the @EnableFeignClients annotation to the launcher to scan the feign interface

        Call the feign interface in the controller 

 

         test

         2.4 Overview of feign principle

         1. Scan the proxy class of the feign interface into the Spring container :
        @EnableFeignClients enables feign annotation scanning: FeignClientsRegistrar.registerFeignClients() scans the interface marked by @FeignClient to generate a proxy class,
        and hands the interface and proxy class to Spring’s container management.
          2. Create a RequestTemplate
for the method of the interface         . When the consumer calls the feign proxy class, the proxy class will call SynchronousMethodHandler.invoke() to create a RequestTemplate (url, parameter)
          3. Sending a request
        proxy class will create a Request through the RequestTemplate , and then the client (URLConnetct, HttpClient , OkHttp) use Request to send the request

        2.5 Three methods of feign interface parameter passing

        1. Path splicing? To pass parameters, add the @RequestParam ("id") annotation before the parameters :

        2. For restful parameter passing, add the @PathVariable("id") annotation before the parameter:

        3. For pojo, add the @RequestBody annotation before the parameters:

         2.6 OpenFeign performance optimization

         1. Log enhancement

        OpenFeign Although the log enhancement function is provided, no logs are displayed by default, but developers can configure the log level by themselves during the debugging phase.

        OpenFeign The log levels are as follows:

  • NONE : default, do not display any logs;
  • BASIC : Only record the request method, URL, response status code and execution time;
  • HEADERS : In addition to the information defined in BASIC, there are request and response header information;
  • FULL : In addition to the information defined in HEADERS, there are request and response body and metadata.

        1.1. The configuration file application.yml is set to enable the log:

 

#com.bjpowernode.feign包下接口的日志级别
logging:
  level:
    com.bjpowernode.feign: debug


#OpenFeign 的日志级别
feign:
  client:
    config:
      default:#此处写服务名字或default默认的
        loggerLevel: full

         The log effect printed by the console

         1.2. Configure the OpenFeign log level in the configuration class

        Customize a configuration class and set the log level in it, which is a global configuration


@Configuration
public class FeignConfiguration {
    @Bean
    Logger.Level feignLoggerLevel(){
        return Logger.Level.FULL;
    }
}

         Local configuration, specify this configuration in the client interface

configuration = FeignConfiguration.class

 

@FeignClient(value = "feign-provider", fallbackFactory = RemoteUserFallbackFactory.class, configuration = FeignConfiguration.class)
public interface UserFeign{
 
    @RequestMapping("/getUserById")
    User getUserById(@RequestParam("id") Integer id);

}

         2. http connection pool

        The process of establishing an HTTP connection between two servers involves the exchange of multiple data packets, which is time-consuming. Using HTTP connection pooling can save a lot of time prompt throughput.

Feign's HTTP client supports 3 frameworks: HttpURLConnection , HttpClient , OkHttp .

        Observing the source code, we can find that Feign uses java.net.HttpURLConnection by default, and each request will establish and close the connection.

        2.1. Add dependencies to the feign interface project

<dependency>
    <groupId>io.github.openfeign</groupId>
    <artifactId>feign-httpclient</artifactId>
</dependency>

         2.2, Open in the configuration file

feign:
  # 开启 httpclient
  httpclient:
    enabled: true

        2.3. How to verify whether it is enabled?

        In feign.SynchronousMethodHandler#executeAndDecode()this method, it can be clearly seen which client is called.
        It was like this before it was turned on:

        After opening:

         3. gzip compression

        introduce

        gzip is a data format that uses the deflate algorithm to compress data; gzip is a popular file compression algorithm that is widely used, especially on the Linux platform.

        ability

        When Gzip compressing to a plain text file, the effect is very noticeable, about 70%+ file size reduction. 

        effect: 

        After the network data is compressed, the number of bytes transmitted by the network is actually reduced, which can speed up the loading of web pages and improve the user experience

        Enable gzip compression in the consumer configuration file

server:
  compression:
    enabled: true #开启gzip压缩

 

         4. feign timeout processing

         When accessing a web page, it often occurs that the network is not good and the access times out. If the network timeout processing is not set in the background, and the timeout is one second and the log output is not set, the background will throw such an exception:

         In the configuration file of the consumer, it can be set like this:

1、方式一:全局的处理
ribbon:
  ConnectTimeout: 5000 #请求连接的超时时间
  ReadTimeout: 5000 #请求处理的超时时间

2、方式二:
  feign:
    client:
      config:
        feign-provider:#这里可以写服务名,或者default默认的,全局的处理
          ConnectTimeout: 5000 #请求连接的超时时间
          ReadTimeout: 5000 #请求处理的超时时间

        Through the above settings, you can perform timeout processing! ! !

Guess you like

Origin blog.csdn.net/m0_71560190/article/details/126352625