我在 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
重启服务后,这个异常不再发生,但我担心这种情况可能会再次发生。此异常的根本原因可能是什么?如何重现和解决此问题?
该错误告诉您,当尝试设置标头值时,该值将超出配置的输出缓冲区。
您配置的输出缓冲区大小是多少?
默认情况下,HttpClient.requestBufferSize 为 4096 字节。
如果这看起来正常,那么还要检查您的 HttpClient 以确保它没有获取额外的 Cookie。 Jetty HttpClient 将使用 JDK CookieStore / CookieManager,它们会记住 Cookie 很长一段时间,有时比您预期的时间长得多。过多的 Cookie 也可能会触发此错误,因为如果自动添加大量 Cookie,则没有足够的空间容纳标头。