【iOS】iOS网络优化方案

1、DNS映射

无论是HTTP还是Socket长连接,第一步都要经过DNS解析出ip,然后再根据ip去拿对应的资源。在这个过程中,如果LocalDNS中存在这个域名对应的ip,就会直接返回这个ip,类似于App内做的缓存。如果不存在,才会去权威DNS查询该访问哪个ip,然后查询到的ip会在LocalDNS中做缓存。然而在iOS设备上几乎每次断网重连,重启设备都会使LocalDNS缓存失效,触发重新查询。
同时,LocalDNS缓存的存在还会引发一些问题。如果之前访问api.weibo.cn的是联通用户,现在新用户使用电信来访问api.weibo.cn,由于localDNS缓存的存在,不会去查询新浪的权威DNS,这样返回的ip是联通这个运营商的ip,从而会使得用户出现访问变慢等状况。
缓存还会导致一点就是,当权威DNS将域名与ip的映射发生改变之后,由于LocalDNS缓存没有及时改变,用户就会访问到错误的服务器,或者直接访问不到资源。还有很多三四级运营商会把域名解析指向他们的缓存服务器上,并把网页里面的广告替换成他们自己的,或者内嵌他们自己的广告。
HttpDNS基于Http协议和域名解析的流量调度解决方案,可以在很大程度上防止上面的问题出现。

HttpDNS原理:

A、客户端直接访问HttpDNS接口,获取业务在域名配置管理系统上配置的访问延迟最优的IP。(基于容错考虑,app内肯定是需要保留使用运营商LocalDNS解析域名方式的。)
B、客户端获取到IP后就直接往此IP发送业务协议请求。以Http请求为例,通过在header中指定host字段,向HttpDNS返回的IP发送标准的Http请求即可。

基于HttpDNS扩展:

A、在App内维护一个Serve IP List。把每次App从HttpDNS取到的ip存储进入该数组,并设置权重,理论上来说从HttpDns解析下来的ip权重是最大的。这个List可以在App启动的时候,进行更新,同时取出本地缓存的Serve IP List的权重最大的ip进行数据的初始化操作(如果第一次启动,没有该List的话,就使用LocalDNS进行解析)。Serve IP List里面的权重设置机制,很明显的一点就是从DNS解析出来的ip具有最大的权重,每次从List里面取ip应该要取权重最大的ip。列表中的ip也是需要可以动态更新配置的,根据连接或者服务的成功失败来进行动态调整,这样即使DNS解析失败,用户在一段时间后也会取到合适的ip进行访问。
B、对ip进行数据统计。在所有app内统计每个ip进行请求所需平均时间、最长时间、最短时间、请求成功次数、失败次数,需要注意的是,要区分网络环境进行统计,Wifi、4G、3G,对在不同的网络环境下数据优秀的ip进行存储,下发到App里面使用起来。这样每次启动App时可以对收集起来的ip根据不同的网络环境进行测速,选择最好的ip进行请求。需要注意的是,在网络环境切换的时候,必须要重新进行速度测试。做到这一步,可以节约DNS解析时间,以及劫持的问题。
C、将图片、音频等资源放到单独的服务器里面,与其他资源分开。第一个是多个域名可以增加并行下载条数,因为客户端对同一个域的域名下载条数是有限制的,所以多个域就会增加并行下载条数,从而加快加载速度。当然二级域名也不能使用太多,因为太多要考虑到dns的解析花费的时间。第二个是方便管理,一般来说,图片在站点的加载中是最占带宽的,可以用独立服务器方便后期管理;还可以使用异步加载的方式,增强用户体验。同时是图片多是静态内容,可以更好的使用CDN加速。第三是如果使用了独立服务器的话,在安全设置上可以有差别的针对设置,很是方便。
D、在防止劫持这一块,需要注意把资源的后缀名去掉,比如说.mp3、.json这样的后缀,以免击中运营商的拦截。

总的来说,采用HttpDNS来解析域名,就绕过了三四级运营商解析域名会出现的问题,在HttpDNS返回了正确的ip之后,我们是直接采用ip去进行http请求,只需要关注通信内容的安全即可。

2、资源优化

资源优化基本就是尽可能的缩小传输数据的大小,选择合适的数据格式。
1、首先是图片大小的解决方案,在一定程度上使用webp来代替jpg、png图片,各种图片同等质量下的大小,webp是最小的。
2、可以使用ProtocolBuffer代替Json进行数据传输,因为ProtocolBuffer数据比Json更小,也是跨平台的,序列化与反序列化也很简单。

3、请求压缩

DNS查询之后是TCP握手建立连接,并发送请求数据。对于TCP来说,单个IP包大小受限于MSS值,大部分用户所处网络环境下每个包的大小约在1.5KB,新建立的HTTP连接由于TCP的slow start特性,会导致本地的部分IP包被临时缓存,从而增加了整体request的延迟。所以我们应该尽可能尝试去压缩我们的网络请求业务数据,减少一个Request的IP包数量,或许可以让用户少经历一个RTT,降低请求延迟的用户感知。

