QQ18年,解密8亿月活的QQ后台服务接口隔离技术
QQ18年
1999年2月10日,腾讯QQ横空出世。光阴荏苒,那个在你屏幕右下角频频闪动的企鹅已经度过了18个年头。随着QQ一同成长的你,还记得它最初的摸样吗?
1999年:腾讯QQ的前身OICQ诞生,该版本具备中文网络寻呼机、公共聊天室以及传输文件功能。
1999年QQ界面
2000年,OICQ正式更名为QQ,发布视频聊天功能、QQ群和QQ秀等功能。
2003年版本,QQ发布聊天场景、捕捉屏幕、给好友播放录影及QQ炫铃等功能。
2004年,QQ新增个人网络硬盘、远程协助和QQ小秘书功能。
···
几经更迭,QQ版本也产生许多变化,很多操作方式都变了,也让QQ更有现代感了。如今的QQ越来越精美,越来越简洁,如你所见。
据不完全统计,腾讯QQ月活用户达到8.7亿左右,而这个数字还在不断增加。。。
如此庞大的用户群的任何行为,都会产生巨大的影响。
2017年春节,QQ推出AR红包加入红包大战,经调查手机QQ的红包全网渗透率达到52.9%。
在此期间,后台想必又一次承受了海量的压力,年后第一波推送,来看看腾讯内部对QQ后台的接口处理的相关技术干货,或许可以给到你答案。
一、背景
QQ后台提供了一套内部访问的统一服务接口,对腾讯各业务部门提供统一的资料关系链访问服务,后面我们把这套接口简称为DB。
现在说说分set的背景:2013年的某一天,某个业务的小朋友在申请正式环境的DB接入权限后,使用正式环境来验证刚写完的测试程序,循环向DB接口机发送请求包,但因为这个包格式非法,触发了DB解包的一个bug,导致收到这些请求包的服务器群体core dump,无一幸免。。。。整个DB系统的服务顿时进入瘫痪状态。
因此有了故障隔离的需求,2014年初,我们着手DB的故障隔离增强改造。实现方法就是分set服务–把不同业务部门的请求定向到不同的服务进程组上,如果某个业务的请求有问题,最多只影响一个部门,不会影响整个服务系统。
二、总体方案
为了更清楚描述分set的方案,我们通过两个图进行分set前后的对比。
分set之前:
分set之后:
从图中可以看出,实现方式其实非常简单,就是多启动一个proxy进程根据IP到set的映射关系分发请求包到对应set的进程上。
三、分set尝试
很多事情往往看起来非常简单,实现起来却十分复杂,DB分set就是一个典型的例子。怎么说呢?先看看我们刚开始实现的分set方案。
实现方案一:通过socket转包给分set进程,分set进程直接回包给前端。
这个方案刚发布几台后就发现问题:
1,有前端业务投诉回包端口不对导致访问失败。后来了解这些业务会对回包端口进行校验,如果端口不一致就会把包丢弃。
2,CPU比原来上涨了25%(同样的请求量,原来是40%,使用这个方案后CPU变成50%)
回包端口改变的问题因为影响业务(业务就是我们的上帝,得罪不起^^),必须马上解决,于是有了方案二。
实现方案二:通过socket转包给分set进程,分set进程回包给proxy,由proxy回包。
改动很快完成,一切顺利,马上铺开批量部署。。。。
晚上10点准时迎来第一次高峰,DB出现大量的丢包和CPU告警,运维紧急迁移流量。
第二天全部回滚为未分set的版本。
重新做性能验证的时候,发现CPU比原来涨了50%,按这个比例,原来600多台机器,现在需要增加300多台机器才能撑起同样请求的容量。(这是写本文时候的机器数,目前机器数已经翻倍了~)
后来分析原因的时候,发现网卡收发包量都涨了一倍,而CPU基本上都消耗在内核socket队列的处理上,其中竞争socket资源的spin_lock占用了超过30%的CPU – 这也正是我们决定一定要做无锁队列的原因。
四、最终实现方案
做互联网服务,最大的一个特点就是,任何一项需求,做与不做,都必须在投入、产出、时间、质量之间做一个取舍。
前面的尝试选择了最简单的实现方式,目的就是为了能够尽快上线,减少群体core掉的风险,但却引入了容量不足的风险。
既然这个方案行不通,那就得退而求其次(退说的是延期,次说的是牺牲一些人力和运维投入),方案是很多的,但是需要以人力作为代价。
举个简单的实现方法:安装一个内核模块,挂个netfilter钩子,直接在网络层进行分set,再把回包改一下发送端口。
这在内核实现是非常非常简单的事情,但却带来很大的风险:
1,不是所有同事都懂内核代码
2,运营环境的机器不支持动态加载内核模块,只能重新编译内核
3,从运维的角度:动内核 == 杀鸡取卵 – 内核有问题,都不知道找谁了
好吧,我无法说服开发运营团队,就只能放弃这种想法了–即便很不情愿。
。。。跑题了,言归正传,这是我们重新设计的方案:
方案描述:
1,使用一写多读的共享内存队列来分发数据包,每个set创建一个shm_queue,同个set下面的多个服务进程通过扫描shm_queue进行抢包。
2,Proxy在分发的时候同时把收包端口、客户端地址、收包时间戳(用于防滚雪球控制,后面介绍)一起放到shm_queue中。
3,服务处理进程回包的时候直接使用Raw Socket回包,把回包的端口写成proxy收包的端口。
看到这里,各位同学可能会觉得这个实现非常简单。。。不可否认,确实也是挺简单的~~
不过,在实施的时候,有一些细节是我们不得不考虑的,包括:
1)这个共享内存队列是一写多读的(目前是一个proxy进程对应一组set化共享内存队列,proxy的个数可以配置为多个,但目前只配一个,占单CPU不到10%的开销),所以共享内存队列的实现必须有效解决读写、读读冲突的问题,同时必须保证高性能。
2)服务server需要侦听后端的回包,同时还要扫描shm_queue中是否有数据,这两个操作无法在一个select或者epoll_wait中完成,因此无法及时响应前端请求,怎么办?
3)原来的防滚雪球控制机制是直接取网卡收包的时间戳和用户层收包时系统时间的差值,如果大于一定阀值(比如100ms),就丢弃。现在server不再直接收包了,这个策略也要跟着变化。
基于signal通知机制的无锁共享内存队列
A. 对于第一个问题,解决方法就是无锁共享内存队列,使用CAS来解决访问冲突。
这里顺便介绍一下CAS(Compare And Swap),就是一个汇编指令cmpxchg,用于原子性执行CAS(mem, oldvalue, newvalue):如果mem内存地址指向的值等于oldvalue,就把newvalue写入mem,否则返回失败。
那么,读的时候,只要保证修改ReadIndex的操作是一个CAS原子操作,谁成功修改了ReadIndex,谁就获得对修改前ReadIndex指向元素的访问权,从而避开多个进程同时访问的情况。
B. 对于第二个问题,我们的做法就是使用注册和signal通知机制:
工作方式如下:
1)Proxy负责初始化信号共享内存
2)Server进程启动的时候调用注册接口注册自己的进程ID,并返回进程ID在进程ID列表中的下标(sigindex)
3)在Server进入睡眠之前调用打开通知接口把sigindex对应的bitmap置位,然后进入睡眠函数(pselect)
4)Proxy写完数据发现共享内存队列中的块数达到一定个数(比如40,可以配置)的时候,扫描进程bitmap,根据对应bit为1的位取出一定个数(比如8,可以配置为Server进程的个数)的进程ID
5)Proxy遍历这些进程ID,执行kill发送信号,同时把bitmap对应的位置0(防止进程死了,不断被通知)
6)Server进程收到信号或者超时后从睡眠函数中醒来,把sigindex对应的bit置0,关闭通知
除了signal通知,其实还有很多通知机制,包括pipe、socket,还有较新的内核引入的eventfd、signalfd等等,我们之所以选择比较传统的signal通知,主要因为简单、高效,兼容各种内核版本,另外一个原因,是因为signal的对象是进程,我们可以选择性发送signal,避免惊群效应的发生。
防滚雪球控制机制
前面已经说过,原来的防滚雪球控制机制是基于网卡收包时间戳的。但现在server拿不到网卡收包的时间戳了,只能另寻新路,新的做法是:
Proxy收包的时候把收包时间戳保存起来,跟请求包一起放到队列里面,server收包的时候,把这个时间戳跟当前时间进行对比。
这样能更有效的做到防滚雪球控制,因为我们把这个包在前面的环节里面经历的时间都考虑进来了,用图形描述可能更清楚一点。
五、性能验证
使用shm_queue和raw socket后,DB接口机处理性能基本跟原来未分set的性能持平,新加的proxy进程占用的CPU一直维持在单CPU 10%以内,但摊分到多个CPU上就变成非常少了(对于8核的服务器,只是增加了1.25%的平均CPU开销,完全可以忽略不计)。
最后,分set的这个版本已经正式上线运行一段时间了,目前状态稳定。
对许多企业而言,虽不一定经历月活8亿用户,但为了能够面对蜂拥而来的用户游刃有余,时刻了解并保持自己的最优状态迎接用户,一定要在上线之前对自己的网站承载能力进行一个测试。如果自己没有服务器,没有人力,没有钱,都没有关系。。。
腾讯提供了一个可以自主进行服务器性能测试的环境,用户只需要填写域名和简单的几个参数就可以获知自己的服务器性能情况,目前在腾讯WeTest平台可以免费使用。
腾讯WeTest服务器性能测试运用了沉淀十多年的内部实践经验总结,通过基于真实业务场景和用户行为进行压力测试,帮助游戏开发者发现服务器端的性能瓶颈,进行针对性的性能调优,降低服务器采购和维护成本,提高用户留存和转化率。
功能目前免费对外开放中,点击 http://WeTest.qq.com/gaps 即可体验!
如果对使用当中有任何疑问,欢迎联系腾讯WeTest企业qq:800024531
QQ18年,解密8亿月活的QQ后台服务接口隔离技术相关推荐
- 如何分享10亿月活红利?揭秘拥抱小程序电商的正确姿势
对于很多电商中小企业来说,小程序可能还只是一个模糊的概念.但是小程序电商这一巨大风口已经到来.根据不久前调研机构QuestMobile发布的2018<微信小程序洞察报告>,微信小程序月活跃 ...
- Pinterest 如何突破获客和留存两大难题,打造 2.5 亿月活增长新闭环?-实践
转自 | GrowingIO 作者介绍 Casey Winters,硅谷增长实践鼻祖,前 Pinterest 增长负责人,打造 Pinterest 超 2 亿月活用户:硅谷顶级风投 Greylock ...
- 独家:小程序再添新能力,QQ空间5.62亿月活用户福利来袭
QQ空间广告支持跳转小程序 小程序广告能力再升级,这次的触角伸向QQ空间广告! 以前广告主只能在微信内投放小程序广告,现在广告主如果投放QQ广告,可以引导用户点击广告后的落地页设置为公众号文章,并且, ...
- Python + Django 如何支撑了 7 亿月活用户的 Instagram?
PyCon 简介 PyCon 是全世界最大的以 Python 编程语言为主题的技术大会.大会由 Python 社区组织,每年举办一次.在大会上,来自世界各地的 Python 用户与核心开发者齐聚一堂, ...
- 小程序input获得焦点触发_小程序如何获得种子用户,微信9亿月活用户来教你!...
小程序虽已上线2年了,但在微信生态中还非常年轻,正处于学习奔跑的阶段.而且,许多商家对于如何正确获得第一批种子用户,并不十分清楚. 今天,企乐网就以如何定位种子用户?种子用户在哪里获得?用什么方法沉淀 ...
- 轻松应对1亿+月活,《迷你世界》背后有啥黑科技
本文分享自华为云社区<亿级月活沙盒平台<迷你世界>背后的黑科技>,作者:GaussDB 数据库 . 年少时期,我们有过许多梦,想仗剑天涯,想修种藩篱,想成为建筑大师,想改变世界 ...
- 坐拥12亿月活流量,腾讯直播带货的底牌
本文经授权转载自Tech星球 ID:tech618 作者| 杨业擘 "今天直播已经不是你做不做的问题,而是怎么做的问题."在微信的直播间中,直播培训商李峰向观众布道.去哪家平台作做 ...
- 1.31亿月活的爆款游戏,它的后端架构是怎样的?
1.31亿人,这是什么概念? 如果是个国家,那么这个"国家"的人口数刚好在全球排名第十. 如果是个游戏的玩家数量呢?那就是:Minecraft<我的世界>! 作为一款多 ...
- 哔哩哔哩2019年Q3财报:手握1.28亿月活,年轻人为何偏爱B站?
北京时间11月19日(美国东部时间11月18日),国内领先的年轻人文化社区哔哩哔哩公布了截至2019年9月30日的第三季度未经审计的财务报告.本季度内,哔哩哔哩(以下简称"B站") ...
最新文章
- 你奋斗这么辛苦,这辈子要证明什么?
- SAP UI5 main page design
- 开放防火墙的端口号mysql_linux下mysql开启远程访问权限及防火墙开放3306端口
- Android中监听ScrollView滑动停止和滑动到底部
- canvas 擦除动画_帧动画的多种实现方式与性能对比
- python rpc调用_从0到1:全面理解 RPC 远程调用
- html5坦克游戏ppt说明,HTML5制作的坦克游戏
- 中小型企业无线网络设计
- 上位机与下位机进行交互
- Android万能布局检查器UI Automator Viewer使用教程、环境配置和Mac无法打开问题解决(uiautomatorviewer,android studio,layer,查看,错误)
- # Codeforces Round #722(div2)D. Kavi on Pairing Duty
- 为什么创造 Charj 语言?从十年以后的编程说起
- javascript实现汉诺塔
- 智商情商哪个重要_情商和智商 哪个对孩子更重要?
- VC学习资料收集(12):VC小知识总结
- netty的epoll和linux的epoll是如何实现的
- 洛谷P1262 间谍网络题解
- android开发评论列表,Android类Reddit循环评论列表开发
- 漫画:震惊!直觉误判类题目在面试时是如何坑人的?
- 课后作业7.1:文件系统的静态结构
热门文章
- PHP接入支付宝当面付
- NISPA: Neuro-Inspired Stability-Plasticity Adaptation for Continual Learning in Sparse Networks 论文阅读
- 【C语言】让你不再因为指针而感到头疼
- MTK Nucleus OS之初识
- Qt之读取qss文件
- linux busybox源码下载,源码编译 busybox
- 25 机器学习相关参考文献及推荐阅读
- 《乔新亮的CTO成长复盘》—— 产品思维,契约精神是基础,洞察人性才能成就卓越。——有感
- RPC系列之Netty实现自定义RPC框架
- 无决心,不梦想 开利网络持续开展每周主题分享会