简体   繁体   English

HttpClient 长时间停滞,即使设置了超时参数

[英]HttpClient stalls for long periods of time, even with timeout parameters set

I have an app that is doing a non trivial amount of downloading of thumbnail images and other resources from a remote service.我有一个应用程序正在从远程服务中下载大量的缩略图和其他资源。

I'm using a single instance of DefaultHttpClient and a custom class that I wrote that schedules all of my downloads.我正在使用 DefaultHttpClient 的单个实例和我编写的自定义 class 来安排我的所有下载。 All downloading is run in serial on background threads via AsyncTask.所有下载都通过 AsyncTask 在后台线程上串行运行。 I don't re-run my download routine until onPostExecute gets executed in the AsyncTask.在 AsyncTask 中执行 onPostExecute 之前,我不会重新运行我的下载例程。

This often works perfectly.这通常非常有效。 If I queue up 20 images, my scheduler does its thing just fine.如果我将 20 个图像排队,我的调度程序就可以正常工作。 However, I run into cases where the procedure just stalls at the point of calling client.execute (where client is my instance of DefaultHttpClient).但是,我遇到了程序在调用 client.execute 时停止的情况(其中 client 是我的 DefaultHttpClient 实例)。 I can inexplicably resuscitate the process by navigating around the app and doing random actions (scrolling a list, navigating back and forth between activities, etc).我可以通过浏览应用程序并执行随机操作(滚动列表、在活动之间来回导航等)来莫名其妙地恢复该过程。 It's as if something I'm doing is sending a "wake up" message to a thread that has stalled or deadlocked.就好像我正在做的事情是向已停止或死锁的线程发送“唤醒”消息。

I've added an obnoxious amount of logging at all moving parts of my application to see if something external to this procedure is causing some kind of deadlock condition.我在我的应用程序的所有移动部分添加了大量令人讨厌的日志记录,以查看此过程之外的某些东西是否导致某种死锁情况。 I view LogCat by pid to see if anything else is happening in my process at the point of stalling or at the point of resuming, and I don't see anything whatsoever out of the ordinary.我通过 pid 查看 LogCat 以查看在停止或恢复时我的进程中是否发生了其他任何事情,并且我没有看到任何异常情况。 The weirdest part about this is that I can duplicate the exact condition over and over.最奇怪的部分是我可以一遍又一遍地复制确切的条件。

FWIW, I have set socket timeouts and connection timeouts on both the HttpClient instance and the HttpGet instance that I pass to the execute method. FWIW,我在传递给执行方法的 HttpClient 实例和 HttpGet 实例上都设置了套接字超时和连接超时。 This does not cause the execute method to return early or throw an exception or anything like that.这不会导致执行方法提前返回或抛出异常或类似的东西。 When the procedure "kicks back in", HttpClient.execute returns a valid HttpResponse and everything operates as normal.当程序“重新启动”时,HttpClient.execute 返回一个有效的 HttpResponse,一切正常运行。

Any ideas on things I can debug to find out where this is getting tripped up?关于我可以调试以找出问题所在的任何想法? I recognize that this is a very specific condition, but are there any advanced methods for specifically debugging DefaultHttpClient or http traffic in Android in general?我认识到这是一个非常具体的情况,但是一般来说,有没有什么高级方法可以专门调试 Android 中的 DefaultHttpClient 或 http 流量?

Thanks!谢谢!

Do you share the same HttpClient across threads?您是否跨线程共享相同的 HttpClient ? It's not thread-safe by default, so you might want to check that.默认情况下它不是线程安全的,因此您可能需要检查一下。 Most likely it's blocking on I/O though, so you should do some wire debugging.很可能它在 I/O 上阻塞,所以你应该做一些线调试。 You can use something like this to enable HttpClient wire dump logs:您可以使用类似这样的东西来启用 HttpClient 线转储日志:

Logger.getLogger("org.apache.http.wire").setLevel(Level.FINEST);
Logger.getLogger("org.apache.http.headers").setLevel(FINEST);
Logger.getLogger("httpclient.wire.header").setLevel(FINEST);
Logger.getLogger("httpclient.wire.content").setLevel(FINEST);

System.setProperty("org.apache.commons.logging.Log",
     "org.apache.commons.logging.impl.SimpleLog");
System.setProperty("org.apache.commons.logging.simplelog.showdatetime", "true");
System.setProperty("org.apache.commons.logging.simplelog.log.httpclient.wire", "debug");
System.setProperty("org.apache.commons.logging.simplelog.log.org.apache.http", "debug");
System.setProperty("org.apache.commons.logging.simplelog.log.org.apache.http.headers", "debug");

To enable it, execute the following shell commands.要启用它,请执行以下 shell 命令。 Wire logs will be output to logcat:线日志将 output 到 logcat:

adb shell setprop log.tag.org.apache.http VERBOSE 
adb shell setprop log.tag.org.apache.http.wire VERBOSE 
adb shell setprop log.tag.org.apache.http.headers VERBOSE

I have had a similar problem before.我以前也遇到过类似的问题。 When I try to do HTTP get in an queue, the method httpClient.execute(get);当我尝试做 HTTP 进入队列时,方法httpClient.execute(get); will not return a response, like deadlock.不会返回响应,例如死锁。

HttpResponse response = httpClient.execute(get);
HttpEntity entity = response.getEntity();

This is my code, and what I do is call entity.consumeContent();这是我的代码,我所做的是调用entity.consumeContent(); then it works.然后它工作。

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM