首页 > 解决方案 > 当一个服务实例正在终止时,JHipster 微服务网关暂时抛出 HTTP 500 错误

问题描述

我们有一个标准的 JHipster 设置,包括一个网关和一个微服务应用程序。JHipster-Registry 用于服务发现。我们没有对 JHipster 生成器生成的代码或配置进行任何类型的更改。

一切都按预期工作。但是,当关闭其中一个微服务应用程序实例(SIGINT、CLI 上的 ^C、Kubernetes pod 终止)时,我们会暂时收到 HTTP 500 内部服务器错误,以通过网关 ( http://gateway/service/. ......)。

请在下面从网关中的 HTTP 500 错误中找到堆栈跟踪:

Caused by: org.apache.http.NoHttpResponseException: 172.16.94.61:8085 failed to respond
    at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:141)
    at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:56)
    at org.apache.http.impl.io.AbstractMessageParser.parse(AbstractMessageParser.java:259)
    at org.apache.http.impl.DefaultBHttpClientConnection.receiveResponseHeader(DefaultBHttpClientConnection.java:163)
    at org.apache.http.impl.conn.CPoolProxy.receiveResponseHeader(CPoolProxy.java:165)
    at org.apache.http.protocol.HttpRequestExecutor.doReceiveResponse(HttpRequestExecutor.java:273)
    at org.apache.http.protocol.HttpRequestExecutor.execute(HttpRequestExecutor.java:125)
    at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:272)
    at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:185)
    at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:89)
    at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:111)
    at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:185)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:83)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:108)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:56)
    at org.springframework.cloud.netflix.ribbon.apache.RetryableRibbonLoadBalancingHttpClient$1.doWithRetry(RetryableRibbonLoadBalancingHttpClient.java:93)
    at org.springframework.cloud.netflix.ribbon.apache.RetryableRibbonLoadBalancingHttpClient$1.doWithRetry(RetryableRibbonLoadBalancingHttpClient.java:71)
    at org.springframework.retry.support.RetryTemplate.doExecute(RetryTemplate.java:287)
    at org.springframework.retry.support.RetryTemplate.execute(RetryTemplate.java:164)
    at org.springframework.cloud.netflix.ribbon.apache.RetryableRibbonLoadBalancingHttpClient.executeWithRetry(RetryableRibbonLoadBalancingHttpClient.java:113)
    at org.springframework.cloud.netflix.ribbon.apache.RetryableRibbonLoadBalancingHttpClient.execute(RetryableRibbonLoadBalancingHttpClient.java:104)
    at org.springframework.cloud.netflix.ribbon.apache.RetryableRibbonLoadBalancingHttpClient.execute(RetryableRibbonLoadBalancingHttpClient.java:50)
    at com.netflix.client.AbstractLoadBalancerAwareClient$1.call(AbstractLoadBalancerAwareClient.java:109)
    at com.netflix.loadbalancer.reactive.LoadBalancerCommand$3$1.call(LoadBalancerCommand.java:303)
    at com.netflix.loadbalancer.reactive.LoadBalancerCommand$3$1.call(LoadBalancerCommand.java:287)
    at rx.internal.util.ScalarSynchronousObservable$3.call(ScalarSynchronousObservable.java:231)
    at rx.internal.util.ScalarSynchronousObservable$3.call(ScalarSynchronousObservable.java:228)
    at rx.Observable.unsafeSubscribe(Observable.java:10211)
    at rx.internal.operators.OnSubscribeConcatMap$ConcatMapSubscriber.drain(OnSubscribeConcatMap.java:286)
    at rx.internal.operators.OnSubscribeConcatMap$ConcatMapSubscriber.onNext(OnSubscribeConcatMap.java:144)
    at com.netflix.loadbalancer.reactive.LoadBalancerCommand$1.call(LoadBalancerCommand.java:185)
    at com.netflix.loadbalancer.reactive.LoadBalancerCommand$1.call(LoadBalancerCommand.java:180)
    at rx.Observable.unsafeSubscribe(Observable.java:10211)
    at rx.internal.operators.OnSubscribeConcatMap.call(OnSubscribeConcatMap.java:94)
    at rx.internal.operators.OnSubscribeConcatMap.call(OnSubscribeConcatMap.java:42)
    at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)
    at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)
    at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)
    at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)
    at rx.Observable.subscribe(Observable.java:10307)
    at rx.Observable.subscribe(Observable.java:10274)
    at rx.observables.BlockingObservable.blockForSingle(BlockingObservable.java:445)

看起来网关的负载均衡器仍在使用正在终止的微服务实例。

我们还尝试了 Consul 而不是 JHipster-Registry/Eureka 并发现了相同的行为。

重现步骤:

由于我们使用的是开箱即​​用的 JHipster 设置,因此我们很困惑,因为在 Internet 上找不到任何解决此问题的文章。

有没有人遇到同样的问题,知道这里出了什么问题或如何解决这个问题?我们尝试了很长时间来寻找原因和解决方案,但我们觉得我们被困在这里。

如果您需要更多信息(日志、配置、跟踪等),我们很乐意在此处发布。

标签: microservicesjhipstergatewayservice-discovery

解决方案


您可以通过在 application.yml 中设置来启用spring-retry(包含在默认 JHipster 网关的 pom.xml 中) 。zuul.retryable: true然后将再次尝试任何失败的 GET 请求。如果您还希望多次尝试其他 HTTP 方法(例如 POST),请设置ribbon.OkToRetryOnAllOperations: true

http://cloud.spring.io/spring-cloud-static/Dalston.SR1/#retrying-failed-requests


推荐阅读