网易首页 > 网易号 > 正文 申请入驻

全链路压测在网易传媒的落地与实践

0
分享至

项目 背景

随着线上业务越来越复杂,请求链路上下游环节越来越多,如何多维度保障线上业务稳定性也越来越成为技术团队日常的又一重要工作组成部分。 那么如何能做到主动出击发现问题,不在线上事故出现后才疲于奔命,保障服务的同时又尽可能的节省投入资源成为了基础技术团队需要突破的方向,因此我们成立了稳定性保障小分队,启动了相关的一系列项目。

2

项目架构

在之前的工作中业务压测多集中于测试环境并针对单体服务,受制于线上和测试环境的差别,包含: 各种环境变量配置差别、服务器硬件资源差别、调用链路差别(是否通过网关等); 同时微服务化的逐步普及也导致以往常用的“线下小规模部署,外围服务mock,压测结果放大推导”思路,在大量微服务相互强依赖的微服务之间难以施展,最理想的情况是可以在线上环境进行压测,以最接近于真实流量为前提在用户之前发现问题。

为了快速定位问题,小分队开发了全链路追踪项目。项目核心方案:在各类请求header中增加全局唯一TraceId并可以在请求过程中不同服务之前进行透传,达到根据traceId将同一请求在不同服务中的请求数据进行关联的目的,这一项目上线后解决了线上压测面临的最大问题:无法区分正常流量和测试流量,我们利用全链路tracer agent同样实现了在测试流量header中增加压测标记,并在请求过程中跨服务进行透传。以此为基础,结合互联网各大公司使用的影子存储、流量录制等技术的实战经验,设计了适合传媒技术体系的全链路压测服务。

3

核心模块

3.1压测流量构建

全链路tracer agent随服务同时启动,拦截服务的所有请求并将traceId和压测标记向下游透传,同时根据分布式配置中心实时下发的配置决定是否要上报当前请求的path、headers、参数等(可指定录制的时间段),全链路追踪服务端接收请求后将数据保存到ES集群中方便后续使用。为尽量减少存储,录制开关平时默认关闭,按需开启。业界使用Tcp copy、goreplay等开源方案复制线上流量,以Tcp copy为例,局限性在于是4层流量复制,没法按照域名或接口进行过滤,一是资源浪费,二是运维部署较为复杂;我们当前的方案可以在整个调用过程中的任一环节按需获取流量,更加方便灵活。

3.2 数据污染

参考业界影子存储方案解决测试流量产生的数据污染,利用tracer agent拦截服务各类请求,包含:jdbc、redis、memcaced、kafka、rabbitmq、logback、http、rpc等,将压测流量产生的写请求写入到影子存储中。

a、数据库:数据库的影子存储是拦截数据库连接后替换jdbc connection对象,保证测试流量的sql语句执行在影子db实例中,影子db实例与线上db实例保证在同一数据库集群内,保证压力测试有效;

b、缓存:redis和memcache是拦截连接后改写缓存的key,在原key前加统一压测标识并写入同一缓存集群中,保证压力测试有效,压测产生的缓存过期时间统一改短到1分钟,并开发测试缓存删除脚本,执行后可快速释放缓存空间;
c、日志:部分业务产生的日志可能会被大数据部门采集后制作报表或各类数据统计,目前对logback进行了支持,将测试流量产生的日志写入单独的测试日志文件中。另一种可选方案是在日志内容中增加压测标记,在日志收集处理服务中识别压测标记后丢弃,这样处理出错风险更低,但前提是用相同的日志框架并有统一的日志收集处理服务,目前网易严选团队采用的是这种方案;
d、消息队列:所有应用使kafka和rabbitmq因为暂时业务使用版本不统一,低版本无法透传压测标记,目前方案是遇到压测流量产生的消息统一丢弃不做处理;
e、其它:需要特殊注意的是:java本地内存读写是无法拦截和做影子存储方案的,需要在压测前与业务方确认,做代码侵入式的做响应的修改;


