我有一个HttpClient来访问REST服务,现在我正在实现一个软关闭,这意味着当进程被关闭时(在linux上使用一个简单的kill命令),它应该停止接收新任务并完成它正在处理的所有任务。
我的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是否为空,这可以吗?如果我做得对,那就意味着这个特定的池没有更多的开放连接。
发布于 2018-02-15 11:28:52
最后,我实现了一个Phaser,以便根据对jetty github页面的评论来控制关闭的时间。
至于等待发送请求完成的问题,这很容易通过使用Phaser来实现,在发送请求时(从Request.QueuedListener轻松地完成)调用寄存器(),以及从Response.CompleteListener调用As ()。
https://stackoverflow.com/questions/48713817
复制相似问题