iOS官方文档翻译iOS文档翻译iOS学习

设计真实世界的网络 <- 网络概述

2017-06-30  本文已影响9人  raingu24

在理想的世界,网络“只要运行”就可以。网络连接是可靠的、快速的、低延时的。在真实的世界,网络大多数时候是运行的,但它会断,它经常以匪夷所思的方式断开。例如:

虽然你的软件不可能修复一个真正断开的网络,但是糟糕的网络代码可以轻松地让事情变得更加糟糕。例如,假设一个服务器严重超载,并且需要45秒才能响应每个请求。如果你的应用连接到这个服务器设定了30秒超时,它占用了服务器的资源,但是却从没有成功接收过任何数据。

甚至在网络运行良好的情况下,糟糕的网络代码也会给用户带来问题——电池寿命降低、性能差等等。本章部分描述了无论是网络条件是否理想,应用都应该做到的事情,以便减轻用户的痛苦。

高效的使用电量和带宽

在写网络代码的时候,首先要考虑到的重要事情,是应用无论何时上传或下载数据,它都会消耗用户的时间和金钱。

网络操作消耗用户时间是因为:

网络操作也消耗用户的金钱是因为带宽不是免费的。这些花费包括:

作为一个网络软件的开发者,你有责任让你的应用的电量和带宽的消耗最小化。

批量传输,并尽可能的空闲

在编写通用代码的时候,你应该尽可能的执行更多工作,然后返回到空闲状态。这对于网络活动来说是双赢的。例如:

一次下载一点内容会导致两个问题。首先,他会使应用对细微的网络延迟非常敏感,造成停顿、视频卡顿等等。其次,它会一直让蜂窝网络或Wi-Fi无线电持续使用。这会浪费电量,特别是当应用和蜂窝网络连接通信的时候。如果应用在一小段时间下载大量数据,然后允许无线连接进入完全休眠,这会显著提高用户的电池寿命。

这同样适用于socket编程。除了少数例外(例如远程终端程序),你永远不要一次只发送少量字节。这样做在CPU负载方面是非常低效的,并会导致操作系统发送更多不必要的数据包。

尽可能下载最小可用资源,并在本地缓存资源

下载数据有很多与之相关的成本——电池寿命、性能、以及在多种情况下真实的数据传输成本。因此,你应该始终根据需要来下载最小化的资源。

例如,如果你有一个图片应用,它下载一系列大型图片,并以缩略图的方式呈现,那你应该在服务器端完成缩略图的加工。应用应该在一开始只下载缩略图,只有当用户选择了某个缩略图的时候,才下载全尺寸的图片版本。这样做有两个原因:

因为同样的原因,把下载资源保存在本地缓存,可以节省时间、带宽、以及电池寿命。想要做到这一点,当下载完数据之后,不再向服务器请求资源,而是向它请求有改变的资源。如果没有改变,就使用本地的副本。

在OS X和iOS中有很多高级APIs(例如NSURL)提供缓存支持(例如NSURLCache)。但是你你必须选择合适的缓存尺寸。无论你是使用内置的缓存API还是自建的,你都应该尝试使用缓存尺寸和替换策略来决定哪些对你的应用最有意义。

注意:这个目的和之前的目的(一次下载大量数据以便网络硬件变成闲置状态)之间经常存在冲突。
例如,考虑一个加载图像缩略图的应用。如果用户滚动几个被缩略图填充的屏幕,那么应用应该在一次下载足够多的图片来填充前面几个屏幕,以便网络硬件进入空闲状态。但是,如果用户基本上不滚动到第二屏,那么所有额外下载的图片就浪费了带宽
每个网络应用都应该平衡这种冲突。这取决于开发者的决定。

优雅的处理网络问题

在当今高度移动的世界,你不能再假设网络连接一旦建立,就会保持不变;或者认为带宽是不变的。这也就是说,唯一不变的是变化。作为一个开发者,你必须为这些常见的故障进行规划,并设计代码来恰当的处理它们。

为变动网络接口可用性设计

网络接口的可用性会因为无数原因而经常改变,特别是iOS。例如用户的如下行为:

因此,在写使用网络的应用的时候,必须准备好处理网络故障。当网络故障发生的时候,应用应该基于多种考虑来决定做什么,最重要的是,这个请求是否由用户明确指定的。

对于用户要求的请求:

