簡體   English   中英

在 iOS 中使用 NSUrlSession 發送 SPDY 請求會導致“請求超時”錯誤

[英]Sending SPDY requests results in "The request timed out" errors with NSUrlSession in iOS

我的 iOS 應用程序從 nginx HTTP 服務器加載圖像。 在我發送了 400 多個這樣的請求后,網絡“卡住了”,所有后續的 HTTP 請求都會導致“請求超時”錯誤。 只有當我重新啟動應用程序時,我才能再次加載圖像。

細節:

  1. 我正在使用NSURLSession.sharedSession().dataTaskWithURL向 jpeg 文件發送四百個 HTTP GET 請求。
  2. 請求按順序發送,一個接一個。 請求之間的間隔為 10 毫秒。
  3. 使用NSURLSessionDataTask對象的cancel()方法取消每個先前未完成的請求。

有趣的是:

  1. 我只能在 HTTPS 請求和服務器上啟用 SPDY 時遇到這個問題。
  2. 非安全 HTTP 請求工作正常。
  3. 非 SPDY HTTPS 請求工作正常。 我通過在服務器端的 nginx 配置中關閉 SPDY 來測試它。
  4. 問題出現在 iOS 8 和 9、物理設備和模擬器上。 在 Wi-Fi 和 LTE 上。
  5. 當我查看 nginx 訪問日志時,我仍然可以看到進入的“卡住”請求。重要的細微差別:請求日志記錄出現在 iOS 應用程序在超時期限結束后放棄它的確切時刻。
  6. 我希望使用Charles Proxy分析 HTTP 請求,但是當請求通過 Charles 時問題會自行解決。 也就是說 - 一切都與查爾斯一起工作,就像量子力學中的效應,當觀察的事實影響結果時。
  7. 當 iOS 應用程序連接到兩個具有截然不同的 nginx 配置的不同服務器時,我能夠重現該問題。 這可能意味着該問題與特定的 nginx 設置無關。
  8. 我使用“活動監視器”工具分析了該應用程序。 它在批量 HTTP 請求期間使用的線程數從 5 跳到 10。相比之下,當我只發送一個 HTTP 請求時,線程數會跳到 8。CPU 負載很少超過 30%。

問題的原因是什么? 任何人都可以推薦其他方法或工具來分析和調試它嗎?

用調度工具分析

在此處輸入圖片說明

演示應用

這個演示應用程序 100% 地為我重現了這個問題。

https://github.com/exchangegroup/ImageLoadDemo

版本和設置

我的 nginx 配置: http : //pastebin.com/pYYjdxfP

OS X :10.10.4 (14E46), iOS :8 和 9, Xcode :7.0 (7A218), nginx :1.9.4

不理想的解決方法

只有當我為每個單獨的請求創建一個新的 NSURLSession 並使用finishTasksAndInvalidateinvalidateAndCancel清除上一個會話時,我才設法保持請求工作。

// 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 ...

一種可能是 iOS 開始發送請求,然后丟包導致 headers 和 request body 無法完全傳遞。

想到的另一種可能性是,您的服務器在實際完成嘗試交付之前可能不會記錄請求,這將使服務器日志中的時間戳與連接關閉的時間對齊,而不是連接打開的時間. (IIRC,這就是 Apache 所做的;我沒有使用過 nginx,所以我不能說它的行為。)如果是這種情況,那么這只是一個簡單的連接停頓。 至於為什么會卡頓,我猜不出來。

問題是否僅針對 HTTPS 流量發生? 如果你可以用 HTTP 重現它,你就不需要 Charles Proxy; 只需使用 OS X 的“Internet 共享”功能,並使用 tcpdump 或 wireshark 捕獲數據包,監聽橋接接口。 如果你不能用 HTTP 重現它,我的錢將用於獲取 CRL 或在驗證服務器證書時執行 OCSP 檢查的問題。

您的應用程序是否會因向新隊列過度異步調度而導致大量線程? 因為那很容易導致各種奇怪的不當行為。

超時時間是多久? 如果它太短,您的應用程序可能只是在運行時遇到硬件的性能限制,同時處理僅在四秒鍾內交付的 400 個請求的結果。

另外,您是否嘗試同時安排這些請求? 因為我似乎記得讀過一個錯誤,如果你在一個會話中同時啟動太多任務,它會導致 NSURLSession 撞到磚牆。 您可以僅在會話中的任務數量低於某個閾值后嘗試添加任務,看看是否能解決問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM