为什么我会收到 org.eclipse.jetty.http.BadMessageException: 500: 请求标头太大

问题描述 投票:0回答:1

我在 Spring Boot 反应式服务中有以下 WebClient 配置:

public WebClient createWebClient(ObjectMapper objectMapper) {
    ExchangeStrategies strategies = ExchangeStrategies
        .builder()
        .codecs(clientDefaultCodecsConfigurer -> {
          clientDefaultCodecsConfigurer.defaultCodecs().enableLoggingRequestDetails(true);
          clientDefaultCodecsConfigurer.defaultCodecs().jackson2JsonEncoder(
              new Jackson2JsonEncoder(objectMapper, MediaType.APPLICATION_JSON));
          clientDefaultCodecsConfigurer.defaultCodecs().jackson2JsonDecoder(
              new Jackson2JsonDecoder(objectMapper, MediaType.APPLICATION_JSON));
        }).build();

    SslContextFactory sslContextFactory = new SslContextFactory();
    HttpClient httpClient = new HttpClient(sslContextFactory) {
      @Override
      public Request newRequest(URI uri) {

        Request request = super.newRequest(uri);
        request.timeout(requestTimeoutInSeconds, TimeUnit.SECONDS);
        return requestLogEnhancer.enhance(request);
      }
    };

    httpClient.setMaxRequestsQueuedPerDestination(maxRequestsPerDestination);
    httpClient.setMaxConnectionsPerDestination(maxConnectionsPerDestination);
    httpClient.setIdleTimeout(idleTimeoutInMilliSeconds);

    WebClient.Builder webClient = WebClient
        .builder()
        .clientConnector(new JettyClientHttpConnector(httpClient))
        .exchangeStrategies(strategies)
        .defaultHeader(HTTP.USER_AGENT, USER_AGENT_VALUE);

    return webClient.build();
  }

此 WebClient 用于对其他服务进行 API 调用。

服务正常运行了一个多月,但其中 1 个实例突然开始出现以下异常:

org.eclipse.jetty.http.BadMessageException: 500: Request header too large
    at org.eclipse.jetty.http.HttpGenerator.generateRequest(HttpGenerator.java:279)
    at org.eclipse.jetty.client.http.HttpSenderOverHTTP$HeadersCallback.process(HttpSenderOverHTTP.java:231)
    at org.eclipse.jetty.util.IteratingCallback.processing(IteratingCallback.java:241)
    at org.eclipse.jetty.util.IteratingCallback.iterate(IteratingCallback.java:224)
    at org.eclipse.jetty.client.http.HttpSenderOverHTTP.sendHeaders(HttpSenderOverHTTP.java:62)
    at org.eclipse.jetty.client.HttpSender.send(HttpSender.java:214)
    at org.eclipse.jetty.client.http.HttpChannelOverHTTP.send(HttpChannelOverHTTP.java:85)
    at org.eclipse.jetty.client.HttpChannel.send(HttpChannel.java:128)
    at org.eclipse.jetty.client.HttpConnection.send(HttpConnection.java:201)
    at org.eclipse.jetty.client.http.HttpConnectionOverHTTP$Delegate.send(HttpConnectionOverHTTP.java:255)
    at org.eclipse.jetty.client.http.HttpConnectionOverHTTP.send(HttpConnectionOverHTTP.java:122)
    at org.eclipse.jetty.client.http.HttpDestinationOverHTTP.send(HttpDestinationOverHTTP.java:38)
    at org.eclipse.jetty.client.HttpDestination.process(HttpDestination.java:346)
    at org.eclipse.jetty.client.HttpDestination.process(HttpDestination.java:304)
    at org.eclipse.jetty.client.HttpDestination.send(HttpDestination.java:294)
    at org.eclipse.jetty.client.HttpDestination.succeeded(HttpDestination.java:228)
    at org.eclipse.jetty.client.AbstractConnectionPool.proceed(AbstractConnectionPool.java:153)
    at org.eclipse.jetty.client.AbstractConnectionPool$1.succeeded(AbstractConnectionPool.java:131)
    at org.eclipse.jetty.client.AbstractConnectionPool$1.succeeded(AbstractConnectionPool.java:123)
    at org.eclipse.jetty.util.Promise$Wrapper.succeeded(Promise.java:130)
    at org.eclipse.jetty.client.http.HttpConnectionOverHTTP.onOpen(HttpConnectionOverHTTP.java:130)
    at org.eclipse.jetty.io.ssl.SslConnection.onOpen(SslConnection.java:267)
    at org.eclipse.jetty.io.SelectorManager.connectionOpened(SelectorManager.java:324)
    at org.eclipse.jetty.io.ManagedSelector.createEndPoint(ManagedSelector.java:253)
    at org.eclipse.jetty.io.ManagedSelector.access$1800(ManagedSelector.java:60)
    at org.eclipse.jetty.io.ManagedSelector$CreateEndPoint.run(ManagedSelector.java:889)
    at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:765)
    at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:683)
    at java.lang.Thread.run(Thread.java:748)
Caused by: java.nio.BufferOverflowException: null
    at java.nio.Buffer.nextPutIndex(Buffer.java:521)
    at java.nio.HeapByteBuffer.put(HeapByteBuffer.java:169)
    at org.eclipse.jetty.http.HttpGenerator.putSanitisedValue(HttpGenerator.java:932)
    at org.eclipse.jetty.http.HttpGenerator.putTo(HttpGenerator.java:954)
    at org.eclipse.jetty.http.HttpGenerator.generateHeaders(HttpGenerator.java:645)
    at org.eclipse.jetty.http.HttpGenerator.generateRequest(HttpGenerator.java:250)
    ... 28 common frames omitted

重启服务后,这个异常不再发生,但我担心这种情况可能会再次发生。此异常的根本原因可能是什么?如何重现和解决此问题?

java spring-boot jetty spring-webflux
1个回答
0
投票

该错误告诉您,当尝试设置标头值时,该值将超出配置的输出缓冲区。

您配置的输出缓冲区大小是多少?

默认情况下,HttpClient.requestBufferSize 为 4096 字节。

如果这看起来正常,那么还要检查您的 HttpClient 以确保它没有获取额外的 Cookie。 Jetty HttpClient 将使用 JDK CookieStore / CookieManager,它们会记住 Cookie 很长一段时间,有时比您预期的时间长得多。过多的 Cookie 也可能会触发此错误,因为如果自动添加大量 Cookie,则没有足够的空间容纳标头。

© www.soinside.com 2019 - 2024. All rights reserved.