【微服务】如何做线上全链路压测?
云栖号资讯:【点击查看更多行业资讯】
在这里您可以找到不同行业的第一手的上云资讯,还在等什么,快来!
1. 背景介绍
如今,在微服务架构盛行的互联网时代,微服务架构下模块(本文指可独立部署的服务)之间的关系错综复杂(哪怕是避免模块之间的直接循环依赖都很变得困难),评估一整套业务系统(集群)的容量已经不像评估单机系统那样容易,而系统的容量评估,是稳定性建设的核心内容之一,是我们绕不开的主题。
有了系统容量评估,配合今年的业务目标,我们才知道应该申请多少预算、什么时候需要扩容、系统瓶颈在哪、哪些服务(模块)需要扩容。评估系统容量或者准确的说 评估线上系统的容量现阶段最优效也是最准确的方式就是进行线上全链路压测。
2. 准备工作
你要问实现线上全链路压测难不难?当然难(现阶段稳定性工作哪一项不难?),但依然有迹可循。而且和当前技术体系的系统化建设程度以及各团队之间协作有关系。想实现线上全链路压测,我们需要做如下三个方面的准备工作(为了描述简单,本文的“全压”指的是线上全链路压测):
- 确定需要哪些团队参与
- 确定全压技术方案
- 设定全压目标和计划
3. 拆分详情
确定需要哪些团队参与
全压绝对是一项耗时耗力的工程,特别是刚开始的时候。首当其冲的当然是得到老大的支持,一般需要参与进来的至少有 研发、测试 和 运维 三个团队。研发团队主要负责技术方案的设定和实施(当然如果有架构组或中间件团队,技术方案的设定可以交给他们),测试团队负责验证全压方案和数据的正确性以及真正的施压,而运维团队需要关注压测对线上集群的影响以及一些辅助工作(例如提前调整网关的限流阈值)。
确定全压技术方案
这一步应该是难度最大的,不同技术体系具体实施方案当然不一样,但可以相互参考,就拿我的业务部门举例,我们服务端是 Java 栈,整个业务流量符合如下链路:
上图最左边的 App 指的是用户手机中装的 App,从后面的链路我们可以看出,业务网关后面就是我们的服务端系统,各模块之间使用 Dubbo 来进行交互,当然异步用的是 DDMQ,而当模块需要使用集团的中台服务时,我们使用的是 HTTP。模块内部还使用了线程池,也使用了 MySQL、Redis 等外部服务。
第一步,确定“全链路”应该包含链路(或顶级接口),所谓的全链路,它其实是一个相对的概念,在刚开始做全压时,我们主要是把线上的核心链路找出来,找到这些链路的顶级接口,这其实就是发压的主要入口。
第二步,确保压测标识在这些链路中传递以及处理,第二步是最难的也是最复杂的,我们要分析第一步中这些链路中如何有效安全的传递压测标识,压测标识是系统中用来区分压测流量还是线上正常流量的标识,我们要保证压测标识正确的传递和清除,否则可能导致严重的线上事故。这里将给出我们的做法,供大家参考,主要分四大部分:
- 尽可能的对模块无侵入或低侵入
微服务架构下可独立你部署的模块数可能会非常惊人,任何能成功实时的技术方案都应该要求是对业务模块是无侵入或者是低侵入的,否则将影响方案的推广以及实施成本,我们为了做到这一点,打算直接在我们的基础组件(内部使用的公共库和中间件)动刀子,尽可能的对用户透明。
- 压测标识安全的传递和处理
这个要分模块内、模块间、模块外三个部分来考虑:
模块内:假如模块内部已经知道该流量是压测流量,我们如何保证该压测流量能在模块内部复杂的逻辑处理中不丢失?模块内主要考虑的是线程中和跨线程执行的时候,压测标识容易丢失,线程中,我们使用的是对 ThreadLocal 的包装类(我们没使用阿里开源的 TransmittableThreadLocal)。而为了能够跨线程传递,我们修改了 taxi-thread 公共库,将其中的 TaxiThreadPoolExecutor 等类进行了修改,加入了压测标识的传递(这里补充下背景,我们为了 traceId 能跨线程传递,在 taxi-thread 公共库中包装了 JDK 线程池相关的类,并在开发规范中要求研发同学不能直接使用 JDK 原生的线程池)。还有一块,就是日志打印,为了能准确区分压测流量和正常流量,也为了压测流量不污染线上数据(比如线上很多模块有埋点日志),我们修改了 taxi-log(我们这边没有直接使用 SLF4J,而是使用包装过的日志公共库 taxi-log),将压测流量所有的日志打在原日志目录下的 shadow 影子目录下,这一切对用户也是透明的。
模块间:我们这边模块间的通讯方式主要是 Dubbo 和 DDMQ,Dubbo 这块的话我们直接通过 Filter 来实现压测标识传递,而 DDMQ 本身就自带压测标识传递方式,可以直接使用。
模块外:这一部分主要是存储、缓存以及一些外部服务(比如上图的中台服务)。
存储例如 MySQL、MongoDB 等,我们必须要隔离压测和线上数据,所以我们会事先建好所谓的 影子表,影子表其实和线上表的区别就是表名,影子表会在真实表名前加一个 shadow_ 前缀,而我们的 taxi-mybatis、taxi-mongo 等公共库在识别到压测标识时,会给表或者文档名称前也带上 shadow_ 前缀。之所以只是做表隔离而没有做库级别隔离,考虑到的还是降低侵入性和成本。关于存储,还有一个关键点,假如模块只提供查询服务(比如某些配置中心),如果按照前面说的,存储接入压测标识这块做成无侵入的话,全压流量查询也会走影子表,这也许是我们不希望看到的,所以在 MySQL 这块我们特意做成有侵入的(需要加一个插件配置),否则默认不识别压测标识。
对于分布式缓存,我们使用的是 Redis,这一块的处理方式和存储类似,我们修改了我们自己 Redis 包装的公共库,如果是识别到压测标识,默认在操作的 key 上加一个 shadow_ 前缀,保证压测流量不污染线上缓存数据。
对于外部服务,我们使用的是 HTTP 来调用,所以修改了我们 taxi-util 中的 HTTP 组件,做了压测标识的传递,保证下游外部服务能知道这是压测流量。那肯定有人问,如果下游服务不支持压测流量识别该咋办?所以这里我们借助了 SDS 服务降级系统( https://github.com/didi/sds ),可以只对压测流量进行拦截,使其不调用下游外部服务。
最后的效果如下:
第三步,确保全压流量能被监控到,这涉及到我们在实际全压中能否直观的感受到压测流量,这一块需要和内部的监控系统来打通,由于能方便的取到压测标识,这一块的实现我们不再阐述。
第四步,准备全压数据,确定接口调用比例,最理想的方式是能对线上流量进行克隆、放大和处理,作为压测输入数据来重放,但这块难度较大,需要有好的平台来支撑,我们目前只能使用更简单的方式来造数据。由于无法使用仿真数据,我们提前在影子表中造了一批用户、设备信息、位置等和业务相关的数据,然后去线上统计了链路上各顶级接口的流量和交易量的比例,来作为压测时流量放大的依据。当然,必不可少的还有一个发压工具或平台,例如滴滴的奥创发压平台。
确定全压目标和计划
全压前我们需要定下全压的目标,比如当前我们交易系统能支撑 100W 订单(现有日单量峰值),而业务今年的目标是冲击 300W 日订单,那按照峰值流量 2 倍来算,我们的交易系统需要支撑 600W 的单量,那么第一次全压的目标可以保守些,定为日订单 200W。因为哪怕线下验证已经充分,全压时也会遇到各种出乎意料的问题,当然发现问题其实也意味着我们发现了系统容量瓶颈,这也是全压的主要目的之一。全压计划也同样重要,因为我们系统一定是在不断的迭代中,上一次的全压结论可能会很快“过期”,所以我们需要定下明确的全压计划和节奏,不断降低全压的人力成本,使这一稳定性建设工作持续有效的进行下去。
4. 总结
截止到目前,我们已经进行过很多轮的全压,也在不断往全压中补充新的链路,加入新的模块,目前全压的人力成本还是较高,我们也在探索全自动化全压方案,到时候有成果将和大伙继续分享。
【云栖号在线课堂】每天都有产品技术专家分享!
课程地址:https://yqh.aliyun.com/zhibo立即加入社群,与专家面对面,及时了解课程最新动态!
【云栖号在线课堂 社群】https://c.tb.cn/F3.Z8gvnK
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
直播APP源码搭建简易直播平台及个人开发直播系统的难点
如何用直播APP源码搭建一个简易的直播平台一.前端推流1.推流可以采用命令: ffmpeg -i input -vcodec copy -acodec copy -f flv rtmp://127.0.0.1/live/cgstream0input 可以是实时流,也可以是文件,如果是文件 需要加上-re。运用中需要将127.0.0.1换成rtmp所在机器的ip地址。 用命令推流时间戳信息不能任意修改,想要达到一个满意的结果还是要用代码实现。 主要方法代码如下: 1.打开视频流,filename可以文件名称也可以是实时流url.2.创建输出上下文以及输出流,输出流的格式需要设置成flv 从输入流中读取音视频包 二. 服务端服务端可以选择crtmpserver,crtmpserver开源,在windows平台以及linux平台下都可以运行。随着人们对视频质量要求的提高,基本上视频的分辨率都是高清(1080p),码率基本会在4M以上。试想如果服务器网卡选择千兆网卡,单个网卡最多也就支持两百多路。一般来讲,服务器的cpu配置会比普通电脑高很多,支持几百路并发是不会出现性能问题。 三. 播放端如...
- 下一篇
桂花网蓝牙医疗物联网服务抗疫一线,实现医疗级全天候体征监测
云栖号资讯:【点击查看更多行业资讯】在这里您可以找到不同行业的第一手的上云资讯,还在等什么,快来! 新冠肺炎疫情之下,各行各业正经历着一场特殊的考验。首当其冲的医疗领域,正迎来一场体征监测的变革。 疫情期间,武汉一方舱医院就通过远距离蓝牙传输技术,实现了患者的全天候体征监测,医护人员无需再逐一为新冠患者测量体征数据,有效减小了医护人员的劳动强度,降低了感染风险,也提高了工作效率。 将体征监测并入物联网只是一小步。作为蓝牙物联网技术的首创者,桂花网正在引领一场“革命”,目前医疗领域的上下游企业正积极与桂花网合作,共同努力构建蓝牙医疗物联网生态圈。 桂花网医疗物联网结构图 医疗健康是关乎国计民生的大事,与百姓息息相关。随着生活水平的提高,人们也越来越重视个人健康问题。特别是受当下疫情影响,体温、呼吸、心率及血氧饱和度等体征数据已被看作是判断病情趋势的重要依据,这更使得人们对自身体温、心率、呼吸等各项体征数据变得更为关心。疫情期间,每天测测体温、心率、血氧饱和度等已成为个人健康管理的重要内容。 然而,无论是在家,还是在医院,传统的测量方式都存在一个弊端,就是这些体征数据都无法做到实时监测,不...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
-
Docker使用Oracle官方镜像安装(12C,18C,19C)
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- CentOS8编译安装MySQL8.0.19
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- MySQL8.0.19开启GTID主从同步CentOS8
- CentOS7,8上快速安装Gitea,搭建Git服务器
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
推荐阅读
最新文章
- SpringBoot2全家桶,快速入门学习开发网站教程
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- MySQL8.0.19开启GTID主从同步CentOS8
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- SpringBoot2整合Redis,开启缓存,提高访问速度
- Windows10,CentOS7,CentOS8安装Nodejs环境
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果