The most important thing in Springcloud is the call between microservices, because network latency or call timeouts can lead to program exceptions, so configuration and processing of timeouts is critical.
In the development process is called the micro-service interrupt point Discovery will retry the situation, the test environment has a request for too long response time will also appear multiple requests, online query configuration tried without fruit, decided to look at the source.
I use the Springcloud version is CAMDEN.SR3.
Micro-service between calls actually go HTTP request, debug the default readtimeout time for 5s,connecttimeout time is 2s, I use Fegin for micro-service between the call, the bottom of the Ribbon, the network mentioned configuration is as follows
Ribbon: 60000 60000 01
The time-out is valid but the number of retries is not valid and should be valid if the Ribbon is used directly.
Start the test below:
Setting up a test method in MicroServices B, Sleep 8s ensures that the request times out
@PostMapping ("/testa") public Integer testee () { Try { thread.sleep (8000L); Catch (interruptedexception e) { e.printstacktrace (); } return 9 ; }
When you call this method using Fegin in MicroServices A, you see an exception
See the method requested in Synchronousmethodhandler
Object executeanddecode (requesttemplate template) throws Throwable {Request Request=targetrequest (template); if(LogLevel! =Logger.Level.NONE) {logger.logrequest (Metadata.configkey (), logLevel, request); } Response Response; LongStart =System.nanotime (); Try{Response=Client.execute (request, options); Response.tobuilder (). Request (Request). Build (); } Catch(IOException e) {if(LogLevel! =Logger.Level.NONE) {logger.logioexception (Metadata.configkey (), LogLevel, E, ElapsedTime (start)); } //throws Retryableexception After an exception occurs Throwerrorexecuting (Request, E); }
Calling throw errorexecuting (Request, E) throws an exception after an exception occurs
Catch in place of calling Executeanddecode
@Override PublicObject Invoke (object[] argv) throws Throwable {requesttemplate template=buildtemplatefromargs.create (argv); Retryer Retryer= This. Retryer.clone (); while(true) { Try { returnExecuteanddecode (template); } Catch(retryableexception e) {//Place to retryretryer.continueorpropagate (e); if(LogLevel! =Logger.Level.NONE) {logger.logretry (Metadata.configkey (), logLevel); } Continue; } } }
Retryer.continueorpropagate (e); This is the key to follow up.
Public void continueorpropagate (retryableexception e) { ///maxattempts is a construction method that passes in more than the number of retries throws an exception, Otherwise continue the loop execution request if (attempt++ >= maxattempts) {throw e; }
The default Retryer constructor
Public Default () { this (1, seconds.tomillis (5); }
The first parameter, period, is the interval algorithm parameter for the request retry, the second parameter maxperiod is the maximum time for the request interval, and the third parameter is the number of retries. The algorithm is as follows:
Long Nextmaxinterval () { long interval = (long) (Period * MATH.POW (1.51 )); return interval > maxperiod? maxperiod:interval; }
Create a new configuration class
@Configuration Public class feginconfig { @Bean public retryer feginretryer () { new Retryer.default (seconds.tomillis (3); return Retryer;} }
The configuration is added to the feginclient
" Fund-server ", fallback = Fundclienthystrix. class, configuration = Feginconfig. class )publicinterface fundclient
Reboot retry, call only once, Fegin retry number resolved.
Let's take a look at the request timeout parameter here
@Override PublicResponse Execute (Request request, Request.options Options) throws IOException {Try{URI Asuri=uri.create (Request.url ()); String ClientName=Asuri.gethost (); URI Uriwithouthost=Cleanurl (Request.url (), clientName); Feignloadbalancer.ribbonrequest ribbonrequest=NewFeignloadbalancer.ribbonrequest ( This.Delegate, request, uriwithouthost); //Request ParametersIclientconfig Requestconfig =getclientconfig (options, clientName); returnlbclient (clientName). Executewithloadbalancer (Ribbonrequest, Requestconfig). Toresponse (); } Catch(clientexception e) {IOException io=findioexception (e); if(IO! =NULL) { Throwio; } Throw NewRuntimeException (e); } }
where ReadTimeout and ConnectTimeout read the Ribbon configuration, take a look
Ribbon: 60000 60000 01
If you want to override the Ribbon's timeout setting, you can inject the following bean in the feginconfig you just wrote
@Bean Public request.options feginoption () { new request.options (7000,7000); return option; }
Summary: The use of open source things in the unclear problem where the best to look at the source code, the principle of implementation and their own coding ideas have a great improvement.
http://www.jianshu.com/p/767f3c72b547
Springcloud fegin Timeout Retry source