This is the sixth day of my participation in the First Challenge 2022
- Microservices: OpenFeign Performance Optimization for Service calls to Spring Cloud
At the end of this article, we mentioned the request timeout configuration in Feign. Feign has its own timeout configuration, and Feign’s default integrated Ribbon also has a timeout configuration.
If we use Hystrix for fuse downgrading, Hystrix has a timeout configuration of its own.
Note: Hystrix is integrated by default in lower versions of Spring-Cloud-starter-OpenFeign, and removed in higher versions.
All right, without further ado, let’s take a look.
Feign and Ribbon
1. Set the OpenFeign timeout period
Let’s start by looking at OpenFeign’s own request timeout configuration, directly in the YML file:
feign:
# set feign timeout
client:
config:
# default Specifies the global timeout period. You can set the timeout period for a single service by specifying the service name
default:
connectTimeout: 5000
readTimeout: 5000
Copy the code
Default The default value is global. If you change the default value to the name of a service, you can set the timeout period of a single service
2. Set the Ribbon timeout period
ribbon:
# The time used to establish the link is applicable to the time used to connect the two ends under normal network conditions
ReadTimeout: 5000
# refers to the time it takes to read the available resources from the server after the link is established
ConectTimeout: 5000
Copy the code
Note that these two parameters are set without intelligence prompt
ConnectTimeout:
It refers to the time for establishing a connection. It is applicable to the time for connecting the two ends when the network is normal. In Java, if the network condition is normal, such as HttpClient or HttpURLConnetion connection, set the parameter connectTimeout=5000. If the connection is more than 5 seconds is thrown java.net.SocketException: connetct time out.
ReadTimeout:
This is the time it takes to read the available resources from the server after the connection is established. ReadTimeout: Normally, when we make a request, we receive the result of the request, that is, the content displayed on the page, but when the network condition is poor, the content cannot be displayed on the page. In addition, when we use crawler or other automatic programs, we cannot judge whether the current network condition is good or not, so ReadTimeout is useful. By setting ReadTimeout parameter, for example: ReadTimeout = 5000, more than 5 seconds didn’t read the content, can’t believe that the reading content and throw Java.net.SocketException: read time out.
3. Source tracking
Configuration is relatively simple, next we will trace the relevant source code.
The @enableFeignClients is the first thing to go into the FeignClientsRegistrar class
Trace to the registerFeignClient method in the FeignClientsRegistrar class
Then go to the configureUsingProperties method in the FeignClientFactoryBean class
And then we end up here in feign.Request
You can see that OpenFeign’s default connectTimeout is 10 seconds and readTimeout is 60 seconds.
Let’s verify this by modifying the interface we tested and letting it sleep for five seconds
@GetMapping("/getUserInfo")
public Map<String, Object> getUserInfo(int userId){
Map<String, Object> map = new HashMap<String, Object>();
User user = new User(1."Black".26);
map.put("code".200);
map.put("data", user.toString());
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return map;
}
Copy the code
OpenFeign
Default timeout
In this case, we want to validate OpenFeign’s default timeout, so in application.yml, the feign and ribbon timeouts are not set.
Start the project called again our old interface: http://localhost:9203/test/getUserInfo? userId=2
what? Error: The connection timed out, but our code sleep 5 seconds, clearly within the timeout range, how can the connection timed out?
In fact, OpenFeign integrates the Ribbon. The Ribbon’s default connection timeout and read timeout are both 1 second. Source in the org. Springframework. Cloud. Openfeign. Ribbon. FeignLoadBalancer# the execute () method, the diagram below:
If OpenFeign does not set the Ribbon timeout, the Ribbon will use the default timeout
- Set up the
OpenFeign
timeout
feign:
client:
config:
default:
connectTimeout: 8000
readTimeout: 8000
Copy the code
Then we restart the project and access the interface again to see the breakpoint above, and find that the timeout has changed to what we configured
The interface also returns normal results:
- Set up the
Ribbon
timeout
ribbon:
ReadTimeout: 7000
ConectTimeout: 7000
Copy the code
Repeat the above step, break point to go into?? Why is it still 8000?
The reason for this is that OpenFeign and the Ribbon only have one or the other timeouts in effect, and OpenFeign takes precedence
Note out the OpenFeign timeout configuration, and this becomes the Ribbon timeout using the Settings
4. Conclusion
Both the Feign and Ribbon timeout Settings take effect. Rule: If no Feign timeout is set, the Ribbon will read the Ribbon Settings and use the Ribbon timeout and retry Settings. Otherwise, use Feign’s own Settings. Both are optional, and Feign takes precedence.
Ribbon and Hystrix
1. Hystrix sets the timeout period
# Set hystrix timeout
feign:
hystrix:
enabled: true
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 6000
Copy the code
The fallback configuration.
@FeignClient(contextId = "remoteUserService", value = "cloud-system", fallbackFactory = RemoteUserFallbackFactory.class)
Copy the code
Note: If fallback is not configured, hystrix timeouts do not take effect and are controlled by the ribbon.
Hystrix’s default timeout is 1s, configured in the HystrixCommandProperties class:
private static final Integer default_executionTimeoutInMilliseconds = 1000;
Copy the code
Hystrix timeout set hystrix timeout set hystrix timeout > Ribbon
ribbon:
ReadTimeout: 2000
ConectTimeout: 2000
Copy the code
To access the address http://localhost:9203/test/getUserInfo? UserId =2 returns the ribbon.ReadTimeout value is the ribbon. The ribbon has timed out. Then it went into the hystrix circuit breaker process.
2. Conclusion:
- If the request takes longer than the ribbon timeout Settings, retries are triggered.
- With fallback configuration, if the request time (including ribbon retry time) exceeds the Ribbon timeout limit, or Hystrix timeout limit, it will fuse.
In general, the ribbon timeout is set to < hystrix because the ribbon has a retry mechanism. This ribbon timeout includes retries, that is, it is best to allow the ribbon to perform all retries until the ribbon timeout is triggered.
Because connectionTime is generally short, it can be ignored. Then, the timeout should be set to:
(1 + MaxAutoRetries) * (1 + MaxAutoRetriesNextServer)* ReadTimeOut < Hystrix *timeoutInMillisecondsCopy the code
PS: Now that you’ve seen it, give it a thumbs up, Daniel!