腾讯问卷一直支撑着腾讯的调研问卷,但它太重,不适合用在微信群实时投票的场景,结合年初微信小程序发布之际,针对微信群场景,我们(CDC)做了个投票小程序。
大家忙活几周,第一版总算出来了。在运营阶段发现一个问题,而这个问题在腾讯问卷中也存在着:
闲时低负载,峰值高并发
腾讯问卷一直支撑着腾讯公司旗下几乎所有业务的调研问卷,例如游戏、音乐,以及滴滴等外部合作公司。基于公司的规模,问卷可能会在瞬间投放给动辄数十万的用户。平时可能用户不多,但只要有业务做大规模的推广时,系统负载会变得特别高。
而在投票小程序当中,这种问题更严重:
1. 无法控制个人用户发起投票的时间
2. 低估了社交场景的传播力量。不少投票可能是单位/学校发起的投票,要求所有员工/学生参与投票,除此之外,用户还会再转发到外部群,生成二维码转发到朋友圈去拉票
于是我们经常会从监控中看到流量暴涨:
流量暴涨,峰值接近平时的 5 倍
面对这种情况,除了对应用本身做优化,也做出了一个迁移腾讯云的决定。于是,在这个背景下,开始了拥抱腾讯云的工作。
迁移腾讯云的过程,开始筹备
1. 上腾讯云前的筹备
腾讯投票在立项初期是基于腾讯问卷的接口去开发的。所以第一步考虑的是有哪些组件可以剥离,以减少迁移的工作量,和提高后续的可维护性。
- 数据库:腾讯问卷因为业务的原因选用了 MySQL、MongoDB 和 Redis,然而并不适合投票。存储和统计只使用 MySQL 即可,MongoDB 可以去除。
- 代码库:共用一个,严格来讲这已经是两个项目了,所以需要拆分。
- 域名:腾讯投票与腾讯问卷共用了 wj.qq.com,根据路径转发请求到不同的服务上。如果腾讯投票迁移至腾讯云了,这个转发就得走公网。为避免这个问题,我们通过更换域名来解决。先在 IDC 内进行域名切换,让腾讯投票用上一个独立的域名,迁移完毕后直接修改 DNS 解析。
- 内部服务:鹅厂的传统技术架构下很多服务可以通过内网接口调用的方式来解决。例如检测用户内容是否包含有敏感词的关键词服务,改为腾讯云通过代理访问 IDC 的服务。
剩下一个最麻烦的:数据库拆分。目前腾讯投票与腾讯问卷的数据都在同一个数据库。如何把数据拆分呢?我们把过程分成 4 步:
- 双写:写入旧数据库的同时也往新数据库写。这样能确保新数据库只有腾讯投票的数据。由于是异步写入,基本不会对用户的请求造成影响。
- 同步:往新数据库补充旧数据,直到两个数据库完全一致。
- 校验:校验两个数据库的数据是否完全一致。
- 切换:确保数据一致后进行切换并停止双写。
现在我们得到了完整且没有多余数据的独立数据库了,后续迁移时只需要备份和恢复这个数据库即可。
迁移腾讯云的过程,迁移
2. 迁移
该优化的都优化好了,开始准备迁移方案。不停机的方案都有哪些?以下是我们的分析:
1. 腾讯云通过专线访问 IDC 的 MySQL
– 优:对于业务比较安全
– 缺:对于公司不安全
2. 腾讯云通过公网访问 IDC 的 MySQL
– 优:方便
– 缺:不安全
3. 在 IDC 运行期间双写 IDC 和腾讯云的数据库,数据一致时进行迁移和切换
– 优:无需额外策略、安全、不需要停机
– 缺:工作量巨大
停机迁移的方案?也有,就是直接停机,备份和恢复 MySQL,改 DNS 解析,再笨也能做好这件事
– 优:安全可靠,时间成本低
– 缺:需要停止服务
考虑到安全策略、时间成本等因素,我们最后选择了停机迁移。为了不出问题,切割前后还有一些工作:
演练
方案选择了,环境也准备好了,接下来是反复演练,检查迁移过程中可能会出现的问题,甚至把执行过的每一条 Shell 命令都记录下来。直到所有记录的 Shell 命令不需要再做修改,直接执行就能完成迁移工作。
切割
前期工作准备好,风险也分析了,回滚方案也有了,演练了这么多遍,也该上战场了,再不迁移,老板休假回来要找我麻烦了。找了一个周末凌晨的时间点,准备好停机公告。然后就可以照着演练时的步骤一步一步操作了。测试通过后就可以做 DNS 切换了。
观察
进行 DNS 切换后就意味着流量都会直接到腾讯云上的环境。接下来的几个小时是最紧张的时间,在监控上看着流量慢慢起来,用户创建的投票也多了起来,这才松了一口气。
关于跨机房迁移,不同的项目有不同的解决方案。具体情况具体分析,如何合理配置原有的 IDC 资源与云计算资源,可能会取决于项目的 SLA、开发团队的规模,安全策略的限制等因素。
迁移腾讯云的过程,弹性伸缩调优
3. 弹性伸缩
前面提到我们的痛点之一是闲时低负载,峰值高并发,有没有解决办法?有,腾讯云的弹性伸缩。利用弹性伸缩,可以做到白天高峰期自动加机器,晚上销毁。任意时间内如果访问量突增,也能自动加机器并投入生产环境。
在介绍弹性伸缩基础概念之后,还需要介绍两个名词:无状态化与服务发现
无状态化
无状态化是指服务不保存需要持久化的数据(不管是短暂的 session 还是长期的用户上传附件)。好处是可以快速复制和销毁实例而不需要考虑数据是否会丢失,这也是弹性伸缩对应用的基本要求。
因为腾讯问卷有文件上传等一系列等功能,无状态化会很困难,得需要很多时间和精力。而投票刚好没有用到这些功能。没有文件上传等功能,session 也没有保存到文件系统。天生就是无状态,非常适合做水平扩展,新增实例只需要加到负载均衡上就能投入使用。
服务发现
无状态化好处之一是快速复制或者销毁实例,这样就可以做到快速地水平扩容。如果这种水平扩容还需要人工参与,那效率会低效很多。所以必须跑集群式的服务。于是你会需要服务发现工具。
服务发现可以告诉你:哪个服务都有哪些实例在提供,例如:
监控脚本问:腾讯投票的后端服务器有哪几台?
服务发现回答:10.0.0.1:8080, 10.0.0.2:8080, 10.0.0.3:8080
在收到回复后,监控脚本就可以把这几个 IP 加到 Nginx 或者 HAProxy 的负载均衡中去了。
在弹性伸缩的帮助下,腾讯投票的后端服务器频繁变更,在服务发现软件 Consul 的帮助下,做到了新增机器时能投入使用,销毁时自动从 Nginx 中摘除,达到了不丢失用户请求的效果。
小结(以上两点需要:策略配置)
应用做好了上述的无状态化与服务发现机制后,接下来就是腾讯云的弹性伸缩配置:
- 制作镜像:这也是腾讯云推荐弹性伸缩的使用方式,需要使用的软件预先安装到镜像中,机器由镜像启动后都带有了运行环境,无需再花时间初始化机器。
- 设置启动配置:这里指的是弹性伸缩自动开启的机器需要什么样的配置,多大的内存,多少核的 CPU,由哪个镜像启动,要在哪个机房启动(腾讯云有多个机房)等选项。
- 配置告警策略:当现有实例处于什么状态时新建实例?在我们观察了一段时间后,发现 CPU 超过 70% 和内存超过 60% 时,就应该考虑新增机器了。
在配合腾讯云的弹性伸缩、服务发现 Consul 以及各种监控系统的情况下,我们做到了:当系统高负载时,弹性伸缩开启新机器,监控脚本同步最新的代码以及启动相应的服务。最后,Consul 将新机器投入使用。
弹性伸缩的配置
当 CPU 利用率超过 70% 时加机器。
监控告警
图中可以看出 12:00 触发告警,12:02 机器启动完成,12:04 投入使用。弹性伸缩还是比较给力的。
迁移腾讯云的过程,监控
4. 监控
一路忙活,做了很多改动,有没有影响到用户?性能有没有变化?快了还是慢了?总不能让用户来告诉我们吧。还好有监控。
有了监控就知道每次变更带来了什么影响,在做运维变更、版本发布时,心里也比较有底。开发者也应该养成良好习惯,每次做完变更、发完版就要看看监控。
比如有一次,我们通过性能监控发现微信接口异常。当时,曲线显示用户投票量突然减少一半,但系统各组件都正常,也没有报错。排查后发现是微信开发平台接口做了变更,把一个字段给去掉了。如果没有监控,估计要等到第二天才能发现。
说了那么多,究竟监控什么呢?以下是我们所使用的监控系统:
- ELK 监控,监控了前端上报、Nginx 请求、PHP 请求、用户创建投票量、用户投票量等。后面做了动态扩容,又监控每一个实例的运行情况。
- 腾讯云监控,监控服务器 CPU、内存、带宽等,不用再自己维护 Nagios 等软件了。
- 腾讯云拨测,定时从多个接入点检测 HTTP 接口是否正常,异常时发短信告警,非常方便。这还避免了监控和应用一起挂掉,连通知都没法发出的尴尬局面。
多方位监控
CPU 动不动就会飙高,幸好有弹性伸缩。此外,我们正在优化投票结果的数据结构,优化完后 CPU 的波动应该会有改善
带宽跟随请求一并增加了
对比一下迁移前后的效果:
可以看出红色的慢请求减少,最底下的绿色也增多了。
服务器利用率这里还有优化空间,我们会在下一篇文章详细介绍。
5. 总结与展望
腾讯投票的定位是一款小而美的应用,像张小龙先生所说,用完就走,成为一个对用户有价值的小工具。
后续我们也计划将腾讯问卷 https://wj.qq.com 的 IDC 资源与腾讯云资源结合,使用弹性伸缩做到动态扩容,在提高运算能力的提前下减少运营成本。以及利用腾讯云的各种云服务为开发同学减轻运维负担,让开发同学更专注于开发业务,为用户提供更多更有价值的创新。
扫一扫,体验一下运行在腾讯云的腾讯投票
Tencent CDC(http://cdc.tencent.com/2017/08/11/是的,腾讯投票已经拥抱腾讯云了/)