该项目旨在提供一种简单的优化网络通信的方法,重点关注使用NSOperationQueue,而不是仅仅使用NSURLConnection的异步API或使用GCD将工作卸载到次要队列,该队列对并发连接数的控制能力较弱,并且无法取消。该项目最初专注于多个文件(图片)的批量下载,未来可能更新以关注具有重试和恢复操作的API通信。
参考项目包括MVCNetworking和AFNetworking。这些项目有不同的重点,范围更广,这使得它们更难理解。使用Optimized Networking,我的目标是理解使用NSOperationQueue和GCD时,允许的并发操作数带来的不同性能现实。根据WWDC 2010的第207和208个会议,在GCD成熟之后,更倾向于使用NSOperationQueue,GCD可能可以开始使用。准备好了吗?如何限制连接数?取消操作怎么办?优先级怎么办?
下载操作使用一个DownloadItem对象,该对象被赋予一个优先级,它将转换为队列中的优先级。它还影响操作在添加到处理网络队列之前进行的排序。可以通过类别添加项,以便可以按类别取消它们。这些类别允许在管理性能和减少过度带宽使用方面具有一些灵活性。
另一种我已使用的方法是使用NSURLConnection的异步API和一个能够触发所有下载立即取消的通知。这是一个广义方法,通过与类别和下载优先级的优化而变得更加精确。
我当前的下载方案使用块和NSURLConnection的异步API以及下载项数组。每次下载完成时,它会以顺序方式开始下载下一项。下载不是并行的。使用NSOperationQueue,连接是并行的,可以设置为1、2、4、8、16或任何任意数量。将使用各种设置组合来确定下载一批图像的最佳方式。测试数据目前正在使用Flickr搜索API。每次下载的持续时间以及所有文件的总持续时间将有助于确定下载多张图片的最佳方式。
带宽是其中一个因素,而处理能力同样重要。利用 NSURLConnection 中的异步 API,在操作内部真正完成大部分工作且具有隔离性,应该使用最少的处理器周期来完成工作。由于并发操作的数目有限,这也应该减少处理器的需求,并主要受带宽限制。
最后,如果能够证明单个队列可以限制执行的块的数量以控制网络连接数,则可以完全切换到 GCD。取消连接仍然可以使用通知,这样可能成为实现相同优势的方式,无需使用 NSRunLoop 和处理线程隔离带来的其他问题。这种使用 GCD 的方式可能存在一些担忧。衡量这两种方法的性能和速度有助于确定快速下载文件和进行其他网络通信的最优方式。
使用线程很困难,这通常是许多问题的来源,所以苹果创建了 NSOperationQueue 以帮助开发者避免线程编程的麻烦。也许它更容易,但使用 NSOperationQueue 并不像我想象的那样简单。
首先,我有一个 NSOperationQueue 和一个从 NSOperation 继承的类。这个操作类有一些属性来传递操作的状态,队列使用键值观察(KVO)来确定操作何时就绪、正在执行和完成。改变状态需要调用 changeStatus:,这将产生 KVO 所需的调用。另一个非常重要的细节是,这个操作被设置为并发执行,这是使用 isConcurrent 属性设置的。使用 NSURLConnection 的异步 API 意味着这个操作是并发的,这意味着它需要使用 NSRunLoop 来处理回调。由于操作在隔离的线程上运行,因此使用运行循环来处理回调。为了整齐地设置一切,这个操作必须在同一线程上运行,而不是主线程,这个线程也在运行 NSRunLoop。您可以在苹果的 MVCNetworking 示例项目中查看所有这些细节,尽管它增加了许多超出本项目管理范围以外的细节。