ZuulProxy терпит неудачу с "время ожидания RibbonCommand и отсутствие резервного копирования", когда он должен выполнить переход на другой ресурс

Краткое описание: Я пытаюсь получить ZuulProxy для обработки отказа экземпляра экземпляра, но он вызывает ошибку ZuulException: Ошибка пересылки вместо ответа на результат из рабочего экземпляра.

Длинное описание: Моя настройка - это один автономный сервер Eureka, один ConfigServer, один ZuulProxy (@EnableZuulProxy) и два экземпляра службы, все они зарегистрированы в Eureka.

Все работает с spring -cloud-starter-parent Angel.SR3

My servicediscovery:

@SpringBootApplication
@EnableEurekaServer
public class EurekaServer {
    public static void main(String[] args) {
        SpringApplication.run(EurekaServer.class, args);
    }
}

Мой ConfigServer:

@SpringBootApplication
@EnableAutoConfiguration
@EnableConfigServer
@ComponentScan
@EnableDiscoveryClient
public class ConfigserverApplication {

  public static void main(String[] args) {
    SpringApplication.run(ConfigserverApplication.class, args);
  }
}

Мой ZuulProxy:

@SpringBootApplication
@EnableAutoConfiguration
@ComponentScan
@EnableDiscoveryClient
@EnableZuulProxy
public class ZuulProxy {
  public static void main(String[] args) {
    SpringApplication.run(ZuulProxy.class, args);
  }
}

правила маршрутизации в zuul:

