为何要做网络优化
网络优化对于App产品的用户体验至关重要,与公司的运营和营收息息相关。这里列举两个公开的数据:
“Amazon页面加载延长1秒,一年就会减少16亿美金营收。”
在做网络优化前,我们首先要为网络通信质量设立一个标尺。
在美团点评,监控团队开发了基于端到端的客户端监控平台。这里要先解释一下“端到端”的含义:是指请求从客户端发出到服务端响应返回的整个过程。它区别于后台服务监控,是一种从用户角度观察到的真实体验监控。
监控页面如图所示:
通过基于命令字的、多维度、实时的监控工具,可以及时发现线上问题。
为了方便发现问题,我们在公司内统一了网络响应状态码的范围。通过状态码的分段范围,也可以迅速清晰地看到网络成败的原因和占比。
有了监控工具后,我们来讨论:移动网络请求过程中,出现了哪些最常见的问题?
首先是网络不可用的问题。主要由以下几种原因导致:
其次是网络加载时间长。原因包括:
最后是HTTP协议的数据安全问题。原因有:
基于短连的优化
面对上述网络问题,我们首先在HTTP短连请求中进行了一些优化尝试。
随着开发规模逐渐扩大,各业务团队出于独立性和稳定性的考虑,纷纷申请了自己的三级域名。App中的API域名越来越多。如下所示:
search.api.dianping.com ad.api.dianping.com tuangou.api.dianping.com waimai.api.dianping.com movie.api.dianping.com …
App中域名多了之后,将面临下面几个问题:
如果想将所有的三级域名都合并为一个域名,又会面临巨大的项目推进难题。因为不同业务团队当初正是出于独立性和稳定性的考虑才把域名进行拆分,现在再想把域名合并起来,势必会遭遇巨大的阻力。
所以我们面临的是:既要将域名合并,提升网络连接效率,又不能改造后端业务服务器。经过讨论,我们想到了一个折中的方案。
该方案的核心思想在于:保持客户端业务层代码编写的网络请求与后端业务服务器收到的请求保持一致,请求发出前,在客户端网络层对域名收编,请求送入后端,在SLB(Server Load Balancing)中对域名进行还原。
网络请求发出前,在客户端的网络底层将URL中的域名做简单的替换,我们称之为“域名收编”。
例如:URL "http://ad.api.dianping.com/command?param1=123" 在网络底层被修改为 "http://api.dianping.com/ad/command?param1=123" 。
这里,将域名"ad.api.dianping.com"替换成了"api.dianping.com",而紧跟在域名后的其后的"ad"表示了这是一条与广告业务有关的域名请求。
依此类推,所有URL的域名都被合并为"api.dianping.com"。子级域名信息被隐藏在了域名后的path中。
被改造的请求被送到网络后端,在SLB中,拥有与客户端网络层相反的一套域名反收编逻辑,称为“域名还原”。
例如:"http://api.dianping.com/ad/command?param1=123" 在SLB中被还原为 "http://ad.api.dianping.com/command?param1=123" 。
SLB的作用是将请求分发到不同的业务服务器,在经过域名还原之后,请求已经与客户端业务代码中原始请求一致了。
该方案具有如下优势:
经过域名合并方案,我们已经将所有的域名都统一成了"api.dianping.com"。针对这唯一的域名,我们可以在客户端架设自己的DNS服务。
方案很简单:程序启动的时候拉取"api.dianping.com"对应的所有的IP列表;对所有IP进行跑马测试,找到速度最快的IP。后续所有的HTTPS请求都将域名更换为跑马最快的IP即可。
举个例子,假如:经过跑马测试发现域名"api.dianping.com"对应最快的IP是"1.23.456.789"。
URL"http://api.dianping.com/ad/command?param1=123"将被替换为"http://1.23.456.789/ad/command?param1=123"
IP直连方案有下面几大优势:
此外,如果你的App域名没有经过合并,域名比较多,也建议可以尝试使用HttpDNS方案。参考:http://www.tuicool.com/articles/7nAJBb 对HTTPS中的证书处理:
HTTPS由于要求证书绑定域名,如果做IP直连方案可能会遇到一些麻烦,这时我们需要对客户端的HTTPS的域名校验部分进行改造,参见:http://blog.csdn.net/github_34613936/article/details/51490032 。
经过域名合并加上IP直连方案改造后,HTTP短连的端到端成功率从95%提升到97.5%,网络延时从1500毫秒降低到了1000毫秒,可谓小投入大产出。
接下来要想进一步提升端到端成功率,就要开始进行长连通道建设了。
长连通道建设
提到长连通道建设,首先让人想到的应该是HTTP/2技术。它具有异步连接多路复用、头部压缩、请求响应管线化等众多优点。
如果查看HTTP/2的拓扑结构,其实非常简单:
HTTP/2在客户端与服务器之间建立长连通道,将同一域名的请求都放在长连通道上进行。这种拓扑结构有如下一些缺点:
与HTTP/2相区别,我们这里推荐另一种代理长连的模式。这种模式的拓扑图如下:
基本思路为:在客户端与业务服务器之间架设代理长连服务器,客户端与代理服务器建立TCP长连通道,客户端的HTTP请求被转换为了TCP通道上的二进制数据包。代理服务器负责与业务服务器进行HTTP请求,请求的结果通过长连通道送回客户端。
与HTTP/2模式对比,代理长连模式具有下面一些优势:
在长连通道项目的早期,出于快速推进的目的,同时受限于建设代理长连服务器需要投入大量资金,我们首先接入使用了腾讯的维纳斯(WNS)服务(官网地址:https://www.qcloud.com/product/wns )。
WNS服务采用的也是代理长连模式,依托腾讯云的强大硬件建设,我们使用下来发现端到端成功率可以达到99.6%以上。(PS:这里的提到的端到端成功率与官网宣传的99.9%不同是由于统计口径的不同。)
由于腾讯WNS服务是面向公众的云服务,服务的客户远不止一家,无法完全满足我们公司技术需求的快速变更,因此还是需要进行自己的长连通道项目建设。
自建长连建设大概可以分为以下几个周期:
① 中转服务的开发和部署
作为开发的初级阶段,这一时期的任务主要是搭建代理中转服务器,并架设完整链路结构。
② 加密通道的建设
为了保护TCP通道上数据的安全性,客户端与代理长连服务器之间的二进制通信数据可以利用加密来保障数据安全。
③ 专线建设
在代理长连服务器与后台业务服务器之间建设专线。使用专线,可以大大降低公网环境的干扰,保障服务的稳定性。
④ 自动降级Failover建设
由于客户端的请求都放在TCP通道上进行,当代理长连服务器需要升级或者由于极端情况发生了故障时,将会造成客户端的整体网络服务不可用。为了解决这个问题,我们准备了Failover降级方案。当TCP通道无法建立或者发生故障时,可以使用UDP面向无连接的特性提供另一条请求通道,或者绕过代理长连服务器之间向业务服务器发起HTTP公网请求。本文的后面章节有展示Failover机制的实际效果。
⑤ 多地部署接入点
在全国多地部署代理长连接入点。客户端与接入点建立长连通道时,可以选择最快的服务器就近接入,从而大大降低通道连接速度并提升通信质量。
我们在近两年的网络优化实践中,将客户端的网络通道服务整理成了一个独立的SDK,SDK内除了包含了自建的长连通信服务,也包含了WNS等网络通道。
完整的网络通道拓扑图如下所示:
图中网络通道SDK包含了三大通信通道:
推送方案:在网络通道拓扑图的右上角,有个Push Server。它是考虑到TCP通道的双工特性,为网络通道SDK提供推送的能力。利用通知推送,可以在服务器数据发生变化时及时通知客户端。推送方案可以替换掉代码中常见的耗时低效的轮询方案。
下图展示了某开机接口在接入长连后的端到端成功率对比:
上图中黑色曲线是某开机接口在短连通道下的成功率曲线。成功率平均只有81%,抖动的特别剧烈,说明网络服务稳定性不够。
蓝色曲线是同一接口在长连通道下的成功率曲线。成功率平均已达到99%,抖动大幅减小。
成功延时对比图:
上图中展示了同样情况下的成功延时曲线。蓝色线为长连延时曲线,黑色线为短连延时曲线。
接下来我们看Failover的效果展示图。
下图展示了2015年的一次长连服务器故障。
当时Android客户端采用了Failover方案,在长连不可用时Failover到短链或者UDP通道上。与未采用Failover方案的iOS客户端相比,Failover机制在维持网络整体可用性方面体现出了非常大的优势。
网络通道SDK包含了CIP|WNS|HTTP三大通道,不同的通道具有各自的优缺点,控制各请求选择合适的网络通道成了迫在眉睫的重要课题。
为此我们开发了网络配置系统,通过下发指令,调整App中网络通道SDK中的通道选择策略,可以控制不同的API请求动态切换网络通道。
下图是某接口的线上通道切换示意图:
图中展示了某接口切换WNS通道的过程。图中的黑色线代表短连通道下的请求数量曲线,蓝色线代表WNS通道下的请求数量曲线。通过线上控制系统下发了通道切换指令后,绝大部分的短连请求在5分钟之内被切换成了WNS通道请求。
经验总结
在客户端开发过程中,我们发现:
对于正在成长中的创业公司,我们有如下改善网络状况的建议: