写点什么

手机 QQ 的移动化实践之路

  • 2014 年 12 月 23 日
  • 本文字数:6259 字

    阅读完需:约 21 分钟

在 2014 年 12 月 19 日~20 日举行的 ArchSummit 北京 2014 大会上,腾讯即时通讯平台部技术总监范瑞彬做了题为《手机QQ 的移动化实践之路》(幻灯片下载)的演讲,介绍了手机QQ 在服务海量移动用户方面经历了的一些经验。

范瑞彬(hata fan),腾讯公司即时通讯平台部技术总监,T4 专家。2004 年加入腾讯,长期负责手机QQ 后台整体建设,完整地经历了手机QQ 从数千人在线到亿级在线的整个过程,见证了十多年来移动互联网服务的高速发展。目前主要负责QQ 整体的接入平台建设,在海量分布式后台架构、IM 系统设计、移动业务架构设计等方面积累了多年实践经验。

本文系根据演讲内容整理而成。

演讲主要涉及3 个部分。第一,移动环境的特点。第二,针对移动环境的特点,如何做好接入?第三,架构设计理念方面的变化。

下图包含了云、管、端三个部分,多种终端通过多种网络访问云端的服务。上面红色部分是接入层,是首先会受到影响的。下面是逻辑存储、运营支撑和安全体系,这个系统目前终端同时在线过亿。终端每秒的请求量差不多千万,一天的请求量在数千亿的量级。

可以从三个方面看移动环境的特点。首先是移动网络,大家首先感觉是慢,而且流量又挺贵的。它还有很多种制式,差别也很大。还有终端的特点,相对PC 来说手机终端资源(CPU、内存、电量等)是受限的,永远是不够用的。而且终端的平台很多,机型多,能力差异也非常大。还有一个很重要的特点就是移动性,可以随身携带,可以随时随地利用碎片化的时间,环境多变,使用频繁。

面对这些环境的变化,接入首先会受到影响,而接入又是所有服务的基石。所以在移动环境下面,提供高质量的接入服务非常重要。如果将接入比作开车,那首先要选择一条快速的路线,这就相当于路由调度策略。另外还需要有一辆好车,车要快,类似于数据传输加速。然而选了一条好的路线,也有了一辆快车,并不代表就能快速到达目的地,尤其是非WIFI 接入时,新增了基站、大量新增的网源系统,非常复杂。这里面有一些规则需要了解,如果不了解的话可能这些就是坑,而遇到了坑可能会翻车,所以不能把它当成黑盒,所以需要熟悉路况。路况很复杂,车也很复杂,跑的过程当中难免会遇到异常,所以还得会修车,不能抛锚,这几点是接入的几个主要工作。

1. 路由调度(选快路)

分布式接入,在南方、北方和中部选择了三个地区,各自部署了一个点,每个点也覆盖了三大运营商,这是基础工作。

这时还有一个问题,如果中小运营商用户也访问到在三大运营商部署的服务,会存在跨网访问,质量很差。所以又建设了一个内容加速机房,它有独立 IP,而且是 TCP 互联,路由直达,这样中小运营商的质量可以得到明显改善。针对海外用户,最初在香港部署了一个点,后来又在全球各大洲,每个洲选择了一个点,海外用户就近访问加速点,通过加速点再访问国内的服务器。

部署是在不断优化的,调度也需要更精准的体现。所谓调度,无非就是说什么时候,哪些用户该连到哪些 server。所以这里可以分用户、server、时间三个维度。比如说用户,细化到每个网关;server,把用户调度到质量较高的 server 上面去;时间比较好理解,因为移动网络经常有波动,需要快速地发现波动,并及时自动干预,把它调度走。

还有一个很常见的问题,就是频繁切换网络。用户可能每天都在不同运营商,不同的网络之间来回切换。连接的时候不用域名,直接用 IP,那如何保证用户不管怎么样切换网络,都能连接到连到他应该连接的 server 上面呢?假如说用户第一次连某个网络时,他会使用本地默认列表,连到 server 时,如果 server 发现不是最优的,会及时纠正,下发一份新的 server 列表。开发团队干脆把用户最近使用的 50 个接入点统统缓存下来。

2. 数据传输加速(造快车)

