简体   繁体   English

有什么方法可以处理 HttpClient java 中的 HTTP/2 Goaway 收到的 IOException?

[英]is there any way to handle HTTP/2 Goaway received IOException in HttpClient java?

I am making API calls in the application, At some point randomly it throws java.io.IOException: /149.222.1.1:553232: GOAWAY received , using Java 11 environment. I am making API calls in the application, At some point randomly it throws java.io.IOException: /149.222.1.1:553232: GOAWAY received , using Java 11 environment. anyway to resolve this exception rather than moving to Http/1.1 or other HTTP client libraries?无论如何要解决此异常,而不是移至 Http/1.1 或其他 HTTP 客户端库?

here is the stack trace这是堆栈跟踪

"com.abcd.common.RequestProcessor:53 getRequest: java.io.IOException: /149.222.1.1:553232: GOAWAY received
    at java.net.http/jdk.internal.net.http.HttpClientImpl.send(HttpClientImpl.java:565)
    at java.net.http/jdk.internal.net.http.HttpClientFacade.send(HttpClientFacade.java:119)
    at com.abcd.common.RequestProcessor.getRequest(RequestProcessor.java:49)
    at com.abcd.common.util.SendApiRequestUtil.sendApiRequestToCMS(SendApiRequestUtil.java:97)
    at com.abcd.controller.ContactsController.getContacts(ContactsController.java:61)
    at jdk.internal.reflect.GeneratedMethodAccessor81.invoke(Unknown Source)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:105)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:878)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:792)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:645)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:750)
    at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:763)
    at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1651)
    at com.abcd.filter.LogFilter.doFilter(LogFilter.java:26)
    at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1638)
    at org.springframework.session.web.http.SessionRepositoryFilter.doFilterInternal(SessionRepositoryFilter.java:141)
    at org.springframework.session.web.http.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:82)
    at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1638)
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
    at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1638)
    at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:567)
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
    at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:602)
    at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127)
    at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:235)
    at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1610)
    at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:233)
    at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1377)
    at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:188)
    at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:507)
    at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1580)
    at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:186)
    at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1292)
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
    at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127)
    at org.eclipse.jetty.server.Server.handle(Server.java:501)
    at org.eclipse.jetty.server.HttpChannel.lambda$handle$1(HttpChannel.java:383)
    at org.eclipse.jetty.server.HttpChannel.dispatch(HttpChannel.java:556)
    at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:375)
    at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:273)
    at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:311)
    at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:105)
    at org.eclipse.jetty.io.ChannelEndPoint$1.run(ChannelEndPoint.java:104)
    at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.runTask(EatWhatYouKill.java:336)
    at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:313)
    at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.tryProduce(EatWhatYouKill.java:171)
    at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:129)
    at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:375)
    at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:806)
    at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:938)
    at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: java.io.IOException: /169.254.8.1:55302: GOAWAY received
    at java.net.http/jdk.internal.net.http.Http2Connection.handleGoAway(Http2Connection.java:985)
    at java.net.http/jdk.internal.net.http.Http2Connection.handleConnectionFrame(Http2Connection.java:853)
    at java.net.http/jdk.internal.net.http.Http2Connection.processFrame(Http2Connection.java:724)
    at java.net.http/jdk.internal.net.http.frame.FramesDecoder.decode(FramesDecoder.java:155)
    at java.net.http/jdk.internal.net.http.Http2Connection$FramesController.processReceivedData(Http2Connection.java:232)
    at java.net.http/jdk.internal.net.http.Http2Connection.asyncReceive(Http2Connection.java:649)
    at java.net.http/jdk.internal.net.http.Http2Connection$Http2TubeSubscriber.processQueue(Http2Connection.java:1275)
    at java.net.http/jdk.internal.net.http.common.SequentialScheduler$SynchronizedRestartableTask.run(SequentialScheduler.java:175)
    at java.net.http/jdk.internal.net.http.common.SequentialScheduler$CompleteRestartableTask.run(SequentialScheduler.java:147)
    at java.net.http/jdk.internal.net.http.common.SequentialScheduler$SchedulableTask.run(SequentialScheduler.java:198)
    at java.net.http/jdk.internal.net.http.common.SequentialScheduler.runOrSchedule(SequentialScheduler.java:271)
    at java.net.http/jdk.internal.net.http.common.SequentialScheduler.runOrSchedule(SequentialScheduler.java:224)
    at java.net.http/jdk.internal.net.http.Http2Connection$Http2TubeSubscriber.runOrSchedule(Http2Connection.java:1293)
    at java.net.http/jdk.internal.net.http.Http2Connection$Http2TubeSubscriber.onNext(Http2Connection.java:1319)
    at java.net.http/jdk.internal.net.http.Http2Connection$Http2TubeSubscriber.onNext(Http2Connection.java:1253)
    at java.net.http/jdk.internal.net.http.common.SSLTube$DelegateWrapper.onNext(SSLTube.java:202)
    at java.net.http/jdk.internal.net.http.common.SSLTube$SSLSubscriberWrapper.onNext(SSLTube.java:484)
    at java.net.http/jdk.internal.net.http.common.SSLTube$SSLSubscriberWrapper.onNext(SSLTube.java:287)
    at java.net.http/jdk.internal.net.http.common.SubscriberWrapper$DownstreamPusher.run1(SubscriberWrapper.java:318)
    at java.net.http/jdk.internal.net.http.common.SubscriberWrapper$DownstreamPusher.run(SubscriberWrapper.java:261)
    at java.net.http/jdk.internal.net.http.common.SequentialScheduler$SynchronizedRestartableTask.run(SequentialScheduler.java:175)
    at java.net.http/jdk.internal.net.http.common.SequentialScheduler$CompleteRestartableTask.run(SequentialScheduler.java:147)
    at java.net.http/jdk.internal.net.http.common.SequentialScheduler$SchedulableTask.run(SequentialScheduler.java:198)
    at java.net.http/jdk.internal.net.http.common.SequentialScheduler.runOrSchedule(SequentialScheduler.java:271)
    at java.net.http/jdk.internal.net.http.common.SequentialScheduler.runOrSchedule(SequentialScheduler.java:224)
    at java.net.http/jdk.internal.net.http.common.SubscriberWrapper.outgoing(SubscriberWrapper.java:234)
    at java.net.http/jdk.internal.net.http.common.SubscriberWrapper.outgoing(SubscriberWrapper.java:200)
    at java.net.http/jdk.internal.net.http.common.SSLFlowDelegate$Reader.processData(SSLFlowDelegate.java:403)
    at java.net.http/jdk.internal.net.http.common.SSLFlowDelegate$Reader$ReaderDownstreamPusher.run(SSLFlowDelegate.java:264)
    at java.net.http/jdk.internal.net.http.common.SequentialScheduler$SynchronizedRestartableTask.run(SequentialScheduler.java:175)
    at java.net.http/jdk.internal.net.http.common.SequentialScheduler$CompleteRestartableTask.run(SequentialScheduler.java:147)
    at java.net.http/jdk.internal.net.http.common.SequentialScheduler$SchedulableTask.run(SequentialScheduler.java:198)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)

This is something that your code will just have to deal with.这是您的代码必须处理的事情。

A GOAWAY frame has been sent by the HTTP 2.0 server that your client is talking to.您的客户端正在与之通信的 HTTP 2.0 服务器已发送 GOAWAY 帧。 That means that the server has decided to shut down the connection for some reason.这意味着服务器已决定出于某种原因关闭连接。 The only thing that the client side can do is tell the caller via an IOException .客户端唯一能做的就是通过IOException告诉调用者。

This is analogous to an HTTP 1.x server doing a TCP reset... or just disconnecting.这类似于 HTTP 1.x 服务器执行 TCP 重置...或只是断开连接。 These will also result in a client-side IOException .这些也将导致客户端IOException

So, the solution is to catch the IOException and handle it;因此,解决方案是捕获IOException并进行处理; eg by reporting to the user that the request has failed, or retrying the HTTP request using a fresh connection.例如,通过向用户报告请求失败,或使用新连接重试 HTTP 请求。

(If you retry, you need some strategy to avoid your client code repeating a request that is never going to succeed. Indeed, ill-advised retrying can actually make things worse, if the reason that the server disconnected is that it is overloaded.) (如果你重试,你需要一些策略来避免你的客户端代码重复一个永远不会成功的请求。事实上,如果服务器断开连接的原因是它过载,那么不明智的重试实际上会使事情变得更糟。)


