移动APP后端网络处理一些问题记录
零。前言
这里讲的移动APP主要指的是安卓平台,大部分情况也适用于IOS等移动平台,可能重点嘛会在后半部分呢。
一。嵌入多SDK存在的隐患
但凡一个常用的APP都会嵌入至少一个SDK,不同来源或同一来源,有广告SDK,有推送SDK,有性能汇报SDK,有用户跟踪SDK,有统计流量SDK等,有支付SDK等等。虽然带来了功能的复用和解耦,便于纵向扩展,但可能会存在:
- 一个SDK可以看做一个后台Service,多个SDK多个Service存在(粗略上计算)
- 运行缓慢的问题,多个SDK或多功能的模块(若不按需加载的话)会导致运行缓慢,符合木桶理论,最慢的那个拖慢了总体步伐
- 每一个SDK都有自己核心诉求,各自为政,实现方式各异。总体架构是否合适,带来了隐形的兼容成本
- 彼此协调运作兼容性问题,一旦出现某个隐含BUG,会不会导致连锁反应
- CPU、内存、网络等资源竞争问题,想协调都很难
- 网络资源各自为政,无法共享,更不用提连接复用
若是同一来源的SDK,当问题发生的时候还能够有所协作稍作调整,虽然这也是比较理想的情况。外部的SDK可能问题反馈和BUG修正,时效性就不太好说了。
解耦虽然带来了功能的扩展性,带随之带来了资源利用方面的重复和浪费,愈多的SDK嵌入越有可能导致总体运行缓慢,需要谨慎使用。
二。APP后台Service数量很多
一般安卓手机会提供后台进程的查看,一般APP会启动多个后台服务,比如爱奇艺APP就很变态,5个服务存在(优酷APP也好不了哪去,3-4个服务存在):
一般较大公司,都会自己开发SDK,但碍于KPI等业绩考核,很少有人会认真从总体上考虑把多个Serice服务合并为一个,节省一点用户的资源占用,不过那需要考验研发人员的架构能力了。
虽然小白用户不一定会查看后台服务,但若干个后台服务,每一个都需要维护自身服务存活检测,每一个都会占用若干内存,若合并为一个,自然减少了CPU占用和内存资源占用,以及维护成本,还是有些小必要的。
三。HTTP短连接请求过于频繁
一般来讲,打开一个APP的时候,通过Wireshark抓包工具可以看到若干个HTTP连接瞬间建立,诸如淘宝,天猫,美团,优酷等APP,满屏的都是HTTP请求,看着让人感觉有些小恐怖,业务数据、设备信息上传、SDK信息抓取、埋点跟踪、头像图片、HTML资源等,那叫一个庞大。
但也没办法,业务展示那么丰富,需要消耗过多的资源。大部分请求都只专注于一部分数据。针对单一显示界面屏幕,可以通过一个请求获得合并后的响应结果,减少网络资源消耗。
手机淘宝和手机QQ,在HTTP请求优化方面,已经在使用IP直连、HTTP长连接、SPDY等进行加速处理,值得学习。
四。TCP长连接利用率不高
这里所说长连接,更多的是指TCP方式连接,也包括HTTP方式的长连接,但更多指的是具有双向通道的长连接。单通道的方式,协议所限,资源利用率不是那么高。
当前TCP长连接在其存活期间,大都只专注于传输一类具体业务内容,比如PUSH推送,一台手机连接一天,也接收不了几条消息,最频繁的就是心跳保活数据包传送了。
一旦涉及到新的业务,大家都是要新建一条全新TCP连接,彼此业务不关联嘛,看上去很耦合啊,但却造成了企业大量的重复资源浪费:新的业务需要处理另外的连接接入,资源重复投入,业务层面嘛,也会存在一半左右的重叠。当然,若不在乎这些的话,就另当别论了,但是你要是能够为消费者手机的资源消耗考虑,那便是用户的福音了。
长连接的业务层面多路复用,支持类似于摇一摇、抢红包、客服、客服咨询等,同一个连接传输不同类型的数据,即节省了服务器资源,又提高了网络连接利用率,两端的维护成本降低。针对客户端而言,多路业务复用在一条TCP连接上传输,需要业务路由 + 相应业务处理即可。服务器端嘛,接入不同的业务处理,依靠业务路由进行消息分发。
题外话,举一个例子,平时任一时间点约3000千万用户连接,按每台接200万计算,10-20台机器接入处理足可,推送啊,聊天啊,客服咨询,平常再来一个好运摇一摇都行。年底了要扩容到1亿左右用户摇啊摇的抢东抢西抢红包,还是同一个连接的方式,不过增加了新的业务类型数据传递,服务器嘛,扩展到50-80台就很OK了。用户量一旦降落,撤下多余机器就行。或许,有空可以写一篇供一亿用户在线的系统架构的方法 :))
五。HTTP 持久连接使用
针对HTTP/1.1可能很多人的思维方式,还停留在浏览器环境,一般浏览器有不支持或支持不够好,但在非浏览器环境下,针对APP应用的环境,少了很多传统浏览器环境的限制,但要完全发挥和释放HTTP/1.1协议所带来的持久特性,这便需要深度理解协议规范和具体的使用环境等进行抉择。
1. HTTP/1.1 KeepAlive特性使用
虽说HTTP/1.1 Keep-Alive特性支持多个请求在同一个连接上排队发送,在浏览器端正常的HTML等资源请求,会带来线头阻塞弊端,后一个请求依赖于前一个请求完成,一旦出现阻塞,后续请求只能排队等待。
但若针对非浏览器、业务模型不是很复杂的环境,比如日志采集/跟踪等常见业务,属于简单循环的请求-响应模型,响应仅仅需要HTTP 200状态码即可(这要求服务器端接收之后异步处理直接返回200状态),后续的请求只需要排队,并且不会对延迟有苛刻要求,那么Keep-Alive特性就很适合。一般出现阻塞,那就意味着网络状况不容乐观,关闭然后重键一个HTTP持久连接就行。
有些环境,只需要发送数据,客户端不关心有没有响应(或不接收响应),类似于UDP的方式,比如实时日志(突出实时特性),但这需要客户端异步处理响应。
一般视频网站都会有实时跟踪用户正在播放中的视频播放状态,那就需要建立一个持久的HTTP/1.1连接,即时、持续传递视频观看事件,自然就避免了短连接多次创建、关闭的开销。
2. HTTP/1.1 Pipelining
建立在Keep-Alive持久化基础之上,中文译为管线化,支持连续的幂等的GET/HEAD方法请求,实际环境下,并没有被浏览器所支持。
同一个连接,处理同样的三次请求-响应,Keep-Alive和Pipelining方式不同:
浏览器环境不支持的特性,在应用环境下或许可以找到其适用空间。比如具有通过GET方式提交数据的情况(比如GET方式汇报地理位置,GET方式提交用户设备信息,GET方式汇报用户手机抖动情况等),多个请求批量发送。
但换一个思维方式,若能够合并批量请求为一个POST提交,不走管线化方式,可能会更合适一些。
针对不太重要数据,发送完毕,不用等待响应。
3. HTTP/2
若想了解HTTP/2的规范,可以参考本博客的其它文字。目前客户端库和服务器端库,支持都不太好,需要观察一段时间,公司实力够,完全可以自主开发,或基于SPDY 2.0也可,目前淘宝APP、腾讯手QQ等,也都在使用。
HTTP/1.1能够完全解决的问题,就没有必要使用HTTP/2,后者造成了实现有些复杂,可能中介设备(网关、代理、CDN等)都还没有为之做好准备呢,但HTTP/2毕竟是趋势。
虽然规范只定义一个Hostname只允许一个连接,可能实际情况下会需要2-3条长连接以争夺较多的网络带宽资源。
六。小结
怎么说呢,在当前移动APP环境下:
- TCP长连接的通道用途的传输潜力和利用率很低
- HTTP/1.1的持久特性很容易被人忽略,未能正确使用
- HTTP/2多路复用值得期待
无论哪一种方式,都需要熟悉协议和网络,适合的环境使用适合的协议特性,才能够发挥出潜在的性能出来。