2014-11-01 35 views
2

設置AFNetworking請求操作 - 創建一個漏斗/瓶頸隊列單

我在我的程序兩個方面 - branch 1branch 2 - 去哪兒網請求在同一時間做出異步1併發GET請求,每個區。一次發送請求1次,因爲服務器對任何向服務器發出請求的用戶都有一個很小的幾毫秒的寬限期。一次運行1個併發請求的目的是幫助這個寬限期。

該操作已完成,因此如果在任何分支中有任何請求失敗 - 則有一個失敗保險,只需再次重複請求即可。

問題:

當我彼此分開地運行這些分支,即不同時,服務器是高興。但是,只要我允許兩個操作同時發生,服務器就會拋出一個429錯誤,該錯誤是讓用戶知道there are too many requests coming in at any one time的錯誤。然後會發生的是,有一半的請求失敗,然後由於失敗保護,請求將再次發送進行處理,直到它們全部完成。 代表用戶的數據包浪費時間和資源。

方案

Branch 1發出10個請求(通常它的數千內,處理一次一個,但是爲了簡單起見,我們將保持在10)。 這10個請求將被同時處理1,並且一次很快地返回,並返回相應的數據對象。

現在,如果我們再次branch 1操作運行 - 同時10個請求,然後添加branch 2's 10個請求,這將創造20個請求操作 - 的兩倍多 - OUT將服務器,這將導致大約一半的請求從兩個分支1和2失敗,隨着故障安全,然後踢入重新發送這些請求操作。號泣。

問題

有沒有辦法漏斗這些請求操作出來我的申請,無論在哪裏,這兩個分支我的應用程序內鋪設,使我們可以控制和瓶頸請求操作外出服務器以便服務器不會受到只有一半請求失敗的請求的轟炸?

可能的解決方法

我有一個想法是創建一個單,將作爲一個隊列以及瓶頸需要的,讓我能夠從任何分支內我的代碼庫的任意位置添加請求操作 - 因此,爲什麼我認爲單身人士會是一個好主意 - 然後一旦它意識到請求操作已被添加到隊列中,然後讓隊列同時運行1個併發請求。

我認爲這對我的工作很好,我只是不知道如何處理請求的完成塊,因爲從Branch 1的請求操作與請求操作的完成塊Branch 2不同。

您將如何管理?我們可以做些什麼嗎?


編輯1 - 目前我在做什麼

分支1 - 使用AFHTTPOperation:

1)對於每一個過程中,我創建一個for循環迭代10次加10 AFHTTPRequestOperation s到稱爲multipleOperations的NSMutableArray類型的本地數組。

2)I然後陣列添加multipleOperations到batchOfRequestOperations方法如下所示:

NSArray *operations = [AFURLConnectionOperation batchOfRequestOperations:muiltipleOperations 
         progressBlock:^(NSUInteger numberOfFinishedOperations, NSUInteger totalNumberOfOperations){ 
//Do some stuff here for each iteration 
} 
completionBlock:^(NSArray*operations){ 
//Call the method that repeats this process again. 
}]; 

3)I然後添加操作到mainQueue像這樣

[[NSOperationQueue mainQueue] addOperations:operations waitUntilFinished:NO]; 

現在我不知道在分支1中的這個過程是否設置爲1 concurrenncy,不能看到它是:\

