This is the second day of my participation in the August More text Challenge. For details, see:August is more challenging

Reading reminder:

  1. This article is intended for those with some springBoot background
  2. The Hoxton RELEASE of Spring Cloud is used in this tutorial
  3. This article relies on the project from the previous article, so check out the previous article for a seamless connection, or download the source directly: github.com/WinterChenS…

Before a summary

  • The beginning of the SpringCloud series (part 1)
  • Nacos of SpringCloud series (2) | August more article challenges (juejin. Cn)

This paper gives an overview of

  • What is RPC?
  • How does Spring Cloud integrate With OpenFeign
  • How can I use the Ribbon and Hystrix to perform load balancing and service circuit breaker
  • Actual application scenarios

The last article showed how Spring Cloud integrates Nacos as a configuration hub and registry. Here’s how

Open Feign makes remote service calls. Before we can talk about OpenFeign we need to understand the basic concepts of RPC.

The source address for the demo used in this article: github.com/WinterChenS…

What is RPC?

In distributed computing, Remote Procedure Call (RPC for short) is a computer communication protocol. This protocol allows a program running on one computer to call a subroutine in another address space (usually a computer on an open network) without the programmer having to program for this interaction as if it were a native program (no attention to detail). RPC is a type of Server/Client (Client/Server) pattern. The classic implementation is a system that sends request and receives response for information interaction.

A remote procedure call is also called a remote call or a remote method call if the software involved is object-oriented, such as Java RMI. RPC is a mode of interprocess communication in which programs are distributed in different address Spaces. In the same host, RPCS can communicate through different virtual address Spaces (even if the same physical address is used), while in different hosts, RPCS can communicate through different physical addresses. Many (often incompatible) technologies are based on this concept. — Quoting from Wikipedia

What is the relationship between Feign and RPC? Why do people think that Feign is pseudo RPC?

In fact, Feign implements RPC, which can be used to call remote services by calling local methods. The two key protocols for RPC are:

  1. Communication protocol
  2. Serialization protocol

Common RPC frameworks include Open FeIGN and Dubbo. Feign is based on HTTP protocol, and Dubbo is based on TCP protocol.

How Feign works:

Feign integrates two important modules: the ribbon, Hystrix for load balancing and service fusing, and the Ribbon has RestTemplate built in. RestTemplate is based on HTTP, so FEIGN is based on HTTP.

Feign templates the Request by processing the annotations. When the actual call is made, the parameters are passed in, which are then applied to the Request to turn it into a real Request. With Feign and JAVA’s dynamic proxy mechanism, JAVA developers can make HTTP calls to remote services without using the HTTP framework to encapsulate HTTP request messages.

Spring Cloud integrates with Feign

Based on the Nacos we used as the code base in the previous article, we integrated Feign on top of it, so check out the previous article for a seamless connection.

Spring – the cloud – nacos – the provider to modify:

Add dependencies to the spring-cloud-nacos-Provider project:

<! -- springCloud-feign -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
Copy the code

@feignClient (value = “winter-nacos-provider”)

@FeignClient(value = "winter-nacos-provider")
public interface NacosProviderClient {

    @GetMapping("/nacos/feign-test/{string}")
    String echo2(@PathVariable String string);

}
Copy the code

Class: NacosController add method:

@GetMapping("feign-test/{string}")
public String feignTest(@PathVariable String string) {
    return "Hello feign " + string;
}
Copy the code

Spring – the cloud – nacos – consumer changes:

Add dependencies to the spring-cloud-nacos-Consumer project:

<! -- springCloud-feign -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<! -- Dependencies on service Providers -->
<dependency>
    <groupId>com.winterchen</groupId>
    <artifactId>spring-cloud-nacos-provider</artifactId>
    <version>0.0.1 - the SNAPSHOT</version>
</dependency>
Copy the code

Add an annotation to the startup class NacosConsumerApplication: @enableFeignClients

@EnableDiscoveryClient
@EnableFeignClients
@SpringBootApplication
public class NacosConsumerApplication {

    @LoadBalanced
    @Bean
    public RestTemplate restTemplate(a) {
        return new RestTemplate();
    }