zuul.ignoredServices=*
zuul.routes.examplems=/example/**

Мои экземпляры службы:

@SpringBootApplication
@Configuration
@EnableAutoConfiguration
@EnableDiscoveryClient
@ComponentScan(basePackages = "se.example.microservices")
@EnableSwagger
public class Application {

  public static void main(String[] args) throws Exception{
    SpringApplication.run(Application.class, args);
  }

Мои экземпляры службы регистрируются с помощью spring.application.name=examplems

Все работает нормально, когда я запускаю два экземпляра службы и запускаю запросы через zuulproxy, он округляет запросы к моим двум экземплярам службы. Но когда я останавливаю один из экземпляров, Zuul по-прежнему пытается перенаправить запрос на остановленный экземпляр несколько раз, а затем он терпит неудачу с:

com.netflix.zuul.exception.ZuulException: Forwarding error
Caused by: com.netflix.hystrix.exception.HystrixRuntimeException: examplemsRibbonCommand timed-out and no fallback available.

Я ожидал, что запрос остановленного экземпляра истечет тайм-аут и явным образом перейдем к запущенному экземпляру. Очень странно, что, похоже, zuul (согласно журналам) сначала пытается с остановленным экземпляром несколько раз (что, конечно, не работает), а затем пересылает запрос на рабочий экземпляр, получает ответ "ОК", но вместо пересылки OK ответ клиенту, он генерирует исключение, что приводит к неудачному ответу со статусом 500!?

Смотрите журналы (мой рабочий экземпляр находится на хосте PMD11286, а мой остановленный экземпляр находится на PMD11933):

2015-08-20 08:45:46.343  INFO 7700 --- [nio-9050-exec-9] o.s.c.n.zuul.filters.ProxyRouteLocator   : Finding route for path: /example/ping/delay
2015-08-20 08:45:46.343 DEBUG 7700 --- [nio-9050-exec-9] o.a.h.impl.conn.DefaultClientConnection  : Connection 0.0.0.0:50251<->172.20.120.39:9060 closed
2015-08-20 08:45:46.343 DEBUG 7700 --- [nio-9050-exec-9] .a.h.i.c.DefaultClientConnectionOperator : Connecting to PMD11933:9060
2015-08-20 08:45:47.372 DEBUG 7700 --- [nio-9050-exec-9] .a.h.i.c.DefaultClientConnectionOperator : Connect to PMD11933:9060 timed out. Connection will be retried using another IP address
2015-08-20 08:45:47.372 DEBUG 7700 --- [nio-9050-exec-9] .a.h.i.c.DefaultClientConnectionOperator : Connecting to PMD11933:9060
2015-08-20 08:45:48.386 DEBUG 7700 --- [nio-9050-exec-9] .a.h.i.c.DefaultClientConnectionOperator : Connect to PMD11933:9060 timed out. Connection will be retried using another IP address
2015-08-20 08:45:48.386 DEBUG 7700 --- [nio-9050-exec-9] .a.h.i.c.DefaultClientConnectionOperator : Connecting to PMD11933:9060
2015-08-20 08:45:49.416 DEBUG 7700 --- [nio-9050-exec-9] .a.h.i.c.DefaultClientConnectionOperator : Connect to PMD11933:9060 timed out. Connection will be retried using another IP address
2015-08-20 08:45:49.416 DEBUG 7700 --- [nio-9050-exec-9] .a.h.i.c.DefaultClientConnectionOperator : Connecting to PMD11933:9060
2015-08-20 08:45:50.430 DEBUG 7700 --- [N_MANAGER_TIMER] o.a.h.i.c.t.ThreadSafeClientConnManager  : Closing expired connections
2015-08-20 08:45:50.430 DEBUG 7700 --- [N_MANAGER_TIMER] o.a.h.impl.conn.tsccm.ConnPoolByRoute    : Closing expired connections
2015-08-20 08:45:50.446 DEBUG 7700 --- [nio-9050-exec-9] .a.h.i.c.DefaultClientConnectionOperator : Connect to PMD11933:9060 timed out. Connection will be retried using another IP address
2015-08-20 08:45:50.446 DEBUG 7700 --- [nio-9050-exec-9] .a.h.i.c.DefaultClientConnectionOperator : Connecting to PMD11933:9060
2015-08-20 08:45:51.475 DEBUG 7700 --- [nio-9050-exec-9] .a.h.i.c.DefaultClientConnectionOperator : Connect to PMD11933:9060 timed out. Connection will be retried using another IP address
2015-08-20 08:45:51.475 DEBUG 7700 --- [nio-9050-exec-9] .a.h.i.c.DefaultClientConnectionOperator : Connecting to PMD11933:9060
2015-08-20 08:45:52.505 DEBUG 7700 --- [nio-9050-exec-9] o.a.h.impl.conn.DefaultClientConnection  : Connection 0.0.0.0:50251<->172.20.120.39:9060 closed
2015-08-20 08:45:52.505 DEBUG 7700 --- [nio-9050-exec-9] o.a.h.impl.conn.DefaultClientConnection  : Connection 0.0.0.0:50251<->172.20.120.39:9060 shut down
2015-08-20 08:45:52.505 DEBUG 7700 --- [nio-9050-exec-9] o.a.h.impl.conn.DefaultClientConnection  : Connection 0.0.0.0:50251<->172.20.120.39:9060 closed
2015-08-20 08:45:52.520 DEBUG 7700 --- [nio-9050-exec-9] o.a.h.client.protocol.RequestAddCookies  : CookieSpec selected: ignoreCookies
2015-08-20 08:45:52.520 DEBUG 7700 --- [nio-9050-exec-9] o.a.h.client.protocol.RequestAuthCache   : Auth cache not set in the context
2015-08-20 08:45:52.520 DEBUG 7700 --- [nio-9050-exec-9] o.a.h.c.p.RequestTargetAuthentication    : Target auth state: UNCHALLENGED
2015-08-20 08:45:52.520 DEBUG 7700 --- [nio-9050-exec-9] o.a.h.c.p.RequestProxyAuthentication     : Proxy auth state: UNCHALLENGED
2015-08-20 08:45:52.520 DEBUG 7700 --- [nio-9050-exec-9] o.a.h.impl.conn.DefaultClientConnection  : Sending request: GET /ping/delay HTTP/1.1
2015-08-20 08:45:52.520 DEBUG 7700 --- [nio-9050-exec-9] org.apache.http.wire                     :  >> "GET /ping/delay HTTP/1.1[\r][\n]"
2015-08-20 08:45:52.520 DEBUG 7700 --- [nio-9050-exec-9] org.apache.http.wire                     :  >> "x-forwarded-host: 127.0.0.1:9050[\r][\n]"
2015-08-20 08:45:52.520 DEBUG 7700 --- [nio-9050-exec-9] org.apache.http.wire                     :  >> "x-forwarded-prefix: /example[\r][\n]"
2015-08-20 08:45:52.520 DEBUG 7700 --- [nio-9050-exec-9] org.apache.http.wire                     :  >> "accept-encoding: deflate, gzip[\r][\n]"
2015-08-20 08:45:52.520 DEBUG 7700 --- [nio-9050-exec-9] org.apache.http.wire                     :  >> "user-agent: curl/7.42.1[\r][\n]"
2015-08-20 08:45:52.520 DEBUG 7700 --- [nio-9050-exec-9] org.apache.http.wire                     :  >> "accept: */*[\r][\n]"
2015-08-20 08:45:52.520 DEBUG 7700 --- [nio-9050-exec-9] org.apache.http.wire                     :  >> "Netflix.NFHttpClient.Version: 1.0[\r][\n]"
2015-08-20 08:45:52.520 DEBUG 7700 --- [nio-9050-exec-9] org.apache.http.wire                     :  >> "X-netflix-httpclientname: examplems[\r][\n]"
2015-08-20 08:45:52.520 DEBUG 7700 --- [nio-9050-exec-9] org.apache.http.wire                     :  >> "Host: PMD11286:9060[\r][\n]"
2015-08-20 08:45:52.520 DEBUG 7700 --- [nio-9050-exec-9] org.apache.http.wire                     :  >> "Connection: Keep-Alive[\r][\n]"
2015-08-20 08:45:52.520 DEBUG 7700 --- [nio-9050-exec-9] org.apache.http.wire                     :  >> "[\r][\n]"
2015-08-20 08:45:52.520 DEBUG 7700 --- [nio-9050-exec-9] org.apache.http.headers                  : >> GET /ping/delay HTTP/1.1
2015-08-20 08:45:52.520 DEBUG 7700 --- [nio-9050-exec-9] org.apache.http.headers                  : >> x-forwarded-host: 127.0.0.1:9050
2015-08-20 08:45:52.520 DEBUG 7700 --- [nio-9050-exec-9] org.apache.http.headers                  : >> x-forwarded-prefix: /example
2015-08-20 08:45:52.520 DEBUG 7700 --- [nio-9050-exec-9] org.apache.http.headers                  : >> accept-encoding: deflate, gzip
2015-08-20 08:45:52.520 DEBUG 7700 --- [nio-9050-exec-9] org.apache.http.headers                  : >> user-agent: curl/7.42.1
2015-08-20 08:45:52.520 DEBUG 7700 --- [nio-9050-exec-9] org.apache.http.headers                  : >> accept: */*
2015-08-20 08:45:52.520 DEBUG 7700 --- [nio-9050-exec-9] org.apache.http.headers                  : >> Netflix.NFHttpClient.Version: 1.0
2015-08-20 08:45:52.520 DEBUG 7700 --- [nio-9050-exec-9] org.apache.http.headers                  : >> X-netflix-httpclientname: examplems
2015-08-20 08:45:52.520 DEBUG 7700 --- [nio-9050-exec-9] org.apache.http.headers                  : >> Host: PMD11286:9060
2015-08-20 08:45:52.520 DEBUG 7700 --- [nio-9050-exec-9] org.apache.http.headers                  : >> Connection: Keep-Alive
2015-08-20 08:45:52.630 DEBUG 7700 --- [nio-9050-exec-9] org.apache.http.wire                     :  << "HTTP/1.1 200 OK[\r][\n]"
2015-08-20 08:45:52.630 DEBUG 7700 --- [nio-9050-exec-9] org.apache.http.wire                     :  << "Server: Apache-Coyote/1.1[\r][\n]"
2015-08-20 08:45:52.630 DEBUG 7700 --- [nio-9050-exec-9] org.apache.http.wire                     :  << "X-Application-Context: examplems:9060[\r][\n]"
2015-08-20 08:45:52.630 DEBUG 7700 --- [nio-9050-exec-9] org.apache.http.wire                     :  << "Content-Type: text/plain;charset=UTF-8[\r][\n]"
2015-08-20 08:45:52.630 DEBUG 7700 --- [nio-9050-exec-9] org.apache.http.wire                     :  << "Content-Length: 76[\r][\n]"
2015-08-20 08:45:52.630 DEBUG 7700 --- [nio-9050-exec-9] org.apache.http.wire                     :  << "Date: Thu, 20 Aug 2015 06:45:52 GMT[\r][\n]"
2015-08-20 08:45:52.630 DEBUG 7700 --- [nio-9050-exec-9] org.apache.http.wire                     :  << "[\r][\n]"
2015-08-20 08:45:52.630 DEBUG 7700 --- [nio-9050-exec-9] o.a.h.impl.conn.DefaultClientConnection  : Receiving response: HTTP/1.1 200 OK
2015-08-20 08:45:52.630 DEBUG 7700 --- [nio-9050-exec-9] org.apache.http.headers                  : << HTTP/1.1 200 OK
2015-08-20 08:45:52.630 DEBUG 7700 --- [nio-9050-exec-9] org.apache.http.headers                  : << Server: Apache-Coyote/1.1
2015-08-20 08:45:52.630 DEBUG 7700 --- [nio-9050-exec-9] org.apache.http.headers                  : << X-Application-Context: examplems:9060
2015-08-20 08:45:52.630 DEBUG 7700 --- [nio-9050-exec-9] org.apache.http.headers                  : << Content-Type: text/plain;charset=UTF-8
2015-08-20 08:45:52.630 DEBUG 7700 --- [nio-9050-exec-9] org.apache.http.headers                  : << Content-Length: 76
2015-08-20 08:45:52.630 DEBUG 7700 --- [nio-9050-exec-9] org.apache.http.headers                  : << Date: Thu, 20 Aug 2015 06:45:52 GMT
2015-08-20 08:45:52.630 DEBUG 7700 --- [nio-9050-exec-9] org.apache.http.wire                     :  << "Svar efter 100 ms v[0xc3][0xa4]ntan. Kan [0xc3][0xa4]ndras med: ?time=200  15-08-20 08:45:52,618"
2015-08-20 08:45:52.630  WARN 7700 --- [nio-9050-exec-9] o.s.c.n.z.filters.post.SendErrorFilter   : Error during filtering

com.netflix.zuul.exception.ZuulException: Forwarding error
        at org.springframework.cloud.netflix.zuul.filters.route.RibbonRoutingFilter.forward(RibbonRoutingFilter.java:142)
        at org.springframework.cloud.netflix.zuul.filters.route.RibbonRoutingFilter.run(RibbonRoutingFilter.java:107)
        at com.netflix.zuul.ZuulFilter.runFilter(ZuulFilter.java:112)
        at com.netflix.zuul.FilterProcessor.processZuulFilter(FilterProcessor.java:197)
        at com.netflix.zuul.FilterProcessor.runFilters(FilterProcessor.java:161)
        at com.netflix.zuul.FilterProcessor.route(FilterProcessor.java:120)
        at com.netflix.zuul.ZuulRunner.route(ZuulRunner.java:84)
        at com.netflix.zuul.http.ZuulServlet.route(ZuulServlet.java:111)
        at com.netflix.zuul.http.ZuulServlet.service(ZuulServlet.java:77)
        at org.springframework.web.servlet.mvc.ServletWrappingController.handleRequestInternal(ServletWrappingController.java:158)
        at org.springframework.cloud.netflix.zuul.web.ZuulController.handleRequestInternal(ZuulController.java:43)
        at org.springframework.web.servlet.mvc.AbstractController.handleRequest(AbstractController.java:146)
        at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:50)
        at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)
        at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)
        at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:966)
        at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:857)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:618)
        at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:842)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:725)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
        at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
        at org.springframework.boot.actuate.autoconfigure.EndpointWebMvcAutoConfiguration$ApplicationContextHeaderFilter.doFilterInternal(EndpointWebMvcAutoConfiguration.java:291)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
        at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
        at org.springframework.boot.actuate.trace.WebRequestTraceFilter.doFilterInternal(WebRequestTraceFilter.java:102)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
        at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:85)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
        at org.springframework.boot.actuate.autoconfigure.MetricFilterAutoConfiguration$MetricsFilter.doFilterInternal(MetricFilterAutoConfiguration.java:90)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
        at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:516)
        at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1086)
        at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:659)
        at org.apache.coyote.http11.Http11NioProtocol$Http11ConnectionHandler.process(Http11NioProtocol.java:223)
        at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1558)
        at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1515)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
        at java.lang.Thread.run(Thread.java:745)
Caused by: com.netflix.hystrix.exception.HystrixRuntimeException: examplemsRibbonCommand timed-out and no fallback available.
        at com.netflix.hystrix.AbstractCommand$16.call(AbstractCommand.java:782)
        at com.netflix.hystrix.AbstractCommand$16.call(AbstractCommand.java:769)
        at rx.internal.operators.OperatorOnErrorResumeNextViaFunction$1.onError(OperatorOnErrorResumeNextViaFunction.java:77)
        at rx.internal.operators.OperatorDoOnEach$1.onError(OperatorDoOnEach.java:70)
        at rx.internal.operators.OperatorDoOnEach$1.onError(OperatorDoOnEach.java:70)
        at rx.internal.operators.OperatorDoOnEach$1.onError(OperatorDoOnEach.java:70)
        at com.netflix.hystrix.AbstractCommand$DeprecatedOnFallbackHookApplication$1.onError(AbstractCommand.java:1444)
        at com.netflix.hystrix.AbstractCommand$FallbackHookApplication$1.onError(AbstractCommand.java:1334)
        at com.netflix.hystrix.HystrixCommand$2.call(HystrixCommand.java:314)
        at com.netflix.hystrix.HystrixCommand$2.call(HystrixCommand.java:306)
        at rx.Observable$1.call(Observable.java:144)
        at rx.Observable$1.call(Observable.java:136)
        at rx.Observable$1.call(Observable.java:144)
        at rx.Observable$1.call(Observable.java:136)
        at rx.Observable$1.call(Observable.java:144)
        at rx.Observable$1.call(Observable.java:136)
        at rx.Observable$1.call(Observable.java:144)
        at rx.Observable$1.call(Observable.java:136)
        at rx.Observable$1.call(Observable.java:144)
        at rx.Observable$1.call(Observable.java:136)
        at rx.Observable$1.call(Observable.java:144)
        at rx.Observable$1.call(Observable.java:136)
        at rx.Observable$1.call(Observable.java:144)
        at rx.Observable$1.call(Observable.java:136)
        at rx.Observable$1.call(Observable.java:144)
        at rx.Observable$1.call(Observable.java:136)
        at rx.Observable$1.call(Observable.java:144)
        at rx.Observable$1.call(Observable.java:136)
        at rx.Observable$1.call(Observable.java:144)
        at rx.Observable$1.call(Observable.java:136)
        at rx.Observable.unsafeSubscribe(Observable.java:7466)
        at rx.internal.operators.OperatorOnErrorResumeNextViaFunction$1.onError(OperatorOnErrorResumeNextViaFunction.java:78)
        at rx.internal.operators.OperatorDoOnEach$1.onError(OperatorDoOnEach.java:70)
        at rx.internal.operators.OperatorDoOnEach$1.onError(OperatorDoOnEach.java:70)
        at com.netflix.hystrix.AbstractCommand$HystrixObservableTimeoutOperator$1.run(AbstractCommand.java:923)
        at com.netflix.hystrix.strategy.concurrency.HystrixContextRunnable$1.call(HystrixContextRunnable.java:41)
        at com.netflix.hystrix.strategy.concurrency.HystrixContextRunnable$1.call(HystrixContextRunnable.java:37)
        at com.netflix.hystrix.strategy.concurrency.HystrixContextRunnable.run(HystrixContextRunnable.java:57)
        at com.netflix.hystrix.AbstractCommand$HystrixObservableTimeoutOperator$2.tick(AbstractCommand.java:943)
        at com.netflix.hystrix.util.HystrixTimer$1.run(HystrixTimer.java:98)
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
        at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308)
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180)
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
        ... 1 common frames omitted
Caused by: java.util.concurrent.TimeoutException: null
        at com.netflix.hystrix.AbstractCommand$9.call(AbstractCommand.java:589)
        at com.netflix.hystrix.AbstractCommand$9.call(AbstractCommand.java:570)
        at rx.internal.operators.OperatorOnErrorResumeNextViaFunction$1.onError(OperatorOnErrorResumeNextViaFunction.java:77)
        ... 15 common frames omitted

Если я подожду минуту или две, служба будет удалена из eureka, и в конечном итоге это будет распространено на zuulproxy, что означает отсутствие трафика на остановленную службу. Но мое предположение заключалось в том, что лента/гистерикс обработала бы не отвечающую услугу более элегантную/быстро.

Любая подсказка/предложение? спасибо Magnus

Ответ 1

1/TIMEOUT

Запросы Zuul контролируются Hystrix, целью которых (в этом приложении) является применение тайм-аутов при длительных запросах.

Hystrix предоставляет два разных способа выполнения команд и принудительное использование тайм-аутов: изоляция SEMAPHORE и THREAD.

Когда используется изоляция THREAD, команды Hystrix выполняются в отдельном потоке из пула потоков. Затем Hystrix "приостанавливает" поток, содержащий входящий запрос, до тех пор, пока не будет получен ответ от сервера нисходящего потока или не произойдет тайм-аут.

При использовании изоляции SEMAPHORE в потоке запроса выполняются команды Hystrix. Таймауты обнаруживаются только после получения ответа от сервера нисходящего потока. Поэтому, если вы настроите Zuul/Hystrix с тайм-аутом 5 секунд, и ваша услуга займет 30 секунд, ваш клиент будет уведомлен о тайм-ауте только через 30 секунд - даже если служба ответила успешно (!)

Netflix рекомендует исполнение THREAD по умолчанию, за исключением некоторых редких случаев. К сожалению, интеграция SpringCloud Zuul изменила его на SEMAPHORE по неизвестным мне причинам. См. Почему ZUUL принудительно изолирует SEMAPHORE для выполнения своих команд Hystrix? для получения дополнительной информации.

Это объясняет, почему вы получили ошибку 500, хотя с оставшимся сервером в реальном времени был успешно связан.

2/RETRY

Лента используется для фактического вызова удаленной службы. Он использует информацию, предоставленную Eureka, для определения доступных услуг и соответствующих адресов. Eureka использует локальный кеш, который обновляется каждые 30 секунд. Так как @spencergibb сказал, что на некоторое время он будет хранить устаревшую информацию (мертвый сервер), но это ожидается.

Лента автоматически повторяет попытку подключения/контакта службы. Он может быть настроен на повторный запуск одного и того же сервера, прежде чем пытаться выполнить другой. Я не помню значения по умолчанию или фактическое свойство конфигурации, но лично я использовал следующие настройки:

# Max number of retries on the same server (excluding the first try)
ribbon.maxAutoRetries = 1

# Max number of next servers to retry (excluding the first server)
ribbon.MaxAutoRetriesNextServer = 2

3/CONNECT TIMEOUT

Из ваших журналов кажется, что для отказа от попытки подключения к удаленной службе требуется около 1 с. Это очень долго для прекращения службы. Попытки подключиться к TCP-порту без прослушивания службы должны немедленно сработать (по крайней мере, если хост /ip достигнут, и попытка подключения не заканчивается в пустоте)...

Тайм-аут соединения управляется следующим свойством: убедитесь, что вы установили его в значение спуска:

# Connect timeout used by Apache HttpClient
ribbon.ConnectTimeout=3000

# Read timeout used by Apache HttpClient
ribbon.ReadTimeout=5000

Надеемся, что эта информация поможет вам устранить вашу проблему, -)