做完了调度相当于选择了一条快速路线,这是不够的,还要想办法造一辆快的车。

首先是不用域名,直接用 IP。这样可以减少域名解析的开销,更重要的是,可以避免域名解析带来的各种故障,还可以减少一些被屏蔽和封掉的可能。

第二点是重用连接、预连接。比如说 QQ 里面发图的时候,其实用户还在选择图片的时候,会先把连接建立起来,而且用户传完图以后连接不会立即断掉,会维持一段时间,后面有批量图的时候可以继续使用,减少一次连接的时间可以减少几百毫秒。

第三点是精简协议和逻辑。

第四点是参数调优。比如说“拥塞窗口”(congestion window,CWND),server 的操作系统默认是 4,建议调大一点,可以调到 10,这样可以减轻慢启动对传输带来的影响。还有最大传输单元(Maximum Transmission Unit,MTU),之前跟运营商的朋友交流,他们给的建议是不要大于 1400,现在基本上都是按照这个策略来做的。还有重新传输超时(Retransmission Timeout, RTO),一般设 3 秒左右,系统默认值设的是 1。

还有一点叫高带宽时延积环境,在这种环境下面会遇到带宽吃不满,存在浪费的问题。以前网络都是 2G 网络的功能机时代。当时传图片大部分用的都是单连接。最近几年,网络越来越多,种类也越来越多,而且网络也越来越好。所以系统也进行了改进,可以根据网络状况动态地选择合适的连接数。比如说经过理论分析以及实验验证,开发团队发现其实在 WIFI、3G、4G 比较好的网络下面传输大数据时,用双连接比单连接提升至少 10%,而且越好的网络提升效果越明显。

3. 移动网络环境不是黑盒(熟路况)

不能简单地把移动网络环境当成黑核来处理,有些细节知识是需要了解的。

第一,要了解国内移动网关的一些设置,比如说它会限制某个包传输的大小,如果超过的话直接失败。之前跟设备厂商了解,华为很多网关设置的是 10M,但是各家都不一样,也没有什么标准。还有网关很多时候对传输时间有限制,这个也是各家不一样的。了解了这些细节,肯定要很好地支持分片和断点续传,否则在某些地区可能会出问题。

第二,网关对很多标准的理解和实现,各家也是不一样的,尤其像影响比较大的,比如说对 HTTP 协议的理解和实现。比如说在 HTTP 的标准文档里面,提了一个 range,但是没有强制去做,有的厂商支持的就不是太好。曾经遇到过一种情况,头部用到了 range,在分片传输图片时,运营商网关把它过滤掉了,客户端就不知道下一次该从哪里发,所以可能又从第一片开始发,这种情况下,如果客户端没有做好相关保护,就非常危险,会大量的重传,用户流量会被大量消耗。这就是需要注意的地方,尽量不要在 HTTP 头部加一些字段,需要传一些信息的话,可以放在包体里面,自己解析和理解。

第三,tcp_tw_recycle。用户说网络是好的,但是连不上 server。抓包分析发现,客户端三次握手的包已经发过来了,但是 server 没有回。这是什么问题呢?经过深入分析,研究了一下协议栈,以及一些参数设置,后来发现,假如 tcp_tw_recycle 是开启的,server 会检查对端同一个网关 IP 发过来的包,时间是不是递增的,如果不是递增的可能会丢掉。但是移动网络环境下,这是很难保证的。关闭 tcp_tw_recycle,问题就解决了。后来这成了外网接入层的标准配置。

第四,端口受限。有人反映某些地区的用户连 server 的某些端口连不上,或者是连接质量比较差。比如曾经发现香港数码通的用户连 8080 端口的质量非常差,很慢;还发现有些机场 WIFI,比如说深圳机场 WIFI,除了 8080 和 43 之外的断口都封掉了,用其他的端口用户也连不上。开发团队意识到,不应该被动地靠用户的反馈来发现问题和解决问题,所以建设了一套自动的系统,根据海量的数据去分析,根据分析结果,server 在给客户端返回合适接入列表时,优先选择质量高的端口,而且也尽量注意端口搭配的多样性,这样可以提升接入质量。

