我有一个 HttpClient 来访问 REST 服务,现在我正在实现软关闭,这意味着当进程关闭时(kill
在 linux 上使用一个简单的命令)它应该停止接收新任务并完成它正在处理的所有任务。
我的 HttpClient 已注册侦听器,因此我可以处理 REST 服务器响应。
软关机是通过使用 ShutdownHook 实现的,但这并不是问题所在。
在测试解决方案时,我偶然发现了这个异常:
com.myproject.commons.exception.ErrorCodeException: A network error ocurred during the callback
at com.myproject.callback.client.service.CallbackLogListener.adaptCallbackException(CallbackLogListener.java:386)
at com.myproject.callback.client.service.CallbackLogListener.saveUserError(CallbackLogListener.java:279)
at com.myproject.callback.client.service.CallbackLogListener.onComplete(CallbackLogListener.java:198)
at com.myproject.callback.client.service.MultiResponseListener$8.run(MultiResponseListener.java:143)
at com.myproject.callback.client.service.MultiResponseListener$8.run(MultiResponseListener.java:140)
at com.myproject.util.ListenerCollection.foreach(ListenerCollection.java:84)
at com.myproject.callback.client.service.MultiResponseListener.onComplete(MultiResponseListener.java:140)
at org.eclipse.jetty.client.ResponseNotifier.notifyComplete(ResponseNotifier.java:193)
at org.eclipse.jetty.client.ResponseNotifier.notifyComplete(ResponseNotifier.java:185)
at org.eclipse.jetty.client.HttpReceiver.terminateResponse(HttpReceiver.java:459)
at org.eclipse.jetty.client.HttpReceiver.abort(HttpReceiver.java:540)
at org.eclipse.jetty.client.HttpChannel.abortResponse(HttpChannel.java:129)
at org.eclipse.jetty.client.HttpChannel.abort(HttpChannel.java:122)
at org.eclipse.jetty.client.HttpExchange.abort(HttpExchange.java:257)
at com.myproject.callback.client.http.OverriddenHttpConversation.abort(OverriddenHttpConversation.java:140)
at org.eclipse.jetty.client.HttpRequest.abort(HttpRequest.java:748)
at org.eclipse.jetty.client.http.HttpConnectionOverHTTP.abort(HttpConnectionOverHTTP.java:205)
at org.eclipse.jetty.client.http.HttpConnectionOverHTTP.close(HttpConnectionOverHTTP.java:191)
at org.eclipse.jetty.client.http.HttpConnectionOverHTTP.close(HttpConnectionOverHTTP.java:182)
at java.util.ArrayList.forEach(ArrayList.java:1249)
at org.eclipse.jetty.client.AbstractConnectionPool.close(AbstractConnectionPool.java:193)
at org.eclipse.jetty.client.DuplexConnectionPool.close(DuplexConnectionPool.java:233)
at org.eclipse.jetty.client.HttpDestination.close(HttpDestination.java:372)
at org.eclipse.jetty.client.HttpClient.doStop(HttpClient.java:252)
at org.eclipse.jetty.util.component.AbstractLifeCycle.stop(AbstractLifeCycle.java:89)
at com.myproject.callback.client.http.MyProjectHttpClient.destroy(MyProjectHttpClient.java:243)
at org.springframework.beans.factory.support.DisposableBeanAdapter.destroy(DisposableBeanAdapter.java:262)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroyBean(DefaultSingletonBeanRegistry.java:578)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroySingleton(DefaultSingletonBeanRegistry.java:554)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.destroySingleton(DefaultListableBeanFactory.java:972)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroySingletons(DefaultSingletonBeanRegistry.java:523)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.destroySingletons(DefaultListableBeanFactory.java:979)
at org.springframework.context.support.AbstractApplicationContext.destroyBeans(AbstractApplicationContext.java:1006)
at org.springframework.context.support.AbstractApplicationContext.doClose(AbstractApplicationContext.java:982)
at com.myproject.MyProjectClassPathXmlApplicationContext.access$200(MyProjectClassPathXmlApplicationContext.java:10)
at com.myproject.MyProjectClassPathXmlApplicationContext$1.run(MyProjectClassPathXmlApplicationContext.java:49)
Caused by: java.nio.channels.AsynchronousCloseException: null
... 18 common frames omitted
发生这种情况是因为我发送了 SIGTERM 信号,而一些 HttpClient 请求被发送到 REST 服务器,但侦听器正在等待响应并且连接中断。
如何防止 HttpClient 终止当前连接,直到它们全部完成?(可能尊重超时)。
更新:显然这是 Jetty 本身不支持的东西(https://github.com/eclipse/jetty.project/issues/1445)。如果对于 HttpClient 上的每个目的地我检查其 connectionPool 是否为空,那可以吗?如果我做对了,这意味着该特定池不再有打开的连接。