根本原因出现在Jetty HttpClient连接管理或线程管理的底层。通常,Jetty HttpClient会生成一组线程来处理HTTP GET(见下文),这些线程会按照您的预期启动和消失。在大约40小时或操作之后,JDK VisualVM显示至少9个连接线程不会立即消失:
也
总共九到十个线程。在下一次读取时,创建新的线程实例来承载负载,然后客户端继续执行。此外,应用程序。有一个带有专用线程的时钟,它在应用程序锁定后继续运行,这表明JVM、操作系统和机器本身都很好。
有时,我们会看到这些“卡住”的线程在退出VisualVM线程显示之前停留长达一个小时。至少36小时后,我们看到线仍然存在,但我们没有看到它们消失。
/**
* GET
* @return null or string returned from server
**/
public static String get( final String command ){
String rslt = null;
final String reqStr = "http://www.google.com"; // (any url)
HttpClient httpClient = new HttpClient();
Request request;
ContentResponse response;
try {
//-- Start HttpClient
httpClient.start();
request = httpClient.newRequest( reqStr );
response = request.send();
if( null == response ){
LOG.error( "NULL returned from previous HTTP request.");
}
else {
if( (501 == response.getStatus()) || (502 == response.getStatus()) ){
setNetworkUnavailable(String.format("HTTP Server error: %d", response.getStatus() ));
}
else {
if( 404 == response.getStatus() ){
Util.puts(LOG,"HTTP Server error: 404");
// ignore message since we are talking to an old server
}
else if( 200 == response.getStatus() ){
rslt = response.getContentAsString();
}
else {
LOG.error(String.format( " * Response status: \"%03d\".", response.getStatus() ));
}
setNetworkAvailable();
}
}
}
catch ( InterruptedException iEx ){
LOG.warn( "InterruptException processing: "+reqStr, iEx );
}
catch ( Exception ex ){
Throwable cause = eEx.getCause();
if( (cause instanceof NoRouteToHostException) ||
(cause instanceof EOFException) ||
(cause instanceof SocketException)
&& cause.getMessage().startsWith( EX_NETWORK_UNREACHABLE ) ){
setNetworkUnavailable( cause.getMessage() );
}
else {
LOG.error( "Exception on: "+command, ex );
}
}
finally {
try {
httpClient.stop();
}
catch ( Exception ex ){
LOG.error( "Exception httpClient.stop(), ServerManager::get()", ex );
}
}
return rslt;
}//get method
这是基于简单的示例,关于使用HttpClient的细节很少。一切都是按照霍伊尔做的吗?
在不同的执行运行中,我们还会看到以下异常和日志消息:
我们想知道这条消息是否与其中一条被卡住的线程有关?或者,这个消息是否表明了我们需要检查的一个单独的、不同的问题?还有:
这似乎是线程超时异常。哪条线呢?这与HTTP连接线程有关吗?我认为,服务在内部捕获错误时,至少可以指示错误的位置和堆栈跟踪。
有一些明显的问题:
另一个观察是,当我们在VisualVM中“卡住”线程时,它会在threads面板中显示多余的守护进程线程,而不是增加非守护进程线程。
通过在for循环中运行上面所示的代码大约3或4个小时,在HttpClient send()调用之间间隔250毫秒,就会显示线程泄漏--在Linux上重现很简单。日志输出显示在距离线程泄漏至少30分钟的网络上没有警告和只有两个超时错误。
欢迎提出建议、意见、改进和答复。我们提前表示感谢。
相关问题:
这些问题涉及一些非常相似的问题
这种情况似乎要通过确保两件事来解决。
这两种行为是相互关联的。如果HttpClient有时漏掉异常或错误,线程就会挂起。避免这种情况的唯一方法似乎是确保使用的每个HttpCLient都调用HttpCLient.stop()。这需要在最后{...}子句。
线程的数量将取决于您的应用程序。我建议使用jVisualVM或类似的工具来确保您的Jetty线程在优化线程池中的线程数量之前都得到了正确的清理。
我觉得文档需要强调清理,并确保调用stop()。而且据我所知,关于如何结束异步调用的信息还没有文档记录。只要您的Jetty调用完全停止,那么提供足够的线程似乎可以解决这一问题--通常需要注意管理并发。
上下文: Netty 3.6.3。最终,Java1.7,Scala 2.9. x 为了最大限度地减少(可能空闲的)线程数量,我想与不同的NIO套接字通道工厂(TCP)和一个NioDatagramChannelFactory共享NIO客户端/服务器和工作池。我使用至少两个(或三个与Finagle堆栈)服务器/客户端引导集,每个都有自己的NIO套接字通道工厂。为每个老板和工作池使用新的缓存线程池会导致
我很难清楚地理解MySQL5.6使用/r/t memcache引入了什么。 按照我的理解,memcache本身本质上是一个巨大的、共享的、驻留内存的哈希表,由服务器memcached管理。特别是,它对持久数据存储一无所知,也不提供这方面的服务。它只知道键和值(像Perl散列)。 我认为MySQL5.6引入的是NoSQL API,mySQL客户端可以通过键而不是通过SELECT语句从mySQL服务器
当我尝试使用读取此pod的日志时,它不会返回任何内容。如何查看日志以了解状态为“挂起”的原因?
我正在使用路线距离估算大型城市网络的最后一英里交付成本。我有8000多名客户代理和100多名零售店代理,他们使用纬度/经度坐标绘制在GIS地图上。每个客户都会从最近的商店(通过路线)收到货物。目标是在该网络中为每个门店获取两个距离度量: d0_bar:从商店到所有指定客户的平均距离 d1_bar:单个商店共有的所有客户之间的平均距离 我编写了一个启动函数,其中包含一个简单的foreach循环,可以
在React中开发验证功能。我是一个新手,不想在学习的同时养成任何坏习惯,所以我正在寻找关于如何清理这里的代码块的建议。 该函数检查输入字段,如果它们为空,则将适当的消息附加到数组。检查所有输入字段后,如果该数组为空,则继续提交表单。如果该数组包含错误消息,则该消息将显示到屏幕(未显示) 只是在寻找清理我的条件语句的方法,如果可能的话!谢谢
我正在使用Java 8构建一个使用SpringBoot和SpringREST服务的API。我刚刚发现了Swagger API,现在我想让我的API与Swagger兼容。 据我所知,Swagger是一个记录您的APIS的工具,而且还提供了从规范(swagger.jsonv2中)生成客户端和服务器代码的功能,以及与您的API交互的漂亮Web界面。 现在,我想要一些关于如何继续的建议,因为我已经有了一个