在一个循环中,我遇到了1000个GET请求。由于请求太多,并且网关无法处理它,因此失败并显示错误代码502。解决此问题的最佳方法是什么。我的代码如下。
//In the array there are about 10000 ids
for id in Array {
Network.shared.getData(accountId: id ?? "", successBlock: {(result) in
//Save results to coredata
}) {(errorCode:Int, error:String) in
print(errorCode, error)
}
}
后来我的Singleton Network不能以上述方式调用下面的方法。
class Network: NSObject {
//These blocks catches success & failures
typealias SuccessBlock = (Any) -> Void
typealias FailureBlock = (_ errorCode: Int, _ error: String) -> Void
private static var networkCalls: Network?
private override init() {}
public static var shared: Network {
if networkCalls == nil {
networkCalls = Network()
}
return networkCalls!
}
private lazy var configurationManager: URLSession = {
let configuration = URLSessionConfiguration.default
configuration.allowsExpensiveNetworkAccess = true
configuration.allowsConstrainedNetworkAccess = true
configuration.allowsCellularAccess = true
configuration.timeoutIntervalForRequest = 60
configuration.timeoutIntervalForResource = 60
configuration.httpMaximumConnectionsPerHost = 2
let manager = URLSession(configuration: configuration)
return manager
}()
在上面的类中,我使用通用方法来调用HTTP请求(此处我没有显示带有所有参数的完整方法,但是您可以了解它的外观)
private func performWebServiceRequest(with url: URL, contentType: CONTENT_TYPE? = nil, requestOptions: [String: String]?,successBlock: @escaping SuccessBlock, failureBlock: @escaping FailureBlock) {
let request = NSMutableURLRequest(url: url)
request.httpMethod = requestType // As in "POST", "GET", "PUT" or "DELETE"
request.cachePolicy = NSURLRequest.CachePolicy.reloadIgnoringCacheData
let task = configurationManager.dataTask(with: request as URLRequest) { (data, response, error) in
guard let data: Data = data, let response: URLResponse = response, error == nil else
{return}
do {
let result = try JSONDecoder().decode(type, from: data)
successBlock(result)
} catch {
failureBlock(0,errorMessage)
}
}
task.resume()
}
答案 0 :(得分:0)
您可以使用DispatchSemaphore
来限制并行运行任务的数量,如下所示:
var countedSemaphore = DispatchSemaphore(value:500) // Allow 500 parallel network calls
var queue = DispatchQueue(label: "runner", qos: .background, attributes: .concurrent)
//In the array there are about 10000 ids
for id in Array {
queue.async { //(1)
countedSemaphore.wait() // (2)
Network.shared.getData(accountId: id ?? "", successBlock: {(result) in
countedSemaphore.signal() // (3a)
//Save results to coredata
}) {(errorCode:Int, error:String) in
countedSemaphore.signal() // (3b)
print(errorCode, error)
}
}
}
该示例使用自定义的并发队列(1)创建将启动网络获取的任务。
在任务中,我们首先使用wait
(2)作为信号量。只要该计数器大于零,此调用将简单地减少信号量的计数器。如果计数器为零,则wait
调用会阻塞。
wait
返回后,我们称为getData
。
在成功(3a)和错误(3b)处理程序中,我们在信号量上调用signal
,以表明我们已完成网络调用。 signal
将增加计数器或唤醒任何等待的呼叫。
此构造可确保最多并行运行500个getData
调用