以HikariDataSource数据连接池为例,大概介绍一下具体的数据库的影子逻辑实现方式。

拦截数据库setJdbcUrl、getConnection方法,SetJdbcUrlInterceptor用来构建数据库地址和数据库实例映射,方便后续配置jdbcUrl对应压测数据库地址初始化;JdbcInterceptor用来做压测逻辑拦截。

private void addHikariInterceptor() {this.transformTemplate.transform("com.zaxxer.hikari.HikariConfig", new TransformCallback() {@Overridepublic byte[] doInTransform(Instrumentor instrumentor, ClassLoader classLoader, String className,Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer)throws InstrumentException {InstrumentClass target = instrumentor.getInstrumentClass(classLoader, className, classfileBuffer);InstrumentMethod setJdbcUrlMethod = InstrumentUtils.findMethod(target, "setJdbcUrl",String.class.getName());setJdbcUrlMethod.addInterceptor(SetJdbcUrlInterceptor.class.getName());return target.toBytecode();}});addGetConnectionInterceptor("com.zaxxer.hikari.HikariDataSource", TransformHandler.EMPTY_HANDLER);}
private void addGetConnectionInterceptor(String className, TransformHandler handler) {this.transformTemplate.transform(className, new TransformCallback() {@Overridepublic byte[] doInTransform(Instrumentor instrumentor, ClassLoader classLoader, String className,Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer)throws InstrumentException {InstrumentClass target = instrumentor.getInstrumentClass(classLoader, className, classfileBuffer);handler.handle(target);InstrumentMethod getConnectionMethod = InstrumentUtils.findMethod(target, "getConnection");getConnectionMethod.addInterceptor(JdbcInterceptor.class.getName());return target.toBytecode();}});}

压测LoadTestGetConnectionInterceptor在getConnection方法执行前判断当前流量是否是压测流量,是压测流量则执行压测数据库连接替换,否则继续执行。

