内容简介:疫情爆发,腾讯发起“停课不停学”专项,腾讯课堂一下子被推到风口浪尖上,2天上线极速版,2周内支持pcu要从5w到600w,2周内接入层qps从1.4w/s到65w/s,对整个后台挑战非常大。整整2个月下来,同合作团队一起,白天7点开始盯监控和开发版本,凌晨12点例行压测和发布扩容,踩过很多坑也取得很多收获,这里拎几个关键点记录下。1.1 项目背景大年初一,吃着火锅唱着歌,突然收到重庆十一中的求助信:受疫情影响,年后学校无法开学,高三老师学生都很担心影响到高考,问腾讯课堂能否提供线上平台给高三复课,拉开了整个
疫情爆发,腾讯发起“停课不停学”专项,腾讯课堂一下子被推到风口浪尖上,2天上线极速版,2周内支持pcu要从5w到600w,2周内接入层qps从1.4w/s到65w/s,对整个后台挑战非常大。整整2个月下来,同合作团队一起,白天7点开始盯监控和开发版本,凌晨12点例行压测和发布扩容,踩过很多坑也取得很多收获,这里拎几个关键点记录下。
一、 腾讯课堂 停课不停学
1.1 项目背景
大年初一,吃着火锅唱着歌,突然收到重庆十一中的求助信:受疫情影响,年后学校无法开学,高三老师学生都很担心影响到高考,问腾讯课堂能否提供线上平台给高三复课,拉开了整个停课不停学专项的序幕。
1.2 极速版的诞生
由于课堂是面向线上培训机构的,这次想把十一中这样的传统线下校园,搬到腾讯课堂内上课才发现困难重重:
-
入驻:学校各类资质和机构完全不一样,审核周期长
-
发课:机构发课有很多规范约束,而学校用课程表排课,一个个发课成本高
-
直播:学校老师转线上上课,普遍说直播 工具 有上手成本
耗了很多人力才把十一中的入驻发课和老师培训搞完,同时其他学校也陆续找过来了,才发现根本没人力能对接这么多学校。就在这时,小马哥发话了:“把入驻发课全砍掉,快速做个腾讯课堂极速版,老师下载完就能自助上课了”。
随着总办特批QQ推广资源,各省市教育厅陆续宣布使用急速版复课,课堂pcu/dau开始起飞,短短2-3周,pcu从5w到100w,DAU从60w到1000w,AppStore免费类排行榜进Top10,教育类稳居Top1。
1.3 疫情期间开发缩影
1.4 架构挑战
下面是课堂后台架构图,由于之前架构设计和模块部署都是按10w同时在线峰值来算的,突然要在2周内支持量100倍增涨,同时还要开发校园版需求,时间赶且任务重。这里分五个阶段把架构挑战和解决策略介绍下
二、 阶段1:先抗住后优化
面对2周100倍量级增长,重构肯定来不及了,且过大改动仓促上线反而会增加不稳定因素。所以初期思路就是“先抗住后优化”:梳理极速版用户路径,评估路径上各模块容量,快速扩容后,每天凌晨例行全链路压测,持续验证迭代。
2.1 模块梳理和接口裁剪
和产品讨论完用户路径和访问量级后,各页面qps也基本有个数了,就开始梳理每个页面调用接口列表,明确每个接口要支撑的qps:
由于课堂svr数有200+,cmd有800+,为了争取时间,需聚焦核心路径减少梳理复杂度,对于非核心体验和风险较大的这2类接口,抛出来和产品讨论做页面接口裁剪。
2.2 系统容量评估
模块和接口梳理清楚后,就开始分负责人对系统做容量评估。要特别关注木桶效应,很多新同学只评估了逻辑Svr这一层,其实从用户端->接入层->逻辑层->存储层全链路都得涉及,不能让任一环节成短板。
2.3 扩容扩容扩容
各模块扩容数算清楚后,剩下的就是申请机器部署了。扩容本该是个很简单的活,但因为历史债务等问题,部分模块费了很多周折,比如:
-
容器化和上k8s不彻底
-
部分c++模块依赖ShmAgent,扩容流程极其繁琐
-
扩容svr导致DB链接数爆炸 ...
针对扩容暴露的问题,从接入->逻辑->存储,沉淀了很多设计经验,后面得彻底改造掉,特别是k8s这块应尽快全面铺开。这里终极目标是:针对量级暴涨的情况,不用花人力做评估和扩容,整个系统就有自动伸缩的能力。
通过1周通宵达旦,抗住首波增长。
2.4 全链路压测
在初步扩容完后,为了防止梳理不全、评估不准等情况,例行全链路压测验证非常重要,可以挖掘性能瓶颈和系统隐患。
在测试同学给力支持下,每天例行执行下面流程,持续扩容优化迭代:
-
校准压测模型:非常重要,压测用例设计会直接关系到压测效果
-
确定压测目标:把每个模块/接口的压测qps确定下来
-
执行压测任务:凌晨12点启动整站压测流水线,执行星海用例,输出压测结论
-
回归压测结果:压测不达标接口记录doc,尽快暴露隐患,责任人分析原因给解决方案
压测QCI流水线:
全链路压测方案:
三、 阶段2:瓶颈最先出在DB数据层
根据先抗住后优化的思路,可扩容的都容易解决,架构瓶颈会最先出现在伸缩性差、不容易扩容的环节上,经常会是数据层,课堂这次也中招了。
3.1 核心DB,一挂全挂
由于之前量较小,课堂大部分模块使用同个DB实例(ip+port),上量前这个核心DB的cpu在20%、qps在1k左右,评估下来风险很大:
-
扩展性差:主机没法扩展,从机不建议超5组,且有主备延迟风险
-
耦合度高:任一svr链接数或 sql 没控制好,就算是边缘Svr都可能搞垮DB一挂全挂
-
梳理复杂:涉及svr数100+,时间太赶来不及逐个梳理
也是历史设计的坑,后面数据层设计要多考虑吞吐量和可扩展性。但回不去了,硬骨头得啃下来,立了专项找DBA同学一起分析优化,主要有下面几块:
3.2 业务横向拆分
根据压测发现非常明显的28原则,比如top1的写sql占总量82%,是搜索推荐模块定时刷权重用的,这类模块相对独立,和其他模块表关联join等操作少,方便业务拆分。对于这类模块,像搜索推荐、数据分析、评论系统等,快速切独立DB解耦,规避互相影响。
方便业务拆分的切走后,剩下能快速上的就是读写分离扩ro组了。快速扩了4个ro组,把较独立模块sql切过去,规避互相影响,也分摊了主机压力。因为复制模式是半同步的,也需关注主备同步延时,做好监控,特别是一些对延迟敏感的模块。
3.3 慢查询优化
横向能拆的都快速搞了,主DB风险还是很高,除了升级DB机器配置,剩下就只能逐个做慢sql优化了。采用mysqldumpslow对慢查询日志做归并排序,就可很清楚平均耗时/扫描行数/返回记录数top的慢sql,基本优化也是围绕着索引来,比如:
-
查询没有走索引
-
访问的数据量太大走全表
-
OR的情况无法使用索引
-
在索引上面直接进行函数计算
-
没有使用联合索引
-
唯一索引没有命中数据
优化效果:主db峰值cpu负载从20%下降到5%左右
3.4 连接数优化
连接数上也出过一些很惊险的case:鉴权svr凌晨扩100台机器,没考虑到对DB连接数影响,svr起来后DB连接数瞬间增长2k+差点爆掉。除了对top的svr减少了连接数外,引入DB代理也是个较快的解决方案,由于之前上云对ProxySql和NginxTcpProxy都有实践过,所以这次刚好也使用上。
优化效果:主db峰值链接数从4.6k下降到3.8k
四、 阶段3:核心模块逐个专项击破
4.1 接入:血的教训
课堂支持学生在pc/web/app/ipad/h5/小程序等多端进行学习,接入模块属于基础组件改动不大,但这次web接入模块却出了2个故障,1次还上了微博热搜,确实不应该。
针对这2个问题也做了专项复盘:
-
校准压测用例,更模拟现网流量
-
nginx动静分离,上报等接口也独立出去
-
nginx规则精简,接入层尽量打薄,逻辑后移
-
统一机器net.core.somaxconn等参数配置,重点监控告警
-
压测完要清理战场,关注fd等指标是否恢复
-
升级tomcat规避挂死bug
-
升级tomcat遵循RFC3986规范,规避特殊字符影响 ......
4.2 资料:坑爹的Agent
由于课堂这几年课程/老师数都维持在10万量级,历史上就把这些数据全量Load到1块1G的多阶hash共性内存上,部分C++模块依赖这个ShmAgent获取课程/老师数据,可减少Rpc调用提高性能和可用性。但随着极速版普及,课程/老师数不到2周就增长到100万量级,不仅1G内存放不下了,扩容流程也极其繁琐:
作为历史的坑专项讨论多次,由于时间太赶来不及重构,所以暂时也只能对数据裁剪后铺人力凌晨扩容。对于一些非核心且工作量小的,把ShmApi换成RpcApi调后端资料Svr。
这块没什么技术点,主要告诫团队后面少用SHM,微服务往云原生靠齐(12-Factor):
4.3 直播:站在云的肩膀上
课堂最核心的模块就是音视频,直播的进房成功率/首帧延迟/卡顿率/音画同步时延/分辨率等指标直接影响用户核心体验。由于直播模块之前已全部切云,这次站在云的肩膀上,业务不仅直接使用了云的多种直播模式,云音视频团队在整个疫情期间也提供非常给力的质量保障。
下面是具体的直播架构,业务通过流控Svr来控制各端走哪种直播模式:
4.4 消息:走推走拉?
随着极速版普及,各学校对单房间同时在线人数要求也越来越高,从3w->6w->30w->150w。对于大房间消息系统而言,核心要解决消息广播风暴的问题(30w人房间,有100人在同1秒发言,会产生30w*100=3kw/s消息),随着扩散因子的变大,之前纯推的方案已不能满足需求,参考了业内直播间的一些IM方案:
结合对比方案,也针对课堂产品特性,在原来纯推架构上新迭代一版推拉结合的架构
对于IM系统的设计,推荐一下这个文章:《新手入门一篇就够:从零开发移动端IM》 http://www.52im.net/thread-464-1-1.html
五、 阶段4:做好核心路径的防过载和柔性降级
在非常有限的时间里,逻辑层根本来不及重构,容量评估也不一定精准,过载保护和柔性降级就显得尤其重要。因为没时间全盘优化,在量突然暴涨的情况下,某个模块过载或者爆bug的概率会变大,所以在用户登录->查课表->上课的核心路径上,必须增加足够容错能力来提高可用性。
5.1 雪崩来得猝不及防
疫情初期课堂就遇到一个雪崩的case:2月12号早上,直播间拉取成员列表接口有失败毛刺,因为web没做异常保护,失败直接把循环拉取间隔时间置0,导致接口调用量越滚越大,B侧拉取涨了10倍后雪崩超时。由于没预埋开关等控制策略,得回滚web版本才解决。
这个case暴露了过载保护的缺失,一方面web没对异常返回做合理处理保护后端,一方面svr没有识别雪崩请求做限频,除此之外,也缺少一些配置开关可快速控制web循环间隔时间,导致雪崩来得猝不及防。
5.2 过载保护策略
针对这类badcase,对核心路径的服务做了很多过载保护和柔性降级策略,这里把一些典型方案记录下:
5.3 限流和熔断
高并发场景为了规避过载的级联传递,防止全链路崩溃,制定合理的限流和熔断策略是2个常见的解决方案。以这次疫情互动直播限流场景为例,互动直播默认只部署最多支撑600w同时在线的接口机资源,如果哪天突发超过了600w学生:
限流算法选择上,最常见就是漏桶和令牌桶。不是说令牌桶就是最好的,只有最合适的,有时简单的计数器反而更简单。golang拓展库 golang.org/x/time/rate 就提供了令牌桶限流器,3个核心api:
除了算法外,怎么把限流集成到框架、分布式限流实现、限流后请求优先级选择等问题,可以做得更深入,但很遗憾这次没时间搞,后面继续实践。
熔断是另一个重要防过载策略,其中熔断器Hystrix最为著名,github.com/afex/hystrix-go 就提供了其golang版本实现,使用也简单。其实L5就包含了熔断能力,包括熔断请求数阈值、错误率阈值和自动恢复探测策略。
5.4 Apollo配置中心
好的组件都是用脚投票,这次疫情期间,很多策略开关和阈值控制都是用Apollo配置中心来做,实现配置热更新,在高可用上实践也不错。很多时候多预埋这些配置就是用来保命的,当监控发现趋势不对时,可快速调整规避事故发生,简单列些例子:
-
后端限流阈值大小,后端要过载时可调小
-
Cache缓存时间,数据层负载高时可调大
-
非核心路径后端调用开关,必须时关闭调用补上降级默认值
-
前端定时调用的间隔时间,后端要过载时可调大 ......
当然,如果可做到系统自动触发调整配置就更进一步了,当时有想过但时间太赶没实践,有兴趣同学可思考实践下。
Apollo是携程开源的分布式配置中心,能够集中化管理应用不同环境配置,实现配置热更新,具备规范的权限、流程治理等特性,适用于微服务配置管理场景。补个架构图推荐下:
六、 阶段5:服务性能优化实战
在抗住前2周最猛的流量增长后,下来很长一段时间都是在优化服务的性能和稳定性、处理用户反馈和打磨产品体验上。这里沉淀3个服务性能优化上印象较深刻的点
6.1 分析利器 pprof+torch
在性能分析上,对比c++,golang提供了更多好用的工具,基本每次性能分析都是先用pprof+torch跑一把。通过框架中嵌入net/http/pprof并监听http遥测端口,OA管理后台就可随时得到svr协程/cpu/内存等相关指标。
6.2 缓存设计和踩坑
回过头看,大部分服务性能瓶颈还是在数据层或Rpc调用上,很多时候数据一致性要求没那么高,加缓存是最简单的首选方案。关于缓存的设计,无论是本地缓存、分布式缓存、多级缓存,还是Cache Aside、Read/Write Through、Write Behind Caching等缓存模式,就看哪种更适合业务场景,这里也不累赘,核心说下这次实践中踩的2个坑:
1、缓存击穿
-
案例:高频访问的缓存热key突然失效,导致对这个key的读瞬间压到DB上飙高负载
-
方案:使用异步更新或者访问DB加互斥锁
2、缓存穿透
-
案例:访问DB中被删除的key,这些key在缓存中也没有,导致每次读直接透到DB
-
方案:把这些key也缓存起来,但要关注恶意扫描的影响
6.3 为啥qps压不上去?
疫情期间,有一个现象很奇怪但又经常出现:压测时cpu很低,pprof+torch看不出什么异常,数据层返回也很快,但吞吐量就是上不去。一开始思路较少,后面也慢慢知道套路了,这里列几个真实的case供参考:
-
锁竞争:如死锁、锁粒度太大等,关注锁时间上报
-
打日志:日志量过大等导致磁盘IO彪高,在高并发场景尤其要注意精简日志量
-
进程重启:如panic或oom导致进程被kill,重启过程请求超时,要补齐进程重启监控
-
队列丢包:如请求缓存队列设置过小等,要关注队列溢出监控 ......
比如最后这点,就遇过这样的case:一次凌晨压测,其他机器都正常,就2个新机器死活一直超时,业务指标也看不出区别,折腾了好一阵,才发现monitor上 [监听队列溢出(ListenOverflows)] 这个值有毛刺异常。继续深挖下去,证明请求在tcp队列就溢出了,tcp的accept队列长度 =min(backlog,SOMAXCONN),查看新机器内核配置 [net.core.somaxconn=128],确实比其他机器小,神坑。
所以后续也增加了服务器tcp的半连接和全连接队列相关监控:
最后挂个招聘
在这次疫情的推动下,在线教育越来越普及,各大互联网公司都持续加码,教育也是个有温度的事业,百年大计,教育为本。团队聚焦golang和云原生,还有大量后台HC希望大家推荐或自荐,欢迎随时勾搭。
以上所述就是小编给大家介绍的《腾讯课堂停课不停学:业务后台总结》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Python语言程序设计
[美]梁勇(Lang Y. D.) / 李娜 / 机械工业出版社 / 2015-4 / 79.00元
本书采用“问题驱动”、“基础先行”和“实例和实践相结合”的方式,讲述如何使用Python语言进行程序设计。本书首先介绍Python程序设计的基本概念,接着介绍面向对象程序设计方法,最后介绍算法与数据结构方面的内容。为了帮助学生更好地掌握相关知识,本书每章都包括以下模块:学习目标,引言,关键点,检查点,问题,本章总结,测试题,编程题,注意、提示和警告。 本书可以作为高等院校计算机及相关专业Py......一起来看看 《Python语言程序设计》 这本书的介绍吧!