腾讯课堂后台扩容和性能优化实战

项目背景

大年初一,吃着火锅唱着歌,突然收到重庆十一中的求助信:受疫情影响,年后学校无法开学,高三老师学生都很担心影响到高考,问腾讯课堂能否提供线上平台给高三复课,拉开了整个停课不停学专项的序幕。

极速版的诞生

由于课堂是面向线上培训机构的,这次想把十一中这样的传统线下校园,搬到腾讯课堂内上课才发现困难重重:

  1. 入驻:学校各类资质和机构完全不一样,审核周期长

  2. 发课:机构发课有很多规范约束,而学校用课程表排课,一个个发课成本高

  3. 直播:学校老师转线上上课,普遍说直播工具有上手成本

耗了很多人力才把十一中的入驻发课和老师培训搞完,同时其他学校也陆续找过来了,才发现根本没人力能对接这么多学校。就在这时,小马哥发话了:“把入驻发课全砍掉,快速做个腾讯课堂极速版,老师下载完就能自助上课了”

初 3 收到军令状,公司 2 个通宵生死急速开发完,初 6 凌晨团队体验,解决完体验问题后白天急速上线外发。随着各省市教育厅陆续宣布使用急速版复课,课堂 pcu/dau 开始起飞,短短 2-3 周,各项指标百倍增长,AppStore 免费类排行榜进 Top10,教育类稳居 Top1。

架构挑战

下面是课堂后台架构图,按之前的架构设计和模块部署,突然要在 2 周内支持量 100 倍增涨,同时还要开发校园版需求,时间赶且任务重。这里分五个阶段把架构挑战和解决策略介绍下。

阶段 1:先抗住后优化

面对 2 周 100 倍量级增长,重构肯定来不及了,且过大改动仓促上线反而会增加不稳定因素。所以初期思路就是“先抗住后优化”:梳理极速版用户路径,评估路径上各模块容量,快速扩容后,每天凌晨例行全链路压测,持续验证迭代。

模块梳理和接口裁剪

和产品讨论完用户路径和访问量级后,各页面 qps 也基本有个数了,就开始梳理每个页面调用接口列表,明确每个接口要支撑的 qps:

由于课堂微服务很多,为了争取时间,需聚焦核心路径减少梳理复杂度,对于非核心体验和风险较大的这 2 类接口,抛出来和产品讨论做页面接口裁剪。

系统容量评估

模块和接口梳理清楚后,就开始分负责人对系统做容量评估。

要特别关注木桶效应,很多新同学只评估了逻辑 Svr 这一层,其实从用户端->接入层->逻辑层->存储层全链路都得涉及,不能让任一环节成短板。

扩容扩容扩容!!

各模块扩容数算清楚后,剩下的就是申请机器部署了。扩容本该是个很简单的活,但因为历史债务等问题,部分模块费了很多周折,比如:

  1. 容器化和上 k8s 不彻底

  2. 部分 c++模块依赖 ShmAgent,扩容流程极其繁琐

  3. 扩容 svr 导致 DB 链接数爆炸 ...

针对扩容暴露的问题,从接入->逻辑->存储,沉淀了很多设计经验,后面得彻底改造掉,特别是 k8s 这块应尽快全面铺开。这里终极目标是:针对量级暴涨的情况,不用花人力做评估和扩容,整个系统就有自动伸缩的能力。

全链路压测

在初步扩容完后,为了防止梳理不全、评估不准等情况,例行全链路压测验证非常重要,可以挖掘性能瓶颈和系统隐患。

在测试同学给力支持下,每天例行执行下面流程,持续扩容优化迭代:

  1. 校准压测模型:非常重要,压测用例设计会直接关系到压测效果

  2. 确定压测目标:把每个模块/接口的压测 qps 确定下来

  3. 执行压测任务:凌晨 12 点启动整站压测流水线,执行星海用例,输出压测结论

  4. 回归压测结果:压测不达标接口记录 doc,尽快暴露隐患,责任人分析原因给解决方案

压测 QCI 流水线:

每日不达标记录:

全链路压测方案:

阶段 2:瓶颈最先出在 DB 数据层

根据先抗住后优化的思路,可扩容的都容易解决,架构瓶颈会最先出现在伸缩性差、不容易扩容的环节上,经常会是数据层,课堂这次也中招了。

核心 DB,一挂全挂

由于之前量较小,课堂大部分模块使用同个 DB 实例(ip+port),上量前这个核心 DB 的 cpu 在 20%、qps 在 1k 左右,评估下来风险很大:

  1. 扩展性差:主机没法扩展,从机不建议超 5 组,且有主备延迟风险

  2. 耦合度高:任一 svr 链接数或 sql 没控制好,就算是边缘 Svr 都可能搞垮 DB 一挂全挂

  3. 梳理复杂:涉及 svr 数 100+,时间太赶来不及逐个梳理

也是历史设计的坑,后面数据层设计要多考虑吞吐量和可扩展性。但回不去了,硬骨头得啃下来,立了专项找 DBA 同学一起分析优化,主要有下面几块:

业务横向拆分

根据压测发现非常明显的 28 原则,比如 top1 的写 sql 占总量 82%,是搜索推荐模块定时刷权重用的,这类模块相对独立,和其他模块表关联 join 等操作少,方便业务拆分。对于这类模块,像搜索推荐、数据分析、评论系统等,快速切独立 DB 解耦,规避互相影响。

方便业务拆分的切走后,剩下能快速上的就是读写分离扩 ro 组了。快速扩了 4 个 ro 组,把较独立模块 sql 切过去,规避互相影响,也分摊了主机压力。因为复制模式是半同步的,也需关注主备同步延时,做好监控,特别是一些对延迟敏感的模块。

慢查询优化

横向能拆的都快速搞了,主 DB 风险还是很高,除了升级 DB 机器配置,剩下就只能逐个做慢 sql 优化了。采用 mysqldumpslow 对慢查询日志做归并排序,就可很清楚平均耗时/扫描行数/返回记录数 top 的慢 sql,基本优化也是围绕着索引来,比如:

  1. 查询没有走索引

  2. 访问的数据量太大走全表

  3. OR 的情况无法使用索引

  4. 在索引上面直接进行函数计算

  5. 没有使用联合索引

  6. 唯一索引没有命中数据

优化效果:主 db 峰值 cpu 负载从 20%下降到 5%左右。

链接数优化

链接数上也出过一些很惊险的 case:鉴权 svr 凌晨扩 100 台机器,没考虑到对 DB 链接数影响,svr 起来后 DB 链接数瞬间增长 2k+差点爆掉。

除了对 top 的 svr 减少链接数外,引入 DB 代理也是个较快的解决方案,由于之前上云对 ProxySql 和 NginxTcpProxy 都有实践过,所以这次刚好也使用上。

具体可参考之前的文章 《谈下 mysql 中间件(问题域、业内组件)》:

https://cloud.tencent.com/developer/article/1349133

优化效果:主 db 峰值链接数从 4.6k 下降到 3.8k。

阶段 3:核心模块逐个专项击破

接入:血的教训

课堂支持学生在 pc/web/app/ipad/h5/小程序等多端进行学习,接入模块属于基础组件改动不大,但这次 web 接入模块却出了 2 个问题,确实不应该:

针对这 2 个问题也做了专项总结:

  1. 校准压测用例,更模拟现网流量

  2. nginx 动静分离,上报等接口也独立出去

  3. nginx 规则精简,接入层尽量打薄,逻辑后移

  4. 统一机器 net.core.somaxconn 等参数配置,重点监控告警

  5. 压测完要清理战场,关注 fd 等指标是否恢复

  6. 升级 tomcat 规避挂死 bug

  7. 升级 tomcat 遵循 RFC3986 规范,规避特殊字符影响

直播:站在云的肩膀上

课堂最核心的模块就是音视频,直播的进房成功率/首帧延迟/卡顿率/音画同步时延/分辨率等指标直接影响用户核心体验。由于直播模块之前已全部切云,这次站在云的肩膀上,业务不仅直接使用了云的多种直播模式,云音视频团队在整个疫情期间也提供非常给力的质量保障。

下面是具体的直播架构,业务通过流控 Svr 来控制各端走哪种直播模式:

消息:走推走拉?

随着极速版普及,各学校对单房间同时在线人数要求也越来越高,从 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 的概率会变大,所以在用户登录->查课表->上课的核心路径上,必须增加足够容错能力来提高可用性。

雪崩来得猝不及防

疫情初期课堂就遇到一个雪崩的 case:直播间拉取成员列表接口有失败毛刺,因为 web 没做异常保护,失败直接把循环拉取间隔时间置 0,导致接口调用量越滚越大,B 侧拉取涨了 10 倍后雪崩超时。由于没预埋开关等控制策略,得回滚 web 版本才解决。

这个 case 暴露了过载保护的缺失,一方面 web 没对异常返回做合理处理保护后端,一方面 svr 没有识别雪崩请求做限频,除此之外,也缺少一些配置开关可快速控制 web 循环间隔时间,导致雪崩来得猝不及防。

过载保护策略

针对这类 badcase,对核心路径的服务做了很多过载保护和柔性降级策略,这里把一些典型方案记录下:

限流和熔断

高并发场景为了规避过载的级联传递,防止全链路崩溃,制定合理的限流和熔断策略是 2 个常见的解决方案。

以这次疫情互动直播限流场景为例,互动直播默认只部署最多支撑 600w 同时在线的接口机资源,如果哪天突发超过了 600w 学生:

限流算法选择上,最常见就是漏桶和令牌桶。不是说令牌桶就是最好的,只有最合适的,有时简单的计数器反而更简单。golang 拓展库 golang.org/x/time/rate 就提供了令牌桶限流器,3 个核心 api:

1、func (*Limiter) Allow: 没有取到token返回false,消耗1个token返回true
2、func (*Limiter) Wait: 阻塞等待,直到取到1个token
3、func (*Limiter) Reserve: 返回token信息,返回需要等待多久才有新的token

除了算法外,怎么把限流集成到框架、分布式限流实现、限流后请求优先级选择等问题,可以做得更深入,但很遗憾这次没时间搞,后面继续实践。

熔断是另一个重要防过载策略,其中熔断器 Hystrix 最为著名,github.com/afex/hystrix-go 就提供了其 golang 版本实现,使用也简单。其实 L5 就包含了熔断能力,包括熔断请求数阈值、错误率阈值和自动恢复探测策略。

Apollo 配置中心

好的组件都是用脚投票,这次疫情期间,很多策略开关和阈值控制都是用 Apollo 配置中心来做,实现配置热更新,在高可用上实践也不错。很多时候多预埋这些配置就是用来保命的,当监控发现趋势不对时,可快速调整规避事故发生,简单列些例子:

  1. 后端限流阈值大小,后端要过载时可调小

  2. Cache 缓存时间,数据层负载高时可调大

  3. 非核心路径后端调用开关,必须时关闭调用补上降级默认值

  4. 前端定时调用的间隔时间,后端要过载时可调大 ......

当然,如果可做到系统自动触发调整配置就更进一步了,当时有想过但时间太赶没实践,有兴趣同学可思考实践下。

Apollo 是携程开源的分布式配置中心,能够集中化管理应用不同环境配置,实现配置热更新,具备规范的权限、流程治理等特性,适用于微服务配置管理场景。补个架构图推荐下:

阶段 5:服务性能优化实战

在抗住前 2 周最猛的流量增长后,下来很长一段时间都是在优化服务的性能和稳定性、处理用户反馈和打磨产品体验上。这里沉淀 3 个服务性能优化上印象较深刻的点。

分析利器 pprof+torch

在性能分析上,对比 c++,golang 提供了更多好用的工具,基本每次性能分析都是先用 pprof+torch 跑一把。通过框架中嵌入 net/http/pprof 并监听 http 遥测端口,管理后台就可随时得到 svr 协程/cpu/内存等相关指标,比如优化前的成员列表 svr 火焰图 case。

结合代码,便可快速有些优化思路,比如:

  1. 分离 B/C 调用部署

  2. 优化 pb 序列化,如做些 cache

  3. 简化定时器使用场景

  4. 调整大对象使用优化 gc 消耗

最终根据这些优化思路改版,让超 200ms 的比例从 0.2%降到 0.002%以下:

缓存设计和踩坑

回过头看,大部分服务性能瓶颈还是在数据层或 Rpc 调用上,很多时候数据一致性要求没那么高,加缓存是最简单的首选方案。

关于缓存的设计,无论是本地缓存、分布式缓存、多级缓存,还是 Cache Aside、Read/Write Through、Write Behind Caching 等缓存模式,就看哪种更适合业务场景,这里也不累赘,核心说下这次实践中踩的 2 个坑:

1、缓存击穿

  • 案例:高频访问的缓存热 key 突然失效,导致对这个 key 的读瞬间压到 DB 上飙高负载

  • 方案:使用异步更新或者访问 DB 加互斥锁

2、缓存穿透

  • 案例:访问 DB 中被删除的 key,这些 key 在缓存中也没有,导致每次读直接透到 DB

  • 方案:把这些 key 也缓存起来,但要关注恶意扫描的影响

为啥 qps 压不上去?

疫情期间,有一个现象很奇怪但又经常出现:压测时 cpu 很低,pprof+torch 看不出什么异常,数据层返回也很快,但吞吐量就是上不去。一开始思路较少,后面也慢慢知道套路了,这里列几个真实的 case 供参考:

  1. 锁竞争:如死锁、锁粒度太大等,关注锁时间上报

  2. 打日志:日志量过大等导致磁盘 IO 彪高,在高并发场景尤其要注意精简日志量

  3. 进程重启:如 panic 或 oom 导致进程被 kill,重启过程请求超时,要补齐进程重启监控

  4. 队列丢包:如请求缓存队列设置过小等,要关注队列溢出监控 ......