4、请求合并

对于非关键性的业务数据,或者对实时性要求不高的请求来说,通过合并请求的方式可以减少和服务器交互的次数,一则降低服务器压力,二则合并之后再压缩能节约客户端的流量。这类请求一般见于打点SDK,crash日志收集等非业务型请求。

5、请求的安全性

尽量使用HTTPS来保证基本的网络安全。对于敏感数据,采用MD5、AES、DES、RSA等加密方式来保证数据的安全传输,防止被拦截及篡改。

6、合理的并发数

有些业务场景会出现多个Request集中产生的情况,此时我们需要设置一个合理的并发数。并发数如果太小,会导致“劣质”的请求block住“优质”的请求。如果并发数太大,带宽有限的场景下,会增加请求的整体延迟。

7、数据缓存

1、使用HTTP缓存,减少请求次数,减小传输量(能不传body就不传)HTTP网络缓存减少了需要向服务器发送请求的次数。当一个请求完成下载来自服务器的回应,一个缓存的回应将在本地保存。下一次同一个请求再发起时,本地保存的回应就会马上返回,不需要连接服务器。NSURLCache就干这个,既可以缓存在Memory,又可以缓存在Disk上。
2、将Html,JS,CSS等网页静态文件存在手机上,标记版本,建立合适的更新机制。利用NSURLProtocol做网页的缓存(第一次),将网络IO改变为本地IO,提高H5体验。

8、可靠性保障

可靠性保障也是个容易被忽视的方面,在深入探讨之前,可以先将Request按业务属性分类。

  • 第一类:关键核心的业务数据,期望能100%送达服务器。
  • 第二类:重要内容请求,需要较高的请求成功率。
  • 第三类:一般性内容请求,对成功率无要求。

之所以要将请求分为三类,是要在可靠性保障上做区分。理论上我们应该尽可能让所有的请求成功率达到最高,但客户端的流量,带宽,手机电量,服务器的压力等都是有限的资源,所以我们采取的策略是只对关键性的网络请求做高强度的可靠性保障。
第一类请求类似大家用微信时发送的消息,消息数据一旦从输入框发出,从用户来的角度感知这个消息数据是一定会到达对方的。如果网络环境差,网络模块会自动在后头悄悄重试,一段时间后仍无法成功就通过产品交互的方式告知用户发送失败了,即使失败,请求的数据(消息本身)一直存在客户端。
对于这类请求的处理方式,第一步不是通过网络发送,而是先将请求持久化到DB当中。一旦入了DB,即使断网,断电,重启,请求数据依然还在,只需在App重启的时候还原请求数据,再次发送即可。第二步发送请求,如果请求失败则将请求加入重试队列,成功则从重试队列中移除。重试队列背后也需要一套通用机制,比如多久重试一次,重试几次之后放弃。遇到最恶劣的场景,请求发送失败之后,App被kill。我们需要在App重启之后从DB当中重新load所有失败的请求再次重试。
如果判断为第一类请求,通过上述几步基本上可以使请求的可靠性得到极大的保障,但100%是很难实现的。如果请求失败的时候用户重装App,所有持久化的数据丢失,请求数据也就丢了,不过这种极端的场景非常少。
第二类请求的例子可以是我们App启动时用户看到的首页,首页的内容从服务器获取,如果第一次请求就失败体验较差,这种场景下我们应该允许请求有机会多试几次,增加一个retryCount即可。一般3次的重试基本可以排除网络抖动的情况。三次失败之后即可认为请求失败,通过产品交互告知用户。
第三类请求的重要性最低,比如进入Controller的UV采集打点。这类请求只需要做一次,即使失败也不会对产品体验产生什么负面影响。

9、多通道

现在不少有技术条件的团队都有自己的tcp长连接通道,技术再硬点的甚至配有UDP通道,UDP在丢包率高的网络环境下能极大的提高请求成功的概率。如果能同时具备HTTP,TCP,UDP三条网络通道,在某些场景下,如果不考虑流量(比如wifi),可以针对某个网络请求,两通道或者三通道齐发,对请求成功的速度和可靠性有明显的疗效,不过客户端和服务器都需要针对业务场景做去重。UDP在VOIP服务当中使用较多,不过据说淘宝这类大厂也部分启用了UDP。

10、网络环境监控

现在网络环境虽然越来越好,Wifi,4G,3G在一二线城市都有很好的普及,但还是有不少场景会导致网络状态突然变差,比如进电梯,坐火车,人多的集会场所,从公司回家4G切Wifi等等,这些场景在生活当中并不少见,健壮的网络模块需要仔细的检测网络的变化,针对性的做请求重试。

11、请求成功率监控

网络模块应该能监控当前App的网络请求成功率,对于失败率较高的请求,带上业务数据,手机网络环境,系统参数等等,在用户不活跃的时候能打包上报给server端,一则能找出更多需要优化的业务场景,二则能实时监控server端的健康状态,三则能从数据层面精确判断每一次网络优化是否有成效。

你可能感兴趣的:(【iOS】iOS网络优化方案)