@Overridepublic Ret before(Object target, Object[] args) {SofaTracerSpan span = SofaTraceContextHolder.getSofaTraceContext().getCurrentSpan();if (span != null && span.getSofaTracerSpanContext().isLoadTest()) {Object testDb = DataSourceHolder.getInstance().getLoadTestDb(target);if (testDb != null) {DataSource dateSource = (DataSource)testDb;try {return Ret.newInstanceForReturn(dateSource.getConnection());} catch (SQLException e) {if (logger.isWarnEnabled()) {logger.warn("Failed to getConnection. {}", e.getMessage(), e);}}}if(DataSourceHolder.getInstance().isLoadTestDb(target)) {//压测数据源拦截不处理,返回nonereturn Ret.newInstanceForNone();}else {//数据源无配置或者有异常,则返回null,保证压测不影响数据库正常逻辑return Ret.newInstanceForReturn(null);}}return Ret.newInstanceForNone();}

数据库对应压测数据库的配置目前放在配置中心,配置格式为jdbcUrl=压测jdbcUrl,压测影子库除了地址不同外,其它参数复用原数据库。

3.3 压测风控

与集团内部统一监控平台打通,用户可在压测平台设置停止规则,随时监控压测链路各服务监控数据,达到阈值后自动停止压测流量(QPS、错误率等业务指标手工设置,CPU、内存等通用指标默认提供兜底规则)。

停止规则为JSONArray格式,每个规则可单独配置关注用户,大概结构如图:

3.4 压测平台建设

压测平台跟踪压测流程,流量录制、发送、停止规则设置等操作全部界面化,简单设置后自动执行,完成后生成压测报告。平台规范用户操作习惯,为了防范线上压测风险,所有压测必须先在测试环境预演,没问题之后线上小流量验证再开始压测。

4

方案优势

  1. 压测标记和影子存储采用java agent实现,不侵入业务代码

  2. 录制真实线上流量,仿真度高且可以录制足够的请求量,测试同学只需要按需做简单调整即可投入使用,不再需要开发脚本进行数据准备

  3. 根据停止规则自动化停止压测流量,避免影响线上用户

  4. 压测平台可视化操作流程,大幅节省测试团队操作成本

5

应用收益

  1. 降低压测成本,主要体现在以下几方面:

    1. 过往经验,压测开始前需手工梳理被压接口调用链路,全链路追踪项目生成接口调用拓扑图来圈定压测影响的各类服务,方便测试同学关注受影响的集群并设置停止规则;

    2. 录制线上流量用作压测,无需手工构造,压测平台提供host、参数、path、header等流量转换功能;

    3. 自动生成压测报告,给出初步分析结果;

  2. 容量评估
    利用全链路线上压测可以完成两种目标:1.制定目标qps,达标即停止;2.探测qps极限值,集群某类资源达到上限才停止。获取qps极限值数据后,我们可根据需要调整集群内节点数量:极限值远高于预期值,集群节点数可减少;极限值与预期值较为接近则可能无法应对流量突发高峰,需要扩容。如果压测可以常态化,则可以根据业务变化随时调整各集群间资源配置,更好的应对业务需要。

  3. 故障演练
    服务在各环节增加了应对不同场景的降级、流控、熔断功能,在问题发生时是否可以按预期响应,之前这类测试的成本也很高。我们可以利用全链路压测在流量低峰期模拟各环节故障,以达到检验服务稳定性的目标。

6

优化方向

  1. 传媒各服务会逐步接入service mesh,将影子存储等相关压测功能迁移到mesh中,优雅解决跨语言全链路压测(目前功能主要针对java项目),且代码迭代不再需要业务方升级和重新部署;

  2. 开发工具来简化压测前铺底数据同步成本,缩短压测前准备时间;

  3. 压测过程中各类监控项中异常数据的算法识别和监测,不再依赖阈值和人工识别,提高线上问题识别的准确率和召回率;

  4. 增加工单化的压测审批流程,责任落实到具体负责人;

  5. 配合测试团队建立压测结果评分系统并将线上压测常态化,根据压测评分反推各开发团队提高服务质量;

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
美邀60国加入加沙和平委员会

美邀60国加入加沙和平委员会

财联社
2026-01-19 00:55:06
包头包钢工厂爆炸后续:疑似员工曝光群聊,知情人披露几点原因

包头包钢工厂爆炸后续:疑似员工曝光群聊,知情人披露几点原因

奇思妙想草叶君
2026-01-18 21:54:55
日本传统高级料理餐厅的老板娘,即将出道

日本传统高级料理餐厅的老板娘,即将出道

吃瓜党二号头目
2026-01-19 09:06:31
“陈真”饰演者梁小龙去世,前一天还与好友吃火锅,曝最后露面照

“陈真”饰演者梁小龙去世,前一天还与好友吃火锅,曝最后露面照

180视角
2026-01-18 17:12:09
插播一条日本新闻,弥补了国内未见报道的遗憾

插播一条日本新闻,弥补了国内未见报道的遗憾

生活时尚导刊
2026-01-18 01:02:26
“我被人在大脑中植入芯片!”一封离奇举报信,牵出18年前一桩案子

“我被人在大脑中植入芯片!”一封离奇举报信,牵出18年前一桩案子

都市快报橙柿互动
2026-01-18 22:21:08
涉嫌严重违纪违法,正厅级干部周雄被查

涉嫌严重违纪违法,正厅级干部周雄被查

吉刻新闻
2026-01-18 19:30:13
湖北一村弥漫刺鼻农药味,个别菜商竟偷用含毒农药!当地村民称根本不会吃这里的蔬菜

湖北一村弥漫刺鼻农药味,个别菜商竟偷用含毒农药!当地村民称根本不会吃这里的蔬菜

都市快报橙柿互动
2026-01-19 00:11:42
填满数据栏,杨瀚森半场7分30秒2中1得2分1板1助1断1帽0失误

填满数据栏,杨瀚森半场7分30秒2中1得2分1板1助1断1帽0失误

懂球帝
2026-01-19 11:44:02
大米江湖的暗战:那些超市里的“陷阱米”,正在偷走你的钱和健康

大米江湖的暗战:那些超市里的“陷阱米”,正在偷走你的钱和健康

富贵说
2026-01-18 20:36:10
国际乒联终身主席怒了!樊振东打不打奥运会,应该我们自己说了算

国际乒联终身主席怒了!樊振东打不打奥运会,应该我们自己说了算

淡淡稻花香s
2026-01-19 01:05:31
好消息要来了!中小学终于迎来新改革,学生表示:幸福回来了!

好消息要来了!中小学终于迎来新改革,学生表示:幸福回来了!

老特有话说
2026-01-18 15:46:30
太阳X级耀斑爆发 20至21日可能出现较强地磁活动

太阳X级耀斑爆发 20至21日可能出现较强地磁活动

新京报
2026-01-19 11:12:15
南非宣布进入“国家灾难状态”

南非宣布进入“国家灾难状态”

财联社
2026-01-19 01:50:47
塞内加尔一度罢赛 非洲杯决赛绝杀被吹后遭判点球 摩洛哥勺子罚丢

塞内加尔一度罢赛 非洲杯决赛绝杀被吹后遭判点球 摩洛哥勺子罚丢

我爱英超
2026-01-19 06:13:37
立即停止法拍房:拯救中国房地产和亿万中产阶层!

立即停止法拍房:拯救中国房地产和亿万中产阶层!

微评社
2026-01-19 00:13:19
陈冠希一家洛杉矶参加婚礼,留小胡子像赵本山,女儿更像秦舒培!

陈冠希一家洛杉矶参加婚礼,留小胡子像赵本山,女儿更像秦舒培!

明星私服穿搭daily
2026-01-19 07:30:49
李亚鹏没想到,儿童医院陷租金纠纷不到两天,前妻王菲口碑暴跌

李亚鹏没想到,儿童医院陷租金纠纷不到两天,前妻王菲口碑暴跌

一盅情怀
2026-01-18 20:05:54
西贝的问题,已经不是预制菜和贵不贵了

西贝的问题,已经不是预制菜和贵不贵了

钛媒体APP
2026-01-19 08:44:13
牢A回国了,凭一己之力,捅破美国皇帝新衣,崇洋媚外的真的少了

牢A回国了,凭一己之力,捅破美国皇帝新衣,崇洋媚外的真的少了

番茄说史聊
2026-01-18 14:19:38
2026-01-19 11:52:49
网易传媒技术团队
网易传媒技术团队
网易新闻技术团队
40文章数 262关注度
往期回顾 全部

科技要闻

这一仗必须赢!马斯克死磕芯片"9个月一更"

头条要闻

李国庆向李亚鹏捐款100万 晒出银行转账和聊天截图

头条要闻

李国庆向李亚鹏捐款100万 晒出银行转账和聊天截图

体育要闻

21年后,中国男足重返亚洲四强

娱乐要闻

《狮子王》导演在家中去世,终年76岁

财经要闻

GDP增长5%!统计局正在解读

汽车要闻

2026款福特烈马上市 售价29.98-39.98万元

态度原创

手机
家居
时尚
本地
公开课

手机要闻

9月新机发布 小米18系列首发骁龙8 Elite Gen6

家居要闻

隽永之章 清雅无尘

50+女人的穿搭封神技巧来了,抓准这4点,轻松穿出简约高级感

本地新闻

云游内蒙|黄沙与碧波撞色,乌海天生会“混搭”

公开课

李玫瑾:为什么性格比能力更重要?

无障碍浏览 进入关怀版