最后看一下信令风暴。其实从 09 年开始,手机 QQ 这边每年会被运营商朋友拉过去一起探讨这个问题,双方本着互相理解、合作共赢的态度来对待这个问题。除了建立一些双方认可的虚拟消耗运算模型之外,双方还就移动业务达成了技术共识。比如说减少定时包,减少不必要的及时包,因为有些包真的不一定要非常及时。可以适当做一些缓存和合并。还有一点就是要有流控,万一客户端有 BUG,大量的发包,这时候有压跨移动网络的可能,并不仅仅是数据网,它对电信网也有影响,所以 server 这时要有能力控制客户端发包的策略和频率,这样 HTTP 服务才能让人放心一点。

4. 异常处理(会修车)

比如说业务用的是 TCP 长连接,但是请求有可能被劫持,可能会返回到奇怪的 HTML 页面,最常见的是 WIFI 的认证注册,这时需要及时准确地发现这些问题,展现出来提示用户。

有一种网络抖动叫先发后到,需要做一些保护。比如说要求客户端发包的时候一定要递增,而且即使进程被杀掉重新再起来,也要保证这次发包比上次大。借助这个大小能知道真实发包时间的先后顺序。

终端休眠,终端是为了省电,肯定有一些休眠策略,App 为了应对这些策略,有一些自动唤醒机制,做一些自己想做的事。如果用 Wakelock,拿到这个锁之后,系统再也进入不了休眠了,这个锁一般用两三秒就足够了,一定要慎重。

最后是 App 健康和智能检测。客户端不能保证百分之百不出问题,有时候确实有可能在一些小概率的情况下,存在异常的点,它有可能会触发一些频繁大量的发包策略。大量的发包会把用户的流量大量消耗掉,而且这还算轻的,更严重的是如果有较多用户都出现这样的问题,可能不是流量消耗的问题,而存在把移动网络压跨的可能,移动网络真的很脆弱。

《刑法》中有一条罪叫破坏通信罪,可以判三到七年,所以这种工作很危险,也是有责任的。压垮移动网络后果很严重,要想办法极早发现和干预。怎么办呢?server 可以做一些准实时的流量消耗分析,如果发现在单位时间内用户流量超过某个异常值,就及时干预,而不是事后检查。比如可以把用户直接踢下线,或者更严重一点,直接让客户端的 App 自动自杀。

除了流量的问题,还有一些问题也是很隐蔽的,比如说用户的流量看起来没有太大变化。但是可能客户端有 bug 或者是设计不当,调用了几次后台操作,这个版本发出去的话,调用可能会增加好几倍甚至更多,后台的压力就非常大,于是又是过载保护,又是紧急扩容,这个也不是开发团队希望看到的,需要有更好的办法来解决它。比如可以分析这个版本,每个用户的使用频率。如果发现这个版本与上个版本相比,使用频率变化很大,多了很多,而且又没有提前报备,这里肯定有问题,就把这个问题抓出来,这些事情靠测试同学是不现实的,他很难测试到这些问题,这些问题需要技术同学自己想办法通过做智能数据分析来发现。

根据大量的实践,开发团队提炼出两个关键词:轻量交互和差异服务。

1. 轻量交互

轻量交互,其实核心思想就是节省,主要思想是从协议层面以及逻辑层面做一些精简、合并、压缩、消峰、异步等等。

减少交互步骤。客户端一次请求,尽量把信息都拿下去,后台也尽量把相关的信息都加进去,完整地带下去,减少交互步骤。这里要求后台要多主动地做一些聚合工作,一些协议要重新设计。

精简交互信息,尽量减少每一次传输过程中的信息。有个原则,就是不用的信息尽量不要拉,这里要求开发团队在协议设计的时候要非常灵活和细致,要支持增量更新和同步逻辑。

复用包头。一般做协议设计的时候有包头和包体,包头里面放一些账号信息、身份凭证,还有版本信息。尤其随着现在安全压力越来越大,形势越来越严峻,身份凭证可能会越来越长。其实这些信息没必要每次都带,可以在接入 server 时做一些缓存,后面的包就不需要这些信息了,这样的话每个包可以减少几十个字节,甚至更可观。这样算起来收益是很大的,不光能帮用户省流量,因为传的内容烧,也能加快速度,对体验也有改善,勿以善小而不为。

智能合并压缩。这里需要对业务逻辑有深入的了解。不是所有的包一定要最快响应,可以请求分一下优先级,哪些是需要及时响应的,一定要及时保证。哪些是可以降级的,不需要很及时。可以把大量的不需要及时响应的包做一些延迟,这个延迟不仅是为了解决运营商的消耗问题,延迟以后可以做压缩。当然具体延迟多久,可能要根据具体业务的场景来看。

客户端异步削峰。还是细分问题,把一些不重要的包或者是当前这个不是立即需要的可以往后放,先让用户快点接入进来。同样,客户端也需要注意不要把 UI 绘制跟存储放在一个线程里面做,避免卡顿。

2. 差异服务

可以把差异服务理解成个性化服务,针对网络情况和终端优化应用。下面具体看看。

怎么做好预拉取。比如说 QQ 会拉消息,拉过来的一堆消息里面可能有一些是图片消息,一开始看到这些图片消息只是缩略图。那何时去下载这些缩略图的原图呢?如果说等用户点了之后再去下载,自然大家会觉得这个很慢,体验不好。那提前下载该怎么做呢?这里要细致和全面一点。比如说可能要细分网络状况,在非 WIFI 网络下面流量是很贵的。如果把原图下载了下来,用户也不看,这样流量就浪费了,这浪费的就是钱,肯定不合适。那怎么办呢?可以设计一个算法,类似于银行家算法,给每个用户分配一个配额。比如说有 500K 的配额,预拉取一张原图,比如 100K,如果用户看了原图,配额不变;如果用户后来并没有看,则把配额减去 100K,凡是预拉取了而不看的配额都减掉,配额减到零就不会再做预拉取了,避免盲目下载造成大量的流量消耗。

在 WIFI 情况下,是不是可以简单地全下载下来呢?这样也不好。虽然用户的流量在 WIFI 下基本不收费,但是腾讯后台的出口带宽很贵。尤其是图片下载消耗非常大,这个钱是很多的。怎么办呢?可以根据业务场景做细分。比如把图片分为群图和 C2C 图,就是好友之间点对点的图。分析发现,C2C 图相对是比较重要的,用户点看原图的概率非常大。同时 C2C 图占比相对来说又是非常小的,因为大部分是群图。所以 C2C 图可以预拉取。群图还是采用类似于银行家算法的方式进行管控。

预拉取思路很简单,但是要做好,可能还需要很细致地结合网络状况,结合用户状况和业务场景做细致全面的细分,这样才能在用户体验,以及服务成本和用户成本之间找到一个恰当的平衡。

信息繁简不一。很多信息应该分类归档,针对一些好终端、好网络,尽量返回一次很好的信息,反之只给它简化版。

多种套图规格。需要根据多种屏幕来抽象和简化出几种通用的图片规格,而且可以根据不同网络状况来定每种规格的压缩率。

终端是该轻还是重。到了手机时代,因为手机本身能力比较弱,而且产品还经常要求做一些跨终端的一致体验,很多东西必须放在云端统一处理才可以。大部分场景下是轻终端重后台,具体要看业务场景。比如说有些游戏,以前 PC 时代为了防止 PC 客户端作弊,很多信息都是客户端直接给 server,一律由 server 统一去算。但是在手机游戏上面,为了减少信息传递以及减少交互次数,很可能会在终端也做适当的计算,把计算结果再发给 server,在这种特殊的场景下面,在这些逻辑方面可能终端做的更重一些。所以这个问题有普遍性,也有特殊性,要具体分析、具体看,深入理解业务场景和逻辑。

能不差异的地方就不差异,考虑全面些。设计的时候要考虑全面,要把各种平台、各种网络都考虑到。在选择压缩算法、加密算法、图片格式和文件格式时,这些东西能通用的还是尽量通用,不要给自己找麻烦。如果有些地方没法统一,必须要差异,这里要抽象简化,简化为几大类,而且这个差异点尽量使后台可调可控。

终端版本信息管理,终端运营配置管理。需要把终端版本的各种信息记录下来,然后才可以根据这些信息,再加上用户的信息灵活调整配置给不同用户更好的体验。可以根据不同地区、不同网络、不同版本、不同运营商和不同号码,以及根据不同的 CPU、不同的摄象头、不同的内存,给用户下发不同的闪屏和不同的插件,这是基础能力的建设。