在分支2中使用NSURLSessionDataTa sk(剛剛意識到,如果他們都使用相同的子類,會不會更容易?笑

我注意到,我使用的是AFHTTPSessionManager創建NSURLSessionDataTasks ..這犯規在for循環中運行,而是調用送出了自己的另一請求方法每次請求執行它自己完成的塊。因此,只要分支2中的前一個請求完成,它就會一直保持自己的調用狀態。這就是我知道它同時只運行一個請求的方式。所以這很好。

有沒有辦法讓這個更清潔?我使用HTTPRequestOperationManager其中

無:(有人可以告訴我怎麼事情可以做正確?

謝謝。

+1

既然你正在使用'AFNetworking',你不能只是設置'AFHttpRequestOperationManager'的基礎'NSOperationQueue'來使'maxConcurrentOperationCount'爲'1'嗎?這樣,它只會一次發送一個請求,而不管它來自哪個分支(當然,假設你正在使用'[AFHttpRequestOperationManager manager]'singleton)。 '[[AFHttpRequestOperationManager manager] operationQueue] .maxConcurrentOperationQueue = 1;' – 2014-11-01 20:06:36

+0

是的,但是當你同時運行這些分支時他們不知道另一個分支正在運行,所以他們都會發送兩個併發操作 - 在同時,這導致一半的請求失敗,因爲服務器很高興接收來自一個分支的請求的速率。 這就是爲什麼我提出的場景,看看是否有一個方法適用於我的所有請求操作,無論哪個分支來自ALL隊列,然後讓最終隊列運行1個併發操作,也能夠處理完成塊 – Pavan 2014-11-01 21:03:51

+0

您是否爲每個分支使用不同的AFHttpRequestOperationManager? – 2014-11-01 21:10:33

回答

1

根據您的編輯,我可以看到一些東西,你可能會想改變。首先,是的,這將是容易,如果您使用AFHTTPOperation S或NSURLSessionDataTask S,但不能兩者兼得。

如果你打算使用AFHTTPOperation,那麼就不要在排隊的操作[NSOperationQueue mainQueue]他的理由是,這是主要的UI隊列,你不希望你的網絡操作阻止它。你應該做的是創建自己的NSOperationQueue及其併發設置爲1

NSOperationQueue *networkQueue = [[NSOperationQueue alloc] init]; 
networkQueue.maxConcurrentOperationCount = 1; 

使用你的單身的想法來存儲隊列的地方,你可以從你的應用程序在任何地方訪問將是一個很好的路要走關於確保您通過同一隊列發送所有網絡操作。

這就是說,我建議使用NSURLSessionDataTaskAFHTTPSessionManager而不是。 AFNetworking狀態的文檔:

針對iOS 7或Mac OS X 10的開發人員。9或更高版本與Web服務廣泛交易 鼓勵子類 AFHTTPSessionManager,提供一種類方法,該方法返回一個共享的 單身對象,其中身份驗證和其他配置可以在應用程序之間共享認證和其他配置 。

這聽起來像是一個很好的方法來完成你想要的。基本上你會用類方法創建一個AFHTTPSessionManager的子類,它創建一個用自定義NSURLSessionConfiguration初始化的實例。您可以配置NSURLSessionConfiguration但是適合你的應用程序,但主要屬性,你會感興趣的這個具體問題就是HTTPMaximumConnectionsPerHost

此屬性決定給每臺主機同時做出連接 的最大數量基於此 配置的會話中的任務。

用那一套來1,可以讓AFHTTPSessionManager(當然,實際上,NSURLSession)擔心確保只有一個請求,在任何給定的時間到您的服務器。

這些方針的東西:

@interface AppHTTPSessionManager : AFHTTPSessionManager 

+ (instancetype)appSession; 

@end 

@implementation AppHTTPSessionManager 

+ (instancetype)appSession { 
    static AppHTTPSessionManager *_appSession = nil; 
    static dispatch_once_t onceToken; 
    dispatch_once(&onceToken, ^{ 
     NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration]; 
     configuration.HTTPMaximumConnectionsPerHost = 1; 
     _appSession = [[AppHTTPSessionManager alloc] initWithSessionConfiguration:configuration]; 
    }); 
    return _appSession; 
} 

@end 

然後,每當你想使網絡電話,請確保您從[AppHTTPSessionManager appSession]創建NSURLSessionDataTask。如果這樣做,這些任務應該自動限制爲一次向服務器發送一個請求。

+0

感謝你回到我身邊。我結束了使用AFHTTPOperationManager和使用它的'隊列'屬性,我將所有操作附加到該共享管理器的隊列設置在1併發。我認爲它會做的。但是,您建議使用'AFHTTPSessionManager'的麥克風,我認爲將這些問題附加到隊列的問題是正確的嗎?會話管理器不是用於操作等。糾正我,如果我錯了,我讀它的地方。你可以點亮一下嗎?我需要排隊數百個請求,並添加一切工作在我的最後,有大量的回調。 – Pavan 2014-11-03 08:20:02

+0

請參閱http://stackoverflow.com/a/21422293/445312以供參考。謝謝你@MikeS – Pavan 2014-11-03 13:16:07

+0

你鏈接的答案中的選項1和4與我在這個答案中的建議非常相似,並且可以正常工作。我推薦使用'AFHTTPSessionManager'的主要原因是它使用了Apple提供的更新的API,可以更好地控制某些事物,併爲後臺網絡任務提供更好的支持等。從AFHTTPSessionManager創建的任務真的沒有任何理由'不能用在'NSOperationQueue'中,只是沒有內建的方法,所以你必須編寫自己的'NSOperation'包裝器(選項2在你鏈接的答案中)。 – 2014-11-03 17:13:03