[英]Sending SPDY requests results in "The request timed out" errors with NSUrlSession in iOS
My iOS app loads images from an nginx HTTP server.我的 iOS 应用程序从 nginx HTTP 服务器加载图像。 After I send 400+ such requests the networking 'gets stuck' and all subsequent HTTP requests result in "The request timed out" error.
在我发送了 400 多个这样的请求后,网络“卡住了”,所有后续的 HTTP 请求都会导致“请求超时”错误。 I can make the images load again only when I restart the app.
只有当我重新启动应用程序时,我才能再次加载图像。
Details:细节:
NSURLSession.sharedSession().dataTaskWithURL
to send four hundred HTTP GET requests to jpeg files.NSURLSession.sharedSession().dataTaskWithURL
向 jpeg 文件发送四百个 HTTP GET 请求。cancel()
method of NSURLSessionDataTask
object.NSURLSessionDataTask
对象的cancel()
方法取消每个先前未完成的请求。 Interestingly:有趣的是:
What can be the cause of the issue?问题的原因是什么? Can anyone recommend other ways or tools for analysing and debugging it?
任何人都可以推荐其他方法或工具来分析和调试它吗?
This demo app reproduces the issue 100% of the time for me.这个演示应用程序 100% 地为我重现了这个问题。
https://github.com/exchangegroup/ImageLoadDemo https://github.com/exchangegroup/ImageLoadDemo
My nginx config: http://pastebin.com/pYYjdxfP我的 nginx 配置: http : //pastebin.com/pYYjdxfP
OS X : 10.10.4 (14E46), iOS : 8 and 9, Xcode : 7.0 (7A218), nginx : 1.9.4 OS X :10.10.4 (14E46), iOS :8 和 9, Xcode :7.0 (7A218), nginx :1.9.4
I managed to keep requests working only if I create a new NSURLSession for each individual request and clear the previous session with finishTasksAndInvalidate
or invalidateAndCancel
.只有当我为每个单独的请求创建一个新的 NSURLSession 并使用
finishTasksAndInvalidate
或invalidateAndCancel
清除上一个会话时,我才设法保持请求工作。
// Request 1
let configuration = NSURLSessionConfiguration.defaultSessionConfiguration()
let session = NSURLSession(configuration: configuration)
session.dataTaskWithURL ...
// Request 2
// clear the previous request
session.finishTasksAndInvalidate()
let session2 = NSURLSession(configuration: configuration)
session2.dataTaskWithURL ...
One possibility is that iOS started sending the request, and then packet loss prevented the headers and request body from being fully delivered.一种可能是 iOS 开始发送请求,然后丢包导致 headers 和 request body 无法完全传递。
Another possibility that comes to mind is that your server may not be logging the request until it actually finishes trying to deliver it, which would make the time stamps in the server logs line up with when the connection was closed, rather than when it was opened.想到的另一种可能性是,您的服务器在实际完成尝试交付之前可能不会记录请求,这将使服务器日志中的时间戳与连接关闭的时间对齐,而不是连接打开的时间. (IIRC, that's what Apache does; I haven't worked with nginx, so I can't speak for its behavior.) If that's the case, then this is just a simple connection stall.
(IIRC,这就是 Apache 所做的;我没有使用过 nginx,所以我不能说它的行为。)如果是这种情况,那么这只是一个简单的连接停顿。 As for why it is stalling, I couldn't guess.
至于为什么会卡顿,我猜不出来。
Does the problem occur exclusively for HTTPS traffic?问题是否仅针对 HTTPS 流量发生? If you can reproduce it with HTTP, you don't need Charles Proxy;
如果你可以用 HTTP 重现它,你就不需要 Charles Proxy; just use OS X's "Internet Sharing" feature, and capture the packets with tcpdump or wireshark, listening on the bridge interface.
只需使用 OS X 的“Internet 共享”功能,并使用 tcpdump 或 wireshark 捕获数据包,监听桥接接口。 If you can't reproduce it with HTTP, my money would be on a problem with fetching the CRLs or performing the OCSP check while validating the server's certificate.
如果你不能用 HTTP 重现它,我的钱将用于获取 CRL 或在验证服务器证书时执行 OCSP 检查的问题。
Is your app ending up with a huge number of threads as a result of excessive async dispatching to new queues, by any chance?您的应用程序是否会因向新队列过度异步调度而导致大量线程? Because that could easily cause all sorts of odd misbehavior.
因为那很容易导致各种奇怪的不当行为。
How long is the timeout?超时时间是多久? If it is too short, your app might simply be running up against performance limitations of the hardware while processing the results of 400 requests delivered in only four seconds.
如果它太短,您的应用程序可能只是在运行时遇到硬件的性能限制,同时处理仅在四秒钟内交付的 400 个请求的结果。
Also, are you trying to schedule these requests simultaneously?另外,您是否尝试同时安排这些请求? Because I seem to recall reading about a bug that causes NSURLSession to hit a brick wall if you start too many tasks in a single session at the same time.
因为我似乎记得读过一个错误,如果你在一个会话中同时启动太多任务,它会导致 NSURLSession 撞到砖墙。 You might try adding tasks only after the number of tasks in a session drops below some threshold and see if that fixes the problem.
您可以仅在会话中的任务数量低于某个阈值后尝试添加任务,看看是否能解决问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.