对于后台提出的请求:

重要:检查可达性标识不保证你的流量将不通过蜂窝网络连接发送。详见Restrict Cellular Networking Correctly。

应用应该能够优雅的响应当前网络接口的改变。为了支持这点,使用SCNetworkReachabilityAPI。通过注册网络改变通知,应用可以在可用的网络接口改变的时候收到警告。Reachability样本代码演示了注册回调,它会在当前网络接口改变时响应接到的通知。阅读SCNetworkReachability Reference,可看到对于SCNetworkReachability的完整讨论。

重要:SCNetworkReachabilityAPI不适用于确定网络连接的预检机制。你通过尝试连接来确定网络的连接。如果连接失败,查阅SCNetworkReachability API来帮助诊断导致失败的原因。

无论请求是用户产生的还是还是后台产生的,SCNetworkReachabilityAPI提供一个很好的方式来查看接口可达性的改变。当你使用的网络接口消失时,你应该快速的重连,来避免给用户带来不必要的延迟感。

还有,在iOS中,如果你连接的是蜂窝网络,你应该在Wi-Fi服务再次可用的时候快速在后台进行重连。Wi-Fi连接使用更少的电量,通常也更快,且比蜂窝网络省钱。

为变动的网络速度设计

应用必须为网络速度的改变做好准备,即便当前的网络接口不改变也要如此。例如,当一个移动设备用户改变位置时,Wi-Fi或者蜂窝网络的性能会显著变化,可能是因为干扰的增减,也可能是因为设备切换到了繁忙的基站。这种变化甚至不需要有太大的位置变化;从一个房间走到另一个房间,就可能会产生显著的网速变化。

此外,即便忽略争用和干扰,接口本身也没有告诉你有关全路径的真实带宽。当用户尝试连接Google的时候Wi-Fi网络可能是最快的,但是在用户和服务器之间的路由可能经过蜂窝网络或者卫星网络。类似的,用户可能有一个千兆以太网来连接局域网上的服务器,但与外部世界只有128k的上行连接。由于这个原因,你不应该基于当前的网络接口对网速进行假定。

只有一种方式可以确定网速:使用它。在你下载少量的数据之后,你可以对网速进行初步的估算。你应该持续监控你的下载速率来保持精确的估算,然后相应地调整你的预期。例如,如果你正在传输视频流,当确定视频流的帧率不能够维持播放的时候,你应该切换到较低带宽流来支持播放,用户不会感受到这种变化。如果之后下载速度提高,你可以再切换回来。

为高延时设计

作为开发者,要假设用户可能会使用高延时的连接。高延时在一些蜂窝网络接口类型上是特别常见的,因为它给设备使用的时隙有限。例如,在EDGE连接上的往返延时通常以秒计。但是在卫星连接或一般忙碌的DSL连接,如果应用设计时对此没有估计的话,即使是半秒钟的延时也会造成严重的问题。

当应用向多个远程主机发送多个请求时,如果它在创建第二个请求之前需要等待第一个请求的返回结果,连接延迟会相加。两次请求之间的延时会不断累加。

为了避免这个问题,当应用需要发送任何彼此不相互依赖的多个信息时(资源请求、确认等等),同时发送它们要比一个个的发送要好。图1-1说明了同时发送多个信息应用获得的增速。

图1-1 比较同时和顺序请求的响应时间

如果在iOS应用中使用NSURLConnection,你可以通过启用HTTP管道(pipelining)很轻松的获得增速。当管道被启用时,你的连接自动同时发送多个HTTP请求。通过调用你提供给连接的NSMutableURLRequest对象的setHTTPShouldUsePipelining:方法来启用管道。

注意:一些服务器不支持管道。如果你连接到的服务器不支持管道,这个连接依然工作,但不会提高性能。

在各种条件下测试

Xcode提供了一个名为Network Link Conditioner(网络链接调节器)的工具,它能模拟各种网络条件,包括减少带宽、高延时、DNS延时、丢包等等。在你准备发布任何使用网络的软件之前,你应该安装这个工具,启用它,然后运行你的应用来查看它在真实条件下的性能。

有几件需要测试的事:

你或许还可以发现使用一些第三方工具(例如tcptrace),可以帮助你在恶劣网络条件下对应用的网络访问模式进行可视化观察。

上一篇下一篇

猜你喜欢

热点阅读