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
  • OpenFeignDefault 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 theOpenFeigntimeout
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 theRibbontimeout
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!