This is the second day of my participation in the August More text Challenge. For details, see:August is more challenging
Reading reminder:
- This article is intended for those with some springBoot background
- The Hoxton RELEASE of Spring Cloud is used in this tutorial
- 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:
- Communication protocol
- 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:
- Start the two services in turn;
- The browser input: http://127.0.0.1:16011/nacos/feign-test/hello
- 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