后台 URLSession 卡住了

Background URLSession stuck

我正在使用 URLSession 将大量文件上传到服务器,因为上传的文件可能很大我正在使用 URLSessionConfiguration.background 以便我的上传可以在后台继续。

我的 url 会话声明如下:

urlSessionConfiguration = URLSessionConfiguration.background(withIdentifier: UploadQueue.uploadQueueIdentifier)
urlSessionConfiguration.sessionSendsLaunchEvents = true
urlSessionConfiguration.shouldUseExtendedBackgroundIdleMode = true
urlSessionConfiguration.allowsCellularAccess = true
urlSessionConfiguration.sharedContainerIdentifier = appGroup
backgroundUploadSession = URLSession(configuration: urlSessionConfiguration, delegate: self, delegateQueue: nil)

URLSessionUploadTask 总是在前台创建(我们使用后台会话只是为了确保任务可以完成)。

var request = try! URLRequest(url: url, method: .put)
backgroundUploadSession.uploadTask(with: request, fromFile: fileUrl).resume() 

当上传 ~ 100 个文件并留在前台时,所有必要的委托都已实现并正常调用。 然而,当上传大量文件(~1000)时,第一个文件正确上传但一段时间后会话似乎“卡住”并且没有回调被传递。 (仍然在前台使用应用程序) 我注意到如果我只是等待上传会在 ~5 分钟后重新开始。

我尝试用 URLSessionConfiguration.default 替换 URLSessionConfiguration.background(withIdentifier: UploadQueue.uploadQueueIdentifier),它在前台运行良好。 这是 URLSessionConfiguration.background 的错误还是我做错了什么?

经过调查发现有多个问题:

  1. 我们原以为 URLSessionConfiguration.httpMaximumConnectionsPerHost 会限制打开的连接数。但是,当使用 http/2 或服务器位于代理后面时,似乎没有遵守此限制。

解决方案:进行自己的连接限制(例如使用 DispatchGroup)

  1. 即使限制并发上传的数量,即使应用程序处于 前台,后台会话也会在一段时间后卡住。后台会话有一个速率限制器,但文档说当应用程序在后台时它不被认可。

解决方案:这是 discussed on Apple Developer Forum,这是 CF 网络框架中的错误。已提交错误报告。目前,解决方案是简单地不要创建太多带有小文件的后台会话。