比如最后这点,就遇过这样的 case:一次凌晨压测,其他机器都正常,就 2 个新机器死活一直超时,业务指标也看不出区别,折腾了好一阵,才发现 monitor 上 监听队列溢出(ListenOverflows) 这个值有毛刺异常。

继续深挖下去,证明请求在 tcp 队列就溢出了,tcp 的 accept 队列长度=min(backlog,SOMAXCONN),查看新机器内核配置 net.core.somaxconn=128,确实比其他机器小,神坑。

所以后续也增加了服务器 tcp 的半连接和全连接队列相关监控:

相关推荐

  1. 高德服务单元化方案和架构实践
  2. 微服务部署:蓝绿部署、滚动部署、灰度发布、金丝雀发布

  3. 蚂蚁金服蓝绿发布实践

  4. SET化消息中间件架构实现

  5. SET化架构设计

  6. 快手大数据架构演进实录

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
微服务是什么?微服务是用于构建应用程序的架构风格,一个大的系统可由一个或者多个微服务组成,微服务架构可将应用拆分成多个核心功能,每个功能都被称为一项服务,可以单独构建和部署,这意味着各项服务在工作和出现故障的时候不会相互影响。为什么要用微服务?单体架构下的所有代码模块都耦合在一起,代码量大,维护困难,想要更新一个模块的代码,也可能会影响其他模块,不能很好的定制化代码。微服务中可以有java编写、有Python编写的,他们都是靠restful架构风格统一成一个系统的,所以微服务本身与具体技术无关、扩展性强。大型电商平台微服务功能图为什么要将SpringCloud项目部署到k8s平台?SpringCloud只能用在SpringBoot的java环境中,而kubernetes可以适用于任何开发语言,只要能被放进docker的应用,都可以在kubernetes上运行,而且更轻量,更简单。SpringCloud很多功能都跟kubernetes重合,比如服务发现,负载均衡,配置管理,所以如果把SpringCloud部署到k8s,那么很多功能可以直接使用k8s原生的,减少复杂度。Kubernetes作为成熟的容器编排工具,在国内外很多公司、世界500强等企业已经落地使用,很多中小型公司也开始把业务迁移到kubernetes中。kubernetes已经成为互联网行业急需的人才,很多企业都开始引进kubernetes技术人员,实现其内部的自动化容器云平台的建设。对于开发、测试、运维、架构师等技术人员来说k8s已经成为的一项重要的技能,下面列举了国内外在生产环境使用kubernetes的公司: 国内在用k8s的公司:阿里巴巴、百度、腾讯、京东、360、新浪、头条、知乎、华为、小米、富士康、移动、银行、电网、阿里云、青云、时速云、腾讯、优酷、抖音、快手、美团等国外在用k8s的公司:谷歌、IBM、丰田、iphone、微软、redhat等整个K8S体系涉及到的技术众多,包括存储、网络、安全、监控、日志、DevOps、微服务等,很多刚接触K8S的初学者,都会感到无从下手,为了能让大家系统地学习,克服这些技术难点,推出了这套K8S架构师课程。Kubernetes的发展前景 kubernetes作为炙手可热的技术,已经成为云计算领域获取高薪要掌握的重要技能,在招聘网站搜索k8s,薪资水平也非常可观,为了让大家能够了解k8s目前的薪资分布情况,下面列举一些K8S的招聘截图: 讲师介绍:  先超容器云架构师、IT技术架构师、DevOps工程师,曾就职于世界500强上市公司,拥有多年一线运维经验,主导过上亿流量的pv项目的架构设计和运维工作;具有丰富的在线教育经验,对课程一直在改进和提高、不断的更新和完善、开发更多的企业实战项目。所教学员遍布京东、阿里、百度、电网等大型企业和上市公司。课程学习计划 学习方式:视频录播+视频回放+全套源码笔记 教学服务:模拟面试、就业指导、岗位内推、一对一答疑、远程指导 VIP终身服务:一次购买,终身学习课程亮点:1. 学习方式灵活,不占用工作时间:可在电脑、手机观看,随时可以学习,不占用上班时间2.老师答疑及时:老师24小时在线答疑3. 知识点覆盖全、课程质量高4. 精益求精、不断改进根据学员要求、随时更新课程内容5. 适合范围广,不管你是0基础,还是拥有工作经验均可学习:0基础1-3年工作经验3-5年工作经验5年以上工作经验运维、开发、测试、产品、前端、架构师其他行业转行做技术人员均可学习课程部分项目截图   课程大纲 k8s+SpringCloud全栈技术:基于世界500强的企业实战课程-大纲第一章 开班仪式老师自我介绍、课程大纲介绍、行业背景、发展趋势、市场行情、课程优势、薪资水平、给大家的职业规划、课程学习计划、岗位内推第二章 kubernetes介绍Kubernetes简介kubernetes起源和发展kubernetes优点kubernetes功能kubernetes应用领域:在大数据、5G、区块链、DevOps、AI等领域的应用第三章  kubernetes中的资源对象最小调度单元Pod标签Label和标签选择器控制器Replicaset、Deployment、Statefulset、Daemonset等四层负载均衡器Service第四章 kubernetes架构和组件熟悉谷歌的Borg架构kubernetes单master节点架构kubernetes多master节点高可用架构kubernetes多层架构设计原理kubernetes API介绍master(控制)节点组件:apiserver、scheduler、controller-manager、etcdnode(工作)节点组件:kube-proxy、coredns、calico附加组件:prometheus、dashboard、metrics-server、efk、HPA、VPA、Descheduler、Flannel、cAdvisor、Ingress     Controller。第五章 部署多master节点的K8S高可用集群(kubeadm)第六章 带你体验kubernetes可视化界面dashboard在kubernetes中部署dashboard通过token令牌登陆dashboard通过kubeconfig登陆dashboard限制dashboard的用户权限在dashboard界面部署Web服务在dashboard界面部署redis服务第七章 资源清单YAML文件编写技巧编写YAML文件常用字段,YAML文件编写技巧,kubectl explain查看帮助命令,手把手教你创建一个Pod的YAML文件第八章 通过资源清单YAML文件部署tomcat站点编写tomcat的资源清单YAML文件、创建service发布应用、通过HTTP、HTTPS访问tomcat第九章  kubernetes Ingress发布服务Ingress和Ingress Controller概述Ingress和Servcie关系安装Nginx Ingress Controller安装Traefik Ingress Controller使用Ingress发布k8s服务Ingress代理HTTP/HTTPS服务Ingress实现应用的灰度发布-可按百分比、按流量分发第十章 私有镜像仓库Harbor安装和配置Harbor简介安装HarborHarbor UI界面使用上传镜像到Harbor仓库从Harbor仓库下载镜像第十一章 微服务概述什么是微服务?为什么要用微服务?微服务的特性什么样的项目适合微服务?使用微服务需要考虑的问题常见的微服务框架常见的微服务框架对比分析第十二章 SpringCloud概述SpringCloud是什么?SpringCloud和SpringBoot什么关系?SpringCloud微服务框架的优缺点SpringCloud项目部署到k8s的流程第十三章 SpringCloud组件介绍服务注册与发现组件Eureka客户端负载均衡组件Ribbon服务网关Zuul熔断器HystrixAPI网关SpringCloud Gateway配置中心SpringCloud Config第十四章 将SpringCloud项目部署到k8s平台的注意事项如何进行服务发现?如何进行配置管理?如何进行负载均衡?如何对外发布服务?k8s部署SpringCloud项目的整体流程第十五章 部署MySQL数据库MySQL简介MySQL特点安装部署MySQL在MySQL数据库导入数据对MySQL数据库授权第十六章 将SpringCLoud项目部署到k8s平台SpringCloud的微服务电商框架安装openjdk和maven修改源代码、更改数据库连接地址通过Maven编译、构建、打包源代码在k8s中部署Eureka组件在k8s中部署Gateway组件在k8s中部署前端服务在k8s中部署订单服务在k8s中部署产品服务在k8s中部署库存服务第十七章 微服务的扩容和缩容第十八章 微服务的全链路监控什么是全链路监控?为什么要进行全链路监控?全链路监控能解决哪些问题?常见的全链路监控工具:zipkin、skywalking、pinpoint全链路监控工具对比分析第十九章 部署pinpoint服务部署pinpoint部署pinpoint agent在k8s中重新部署带pinpoint agent的产品服务在k8s中重新部署带pinpoint agent的订单服务在k8s中重新部署带pinpoint agent的库存服务在k8s中重新部署带pinpoint agent的前端服务在k8s中重新部署带pinpoint agent的网关和eureka服务Pinpoint UI界面使用第二十章 基于Jenkins+k8s+harbor等构建企业级DevOps平台第二十一章 基于Promethues+Alert+Grafana搭建企业级监控系统第二十二章 部署智能化日志收集系统EFK 

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值