【问题标题】:upstream connect error or disconnect/reset before headers. reset reason: connection termination when using Spring Boot上游连接错误或在标头之前断开/重置。重置原因:使用 Spring Boot 时连接终止
【发布时间】:2020-08-11 02:35:56
【问题描述】:

我正在使用带有嵌入式 Tomcat 9.0.36 的 Spring Boot。它在 Kubernetes 中用作 Docker 映像。最近升级 envoy 后,我开始收到异常。

  "upstream connect error or disconnect/reset before headers. reset reason: connection termination" with 503 status code

有些人建议将空闲连接超时时间增加到 60 秒,但在春季启动时,我能够找到“连接超时”和“保持活动超时”。我使用下面的代码将它们增加到 5 分钟。

@Configuration
public class TomcatCustomizer implements WebServerFactoryCustomizer<TomcatServletWebServerFactory> {

    private static final Logger LOGGER = LoggerFactory.getLogger(TomcatCustomizer.class);

    @Override
    public void customize(TomcatServletWebServerFactory factory) {

        factory.addConnectorCustomizers(connector -> {
            AbstractHttp11Protocol protocol = (AbstractHttp11Protocol) connector.getProtocolHandler();
            //Setting up connection time out
            protocol.setKeepAliveTimeout(360000);
            protocol.setConnectionTimeout(360000);
            protocol.setMaxKeepAliveRequests(120);
        });
    }
}

仍然,我遇到了同样的错误。此应用程序在内部调用另一个服务,该服务也托管在 Kubernetes 中。我可以在我的服务中看到成功的响应,但在那之后,我看不到任何日志。

【问题讨论】:

  • 这个错误在 istio 中经常出现。你能添加你的 istio 配置吗?你的 istio 版本、网关、虚拟服务、目标规则是什么?你用 mtls 吗?
  • 实际上我无权访问这些。我只知道他们在早期版本代码中将 Envoy 版本升级到 14 工作正常。但是,我能够通过从内部服务获得的响应中删除标头来解决此问题。也许它阻止了一些标头,或者可能交叉检查了自己的标头。
  • 很高兴听到您找到了答案。您能否添加一个答案并将其标记为已接受以提高知名度?
  • @jt97 我不知道如何将其标记为已接受。我已在回答中提供了所有详细信息。

标签: spring-boot tomcat kubernetes istio


【解决方案1】:

我花了一周的时间从应用程序的角度分析了这一点。我遵循了 Ops 团队建议的几个步骤。

  • 将 Tomcat 服务器中的超时时间增加到 60 秒,因为它们在 Envoy 中已配置相同
  • 我确实增加了时间,但无法解决问题。
  • 我将 Spring Cloud Gateway 用于网关服务,我认为这是问题所在,因此我将其更改为 Rest Templates,但这也没有解决问题。
  • 幸运的是,运行状况检查 API 工作正常,除了那些在内部与其他服务通信的 API。在 Health API 中,他们还与其他服务通信以检查他们的 Health,但我没有直接返回响应。我正在打包修改它的响应主体并将其转发到 UI。我也应用了相同的方法并使用了您可以轻松理解的以下代码。我创建了一个新的响应实体并删除了我从内部 API 接收并返回到 UI 的所有标头。它就像魅力一样。

//Earlier (Forwarding same headers received from internal service to UI)
ResponseEntity responseEntity = //Received by calling other APIs;
return responseEntity;

//Now (Dropped headers)
ResponseEntity responseEntity = //Received by calling other APIs;
MultiValueMap<String, String> newHeaders = new LinkedMultiValueMap<>();          
if (Objects.nonNull(responseEntity) && Objects.nonNull(responseEntity.getBody())) {
    newHeaders.set("Content-type", responseEntity.getHeaders().getContentType().toString());
    return new ResponseEntity(responseEntity.getBody(), newHeaders, responseEntity.getStatusCode());
}

【讨论】:

  • 非常感谢......经过 2 周的努力,我能够解决这个问题!
猜你喜欢
  • 2019-12-29
  • 2020-12-04
  • 2021-12-22
  • 2021-06-30
  • 2022-11-04
  • 2021-11-13
  • 1970-01-01
  • 2020-11-09
  • 2022-11-03
相关资源
最近更新 更多