范瑞彬最后还用一句话做了总结:“从实践中来,到实践中去”。

2014 年 12 月 23 日 04:055798
用户头像
臧秀涛 略懂技术的运营同学。

发布了 300 篇内容, 共 120.0 次阅读, 收获喜欢 30 次。

关注

评论

发布
暂无评论
发现更多内容

力扣(LeetCode)刷题,简单题(第16期)

不脱发的程序猿

面试 LeetCode 28天写作 算法面经 3月日更

【遇见Doris】基于Apache Doris的小米增长分析平台实践

ApacheDoris

字节跳动单点恢复功能及 Regional CheckPoint 优化实践

Apache Flink

flink

uni-app跨端开发H5、小程序、IOS、Android(六):uni-app事件绑定

黑马腾云

微信小程序 uni-app 大前端 iOS Developer 3月日更

对于移动开发,人工智能的到来意味着什么?

故胤道长

人工智能 机器学习 ios开发 Android开发

Spark常见的故障排除

五分钟学大数据

大数据 spark 28天写作 3月日更

【LeetCode】位1的个数Java题解

HQ数字卡

算法 LeetCode 3月日更

ThreadLocal 慌不慌?

叫练

JVM ThreadLocal 引用 软引用

java好还是嵌入式好?做IT开发该如何选择

cdhqyj

Java 编程 发展 开发 嵌入式

终于有阿里高工把SpringBoot+SpringCloud+Docker+MQ整合在一起了

Java架构追梦

Java 架构 微服务 springboot SpringCloud

Flink架构体系

大数据技术指南

大数据 flink 28天写作 3月日更

开发也要防“沉迷”?IDEA插件教程详解

京东科技开发者

Java 开发 IntelliJ IDEA

基于感染原理判断图的连通性算法

大奎

图算法 子图 连通性

彩色图像的二值化,取经之旅第 6 天

梦想橡皮擦

28天写作 3月日更

一文了解数据库资源管理技术

华为云开发者社区

数据库 存储 GaussDB(DWS) 资源管理

Flink SQL 在网易云音乐的产品化实践

Apache Flink

flink

书单|互联网企业面试案头书之架构师篇

博文视点Broadview

架构

【IstioCon 2021】最佳实践:从Spring Cloud 到 Istio

华为云原生团队

开源 Kubernetes 云原生 istio 服务网格

Cobar SQL审计的设计与实现

捉虫大师

Disruptor Skywalking cobar 数据库中间件

数据库周刊62丨央企2021年数据库成交公告,国产占90%;流数据库HStreamDB开源;MySQL主从双写导致数据丢失;Oracle 19c升级最佳实践;PG日常工作分享;MySQL MGR运维指南;SQL语法手册……

墨天轮

MySQL 数据库 sql postgre

墨天轮精选:数据库问答集萃第一期-2021

墨天轮

MySQL 数据库 sql dba

力扣(LeetCode)刷题,简单题(第15期)

不脱发的程序猿

LeetCode 编程之路 28天写作 算法面经 3月日更

技术实践丨Prometheus+Grafana搭建HBase监控仪表盘

华为云开发者社区

开源 Grafana Prometheus HBase 开源数据库

EGG公链强势来袭!去中心化社交革命先驱EFTalk

币圈那点事

精选2021互联网大厂Java核心面试题库(金三银四面试必备)

比伯

Java 编程 架构 面试 程序人生

【Doris Weekly】2020.03.08~2021.03.21

ApacheDoris

【Doris Weekly】

揭秘盒马鲜生,如何打破收益增长天花板!

博文视点Broadview

啃透这份399页Java架构知识点笔记,已从13K涨到25K

Crud的程序员

Java 程序员 架构

非常遗憾!靠着这份Redis深度笔记,我面进了阿里

互联网架构师小马

Java 数据库 nosql redis 面试

问题排查 | 客户端突如其来的“白屏”等待

蚂蚁集团移动开发平台 mPaaS

html5 移动开发 mPaaS 离线包

最全面试考点与面试技巧,面试必问

欢喜学安卓

android 程序员 面试 移动开发

手机QQ的移动化实践之路-InfoQ