    public static void main(String[] args) { SpringApplication.run(NacosConsumerApplication.class, args); }}Copy the code

Add methods to class: NacosController:


@Autowired
private NacosProviderClient nacosProviderClient;

@GetMapping("/feign-test/{str}")
public String feignTest(@PathVariable String str) {
    return nacosProviderClient.echo2(str);
}
Copy the code

Testing:

  1. Start the two services in turn;
  2. The browser input: http://127.0.0.1:16011/nacos/feign-test/hello
  3. Return: Hello feign Hello to indicate success

Use the Ribbon

Feign has built-in ribbon for service load balancing, so simply introducing Feign’s dependencies will automatically use load balancing. Let’s try service load balancing:

Spring – the cloud – nacos – the provider to modify:

NacosController adds new methods and parameters:

		@Value("${server.port}")
    String port;

		@GetMapping("/ribbon-test")
    public String ribbonTest(a) {
        return "Hello ribbon , my port: " + port;
    }
Copy the code

NacosProviderClient adds interfaces:

		@GetMapping("/nacos/ribbon-test")
    String ribbonTest(a);
Copy the code

To test the load of the service, the Provider service does not use the configuration center configuration. Delete the configuration center configuration and create the application.yml configuration file as follows:

server:
  port: 16012

spring:
  cloud:
    nacos:
      discovery:
        server-addr: 118.2536.. 41: 8848

test:
  config:
    refresh: false
Copy the code

Spring – the cloud – nacos – consumer changes

NacosController new method:

@GetMapping("/ribbon-test")
    public String ribbonTest1(a) {
        return nacosProviderClient.ribbonTest();
    }
Copy the code

Testing:

Before the test, you need to modify the configuration of IDEA. After the red box is selected, the service can start multiple nodes

Start the two services in turn, and then modify the port configuration of Spring-cloud-nacos-Provider

server:
  port: 16013
Copy the code

Then start the Spring-cloud-nacos-Provider service again. After starting the service, there are two nodes

Then call: http://127.0.0.1:16011/nacos/ribbon-test

You can see that requests are called in turn:

Hello ribbon . my port: 16012
Hello ribbon . my port: 16013
Copy the code

This enables load balancing of services.

The configuration of Ribbon

You can configure the Ribbon parameters for more control. A brief introduction to the Ribbon configurations can be added to the Consumer Project configuration file:

feign:
  client:
    config:
      winter-nacos-consumer:
        connectTimeout: 12000000
        readTimeout: 12000000
        NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
        OkToRetryOnAllOperations: true
        MaxAutoRetriesNextServer: 2
        MaxAutoRetries: 1
Copy the code
Ms ConnectTimeout: # unit, request connection timeout ReadTimeout: ms # unit, request processing timeout OkToRetryOnAllOperations: # for all operation request retry MaxAutoRetriesNextServer: # switch case retries MaxAutoRetries: # # to the current instance of retries NFLoadBalancerRuleClassName configuration Ribbon load balancing rules: IRuleCopy the code

Hystrix use

In addition to the Ribbon mentioned above, Feign also integrates Hystrix as a service circuit breaker. Why do services need to be circuit breaker? The reason is that once the underlying services are unavailable due to timeout or exceptions, no circuit breaker mechanism will lead to the breakdown of the entire service cluster. Therefore, in the microservice architecture, the circuit breaker of services is very important.

Spring – the cloud – nacos – the provider to modify:

NacosController new method:

		@GetMapping("/hystrix-test")
    public String hystrixTest(a) {
        throw new RuntimeException("ex");
    }
Copy the code

New class NacosProviderClientFallback NacosProviderClient and implement interface:

@Component
public class NacosProviderClientFallback implements NacosProviderClient{
    @Override
    public String echo2(String string) {
        return "error";
    }

    @Override
    public String ribbonTest(a) {
        return "error";
    }

    @GetMapping("/hystrix-test")
    public String hystrixTest(a) {
        return "hystrix error"; }}Copy the code

Change the NacosProviderClient to add a new method and the @feignClient annotation to add the fallback parameter, which is the class that degrades the service and the implementation method of this class will be called when the service is unavailable.

@FeignClient(value = "winter-nacos-provider", fallback = NacosProviderClientFallback.class)
public interface NacosProviderClient {

    @GetMapping("/nacos/feign-test/{string}")
    String echo2(@PathVariable String string);

    @GetMapping("/nacos/ribbon-test")
    String ribbonTest(a);

    @GetMapping("/nacos/hystrix-test")
    String hystrixTest(a);

}
Copy the code

Spring – the cloud – nacos – consumer changes

Add configuration:

feign:
  client:
    config:
      winter-nacos-consumer:
        connectTimeout: 12000000
        readTimeout: 12000000
        NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
        OkToRetryOnAllOperations: true
        MaxAutoRetriesNextServer: 2
        MaxAutoRetries: 1
  hystrix:
    enabled: true # enable hystrix

hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 20000 # Default timeout
    winter-nacos-consumer:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 20000 # Specifies the timeout period for the current service
Copy the code

The annotations are new. If you want to specify a service, you can specify the service name instead of default, as shown above.

test

Start two service respectively, and then call: http://127.0.0.1:16011/nacos/hystrix-test

The response returned: Hystrix error

Extension: Hystrix configuration

Thread Pool Configuration

Name note The default value
hystrix.threadpool.default.coreSize Thread pool size 10
hystrix.threadpool.default.maximumSize Maximum size of a thread pool 10
hystrix.threadpool.default.allowMaximumSizeToDivergeFromCoreSize The default value is false. MaximumSize is valid only if it is set to true FALSE
hystrix.threadpool.default.keepAliveTimeMinutes Threads that exceed coreSize will be idle for 1 minute before being released 1
hystrix.threadpool.default.maxQueueSize Cannot be dynamically modified – 1
hystrix.threadpool.default.queueSizeRejectionThreshold This can be changed dynamically, but the default is 5. The request is queued and then executed by the thread pool 5

How do I count the number of thread pools?

Peak number of requests per second / 1000 ms/TP99 request latency + Buffer space

For example, if it takes 50ms to process a request, then TP99, which is 99% of the requests, will take up to 50ms to process a request.

We give a little buffer space of 10ms, which means that the processing of the request interface takes 60ms.

So one thread per second can process: 1000/60 = 16, one thread can process 16 requests per second.

Assuming a peak of 1200 requests per second, and one thread can handle 16 requests per second, how many threads does it take to handle 1200 requests per second? 1200/16 = 75, it takes up to 75 threads to process 16 requests per second, 75 threads to process 1200 requests per second.

The maximum number of threads you need is calculated in this way

If service B -> service A, how to set the number of service B threads?

How many threads does service B need to invoke service A’s thread pool?

In the peak period, service B calls service A 1200 times per second at most, and service A processes A request for 60ms. When service B invokes service A every time, A thread initiates A request, so it takes 60ms for this thread of service B to return.

Service B, A thread to service A initiate A request to 60 ms, A thread can request services A reached 16 per second, but now the service B need to request A service of 1200 per second, so service B requires 75 threads, A service at peak concurrent requests, can complete 1200 times A second call.

If service B is deployed on multiple machines, each machine can invoke service A with A thread pool of 10 threads. For example, if service B is deployed on 10 threads and 10 machines are deployed, then the number of threads that service B can invoke service A is 100, which can easily support the scenario that service A is invoked 1200 times at peak

Each thread can call service A once, taking 60ms, each thread can call service A A total of 16 times per second, 100 threads, service A can be called 1600 times per second, at the peak of 1200 times can support service A, so the machine deployment is more than enough

Perform the configuration

Name note The default value
hystrix.command.default.execution.isolation.strategy The isolation policy is Thread by default. Semaphore can be selected Thread
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds timeout 1000ms
hystrix.command.default.execution.timeout.enabled Whether to enable timeout TRUE
hystrix.command.default.execution.isolation.thread.interruptOnTimeout Whether to interrupt the execution when the timeout occurs TRUE
hystrix.command.default.execution.isolation.semaphore.maxConcurrentRequests Maximum number of concurrent requests allowed under the semaphore isolation policy 10

Demotion configuration

Name note The default value
hystrix.command.default.fallback.enabled Whether to enable demotion TRUE

Fusing configuration

Name note The default value
hystrix.command.default.circuitBreaker.enabled Whether to enable the fuse TRUE
hystrix.command.default.circuitBreaker.requestVolumeThreshold What is the number of requests in 10 seconds to try to trigger the circuit breaker 20
hystrix.command.default.circuitBreaker.errorThresholdPercentage If the number of requests reaches 20 within 10 seconds and the abnormal percentage reaches 50%, the circuit breaker is triggered 50
hystrix.command.default.circuitBreaker.sleepWindowInMilliseconds After the circuit breaker is triggered, the request is directly rejected within 5 seconds and the downgrade logic is adopted. After 5 seconds, the half-open is tried to pass a small amount of traffic and try to recover 5000
hystrix.command.default.circuitBreaker.forceOpen Force open fuse
hystrix.command.default.circuitBreaker.forceClosed Force the fuse to close

Monitoring configuration

Name note The default value
hystrix.threadpool.default.metrics.rollingStats.timeInMillisecond Time of the thread pool statistics indicator The default is 10000, which is 10s
hystrix.threadpool.default.metrics.rollingStats.numBuckets We divided the rolling window into n buckets 10
hystrix.command.default.metrics.rollingStats.timeInMilliseconds Command statistics time. Whether the fuse is open is calculated according to the statistics of one Rolling window. If the Rolling Window is set to 10000 ms, then the Rolling Window is divided into n buckets, each bucket containing statistics on the number of success, failure, timeout, rejection. 10000
hystrix.command.default.metrics.rollingStats.numBuckets To set the number of rolling Windows to be divided, if numBuckets = 10 and rolling window = 10000, then a bucket is one second. Must meet rolling Window % numberBuckets == 0 10
hystrix.command.default.metrics.rollingPercentile.enabled Whether to enable indicator calculation and tracking during execution TRUE
hystrix.command.default.metrics.rollingPercentile.timeInMilliseconds Set the time of the Rolling Percentile window 60000
hystrix.command.default.metrics.rollingPercentile.numBuckets Set the numberBuckets of the Rolling Percentile Window. Same logic as above. 6
hystrix.command.default.metrics.rollingPercentile.bucketSize If bucket size = 100 and window = 10s, if there are 500 executions in 10s, only the last 100 executions will be counted to the bucket. Increasing this value increases the memory overhead as well as the sorting overhead. 100
hystrix.command.default.metrics.healthSnapshot.intervalInMilliseconds Record the intervals between health snapshots (used to count success and error green) 500ms

Configure higher-order features

Name note The default value
hystrix.command.default.requestCache.enabled Whether to enable request caching TRUE
hystrix.command.default.requestLog.enabled Log to HystrixRequestLog TRUE
hystrix.collapser.default.maxRequestsInBatch Maximum number of requests to be processed in a single batch. When this number is reached, batch processing is triggered Integer.MAX_VALUE
hystrix.collapser.default.timerDelayInMilliseconds The delay that triggers the batch, which can also be the time to create the batch + this value 10
hystrix.collapser.default.requestCache.enabled Whether to say hystrixcollapser.execute () and hystrixcollapser.queue () in the cache TRUE

How Feign and Hystrix combine

When Feign integrates with Hystrix, the Feign dynamic proxy has some Hystrix related code. When a request is sent through the Feign dynamic proxy, the request will be sent based on the Hystrix Command, which will implement the isolation, traffic limiting, timeout, degrade, circuit break, statistics, etc.

conclusion

In this paper, springcloud integrates feign to achieve remote service invocation, and uses feign’s Ribbon and Hystrix to achieve load balancing and service circuit breaker, as well as a deep understanding of service load balancing and circuit breaker and some configuration in actual use. The next article will cover SpringCloud Gateway, a microservices Gateway.

The source address

Github.com/WinterChenS…

Reference documents:

Spring Cloud OpenFeign

A combination of Feign and Hystrix