I doubt that switching to HTTP 1.1 would help.我怀疑切换到 HTTP 1.1 会有所帮助。 I would expect that you would continue to get "random" IOExceptions ... with a different message... from the server using HTTP 1.1.我希望您会继续使用 HTTP 1.1 从服务器获取“随机” IOExceptions ......带有不同的消息......


There were a couple of JDK bugs related to GOAWAY handling in HTTPClient, but they were marked as resolved in 2018. You can use this query to find them: HTTPClient 中有几个与 GOAWAY 处理相关的 JDK 错误,但它们在 2018 年被标记为已解决。您可以使用此查询找到它们:

I don't think they are relevant if you are using the latest version of JDK 11.如果您使用的是最新版本的 JDK 11,我认为它们无关紧要。

I believe that given GOAWAY is send from server to "idle connection after being idle too long".我相信鉴于 GOAWAY 是从服务器发送到“空闲时间过长后的空闲连接”。 Generally, you can configure to not log such exception if they occur in client holding connection on background.通常,如果它们发生在后台保持连接的客户端中,您可以配置不记录此类异常。

In your case I see, that exception is thrown from your code:在您的情况下,我看到,该异常是从您的代码中引发的:

com.abcd.common.RequestProcessor.getRequest(RequestProcessor.java:49)

This is not case described at the beginning of my answer.我的答案开头没有描述这种情况。

What is "random point in time"?什么是“随机时间点”? Is it during http call?是在 http 通话期间吗? Does server wait for longer period of time for your input to be sent?服务器是否等待更长的时间才能发送您的输入?

PS: There is also great chance, that after your 1000th request using single TCP connection, server does close connection. PS:也很有可能,在您使用单个 TCP 连接的第 1000 个请求之后,服务器会关闭连接。 It is a default value for nginx at least.它至少是 nginx 的默认值。 See https://www.androidbugfix.com/2022/03/how-to-handle-http2-goaway-with.html for more info.有关更多信息,请参阅https://www.androidbugfix.com/2022/03/how-to-handle-http2-goaway-with.html

try adding ".version(HttpClient.Version.HTTP_1_1)" in your http request尝试在您的 http 请求中添加“.version(HttpClient.Version.HTTP_1_1)”

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何使用 HttpClient 处理 HTTP/2 GOAWAY? - How to handle HTTP/2 GOAWAY with HttpClient? 使用 java.net.http.HttpClient 的 GOAWAY BItBucket API - GOAWAY BItBucket API using java.net.http.HttpClient Java:有没有办法更改收到的HTTP响应头? - Java: Is there a way of changing the received HTTP Response headers? 原因:java.io.IOException:HTTP/1.1 标头解析器未收到任何字节 - Caused by: java.io.IOException: HTTP/1.1 header parser received no bytes 有没有办法将 java.net.http.HttpClient 与 Oauth2 一起使用? - Is there a way to use java.net.http.HttpClient with Oauth2? Apache HttpClient执行是否会对所有HTTP 5XX错误抛出IOException? - Will Apache HttpClient execute throw an IOException on ALL HTTP 5XX errors? 可能是“ java.io.IOException:错误的HTTP请求,收到的数据少于预期的”错误的可能原因? - What could be the possible causes of a “java.io.IOException: Bad HTTP request, less data is received than expected” error? 未收到Java HTTP cookie - Java HTTP cookies not received GCM (legacy FCM) 发送 GOAWAY HTTP/2 帧 - GCM (legacy FCM) sends GOAWAY HTTP/2 frames Java 输入重定向:有没有办法在读取时实际显示接收到的输入? - Java input redirection: Is there any way to actually display the received input as it is read?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM