skywalking源码分析第二十三篇一扩展篇:全链路压测_skywalking 标签透传-程序员宅基地

技术标签: java  全链路压测  skywalking  skywalking6.x源码分析  

前言

全链路压测时一项系统性工程,包含数据工厂,影子环境,压测脚本,数据偏移,压测平台,链路路由等等
本文重点介绍其中一环,业务应用代码增强

原理

  • 红色表示压测流量
  • 黑色表示业务流量
  • 红色的流量由压测平台[比如jmeter压测集群]发起
  • http发送请求需要在请求头设置一个标记,此标记可以被skywalking识别,后skywalking在TracerContext中标记该请求为压测请求[俗称流量染色]
  • 同时该标记能够从应用一透传到应用二透传到应用三
  • 在写入db时,根据流量染色情况进行路由,业务流量写入正常db,压测流量写入影子库
  • redis,es等也是同理,实现上存储层如db都是同一台物理节点,逻辑存储位置不同,比如同一个mysql,其业务db是biz_db,则影子库是shadow_biz_db
  • mq影子流量和业务流量共用topic
    在这里插入图片描述

基于skywalking的压测实现

本文重点介绍基于skywalking的影子传播机制与存储如何落入影子库表

数据容器改造

  • 除去skywalking源码后,新增压测标记字段

public class TraceSegment {
    
    /**
     * 压测标:表明当前链路是业务流量还是压测流量
     */
    private  boolean pressureTest ;
}
public class ContextCarrier implements Serializable {
    
  /**
     * 全链路压测标志
     */
    private boolean pressureTest;
}

public class ContextSnapshot {
    
  
    /**
     * 全链路压测标志
     */
    private boolean pressureTest;
 
}

对Segment的序列化反序列化改造

public class TracingContext implements AbstractTracerContext {
    
    @Override
    public void inject(ContextCarrier carrier) {
    
        ...... 删除skywalking源码
        跨进程级别的压测标传递
        carrier.setPressureTest(segment.isPressureTest());
        ...... 删除skywalking源码
    }

     
    @Override
    public void extract(ContextCarrier carrier) {
    
        ...... 删除skywalking源码
        跨进程级别的压测标志注入
        this.segment.setPressureTest(carrier.isPressureTest());
    }

    @Override
    public ContextSnapshot capture() {
    
        ...... 删除skywalking源码
        跨线程级别的压测标志注入
        snapshot.setPressureTest(segment.isPressureTest());
        return snapshot;
    } 

    @Override
    public void continued(ContextSnapshot snapshot) {
    
        ...... 删除skywalking源码
        this.segment.setPressureTest(snapshot.isPressureTest());
    }
}

说明

  • 基于上述方案后Segment如果有pressureTest压测标记
  • 则跨进程时先序列化成ContextCarrier,进入下一进程在转为Segment时,能够完成pressureTest压测标记跨进程传递
  • ContextSnapshot同理完成跨线程传递

染色一压测流量识别

  • http请求时,获取其请求头pressureTest标记,给Segment进行染色
  • 标志当前流量是压测流量还是业务流量
  • 注意该请求头只有压测流量携带,业务流量不可以出现,否则造成干扰
public class TomcatInvokeInterceptor implements InstanceMethodsAroundInterceptor {
    
    @Override public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments,
        Class<?>[] argumentsTypes, MethodInterceptResult result) throws Throwable {
    
        ...... 删除skywalking源码
        压测流量识别 染色
        String pressureTest = request.getHeader("pressureTest");
        if(!StringUtil.isEmpty(pressureTest)){
    
            Boolean isPressureTest = Boolean.FALSE;
            try {
    
                isPressureTest = Boolean.valueOf(pressureTest);
            } catch (Exception e) {
    

            }
            TracingContext abstractTracerContext = (TracingContext) ContextManager.get();
            TraceSegment segment = abstractTracerContext.getSegment();
            segment.setPressureTest(isPressureTest);
        }
    }
}

小结

  • 通过对skywalking的改造和tomcat流量的改造
  • 我们的流量具有了识别染色能力和传递压测标能力
  • 则当流量进入http和dubbo以及mq到达jdbc时,压测流量的pressureTest始终是true,业务流量始终是false

核心一影子路由

  • 以下为mysql8.x的jdbc插件影子路由实现
  • 当我们发现是压测流量时,修改业务库为压测库,在库名前增强"shadow_’
  • 此时,业务流量写入db.影子流量写入shadow_db
  • 影子库需要和业务库在同一台db实例上,影子库需提前创建,表与业务库相同
public class StatementCreateInterceptor implements InstanceConstructorInterceptor {
    
    @Override
    public void onConstruct(EnhancedInstance objInst, Object[] allArguments) {
    
        TracingContext abstractTracerContext = (TracingContext) ContextManager.get();
        boolean pressureTest = abstractTracerContext.getSegment().isPressureTest();
        if(pressureTest) {
    
            if (objInst instanceof ClientPreparedStatement) {
    
                第三个参数
                allArguments[2] = "shadow_" + allArguments[2];
                ((ClientPreparedStatement) objInst).setCurrentCatalog((String) allArguments[2]);
            }
            if (objInst instanceof StatementImpl) {
    
                第二个参数
                allArguments[1] = "shadow_" + allArguments[1];
                ((StatementImpl) objInst).setCurrentCatalog((String) allArguments[1]);

            }
        }
    }
}

总结

  • 综上,我们完成了流量染色,链路携带染色标记,基于染色标记完成影子库写入,从而实现了全链路压测中最重要的一环,业务应用字节码增强改造
  • 需要注意,实际环境要覆盖所有的技术组件,比如redis,es等等
  • 还需要考虑类似定时任务等各种业务场景的处理,安全问题等等
  • 本文重点在于引路,如读者有兴趣可以自行专研其他组件压测实现[如有疑问可留言]
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_35529969/article/details/123412991

智能推荐

Flask、Django、Tornado三大框架的对比_tornado flask di-程序员宅基地

文章浏览阅读3.9k次。前言之前面试的时候我提到过自己有Flask、Django、Tornado框架的使用经验,于是面试官很自然就问到了这三大框架的区别、各自的特点这样的问题。回答了几次总觉得自己回答得不是太好,有些点没有回答到,亦或是逻辑有点混乱,于是想要归纳总结一下。框架的特点FlaskFlask诞生于2010年,是Armin ronacher用Python语言基于Werkzeug工具箱编写的轻量级Web开发..._tornado flask di

简单实现接口自动化测试(基于python)_接口自动化测试怎么写-程序员宅基地

文章浏览阅读9.3k次,点赞21次,收藏192次。一、简介本文从一个简单的登录接口测试入手,一步步调整优化接口调用姿势,然后简单讨论了一下接口测试框架的要点,最后介绍了一下我们目前正在使用的接口测试框架pithy。期望读者可以通过本文对接口自动化测试有一个大致的了解。二、引言为什么要做接口自动化测试?在当前互联网产品迭代频繁的背景下,回归测试的时间越来越少,很难在每个迭代都对所有功能做完整回归。但接口自动化测试因其实现简单、维护成本低,容易提高覆盖率等特点,越来越受重视。为什么要自己写框架呢?使用requets + unitt_接口自动化测试怎么写

JavaScript大数运算】实现高精度计算的JavaScript算法_js 用什么类型运算大数据和精度要求高的数据-程序员宅基地

文章浏览阅读104次。总结起来,JavaScript中的大数运算是一个挑战,但通过使用字符串表示大数并手动实现算术运算,或者使用专门的JavaScript库,我们可以实现高精度的数值计算。这为处理更大范围的数值提供了可能,使我们能够在JavaScript中进行各种复杂的数值计算。无论是手动实现算法还是使用现有的库,都能帮助我们在JavaScript中实现高精度计算,处理更大范围的数值。在上述代码中,我们将大数表示为字符串,逐位相加,并处理进位。这样,我们可以避免JavaScript的数值限制,从而实现了高精度的加法运算。_js 用什么类型运算大数据和精度要求高的数据

bbp公式求圆周率、python_【并行计算】六种方法计算圆周率-程序员宅基地

文章浏览阅读2.7k次。计算π的历史圆周率π可能是科学界内外最广为人知的自然常数了。早在公元5世纪时,南朝宋数学家祖冲之用割圆法将圆周率计算到小数点后7位数字。大约同一时间,印度的数学家也将圆周率计算到了小数点后5位。历史上首个π精确无穷级数公式(即莱布尼茨公式)直到约1000年后才由印度数学家发现。20世纪以来,随着计算机技术的快速发展,π的精度也在极速提高。截至2019年,π的十进制精度已高达1013位。虽然几乎所有..._chudnovsky算法

苹果快捷键怎么调出来_原来还有这么好用的CAD快捷键,文末附赠快捷键鼠标垫!留言走起...-程序员宅基地

文章浏览阅读141次。▼相信大家都看过一些大神做CAD,那个图纸真是做的又快又好看!当然大神们其实也就基础好一点,把快捷键记得过目不忘,所以接下来小编就教大家一个非常Skr的方法,保证你对这些快捷键过目不忘,文末更有免费鼠标垫领取,千万别错过哦!这个方法就是建立我们的思维导图了,文字看了可能会忘记,但是通过导图的方式,就会变成思维图形,更加符合我们大脑的思考习惯,就可以牢牢记住这些快捷键啦:▼例如我们看到下面的就是绘图..._苹果cad快捷键

MATLAB的GUI 程序设计_制作一个曲面光照效果的演示界面,如图所示,三个弹出式菜单分别用于选择曲面形式、-程序员宅基地

文章浏览阅读7.2k次,点赞7次,收藏60次。第七章 MATLAB的GUI 程序设计Chapter 8: Design of MATLAB of GUI programGUI(Graphical User Interfaces):由各种图形对象组成的用户界面,在这种用户界面下,用户的命令和对程序的控制是通过“选择”各种图形对象来实现的。目前90%以上的应用程序和软件都是在GUI下运行的。MATLAB有两种GUI用户界面控件的创建方式,基于命令行的方式用程序来制作和基于GUI的方式制作。这里主要介绍基于GUI的方式。MATLAB 的._制作一个曲面光照效果的演示界面,如图所示,三个弹出式菜单分别用于选择曲面形式、

随便推点

【中级软考】软件设计-考试介绍_软件设计师 以考代评 考完就是中级职称-程序员宅基地

文章浏览阅读457次。软件设计中级软考基本内容,通过一下几点进行介绍:1、软考好处2、软件设计证书模版3、流程4、考点分布5、考试形式_软件设计师 以考代评 考完就是中级职称

linux7配网卡,CentOS 7 配置网卡-程序员宅基地

文章浏览阅读60次。VM安装了一个Linux系统CentOS,但是安装后发现ping www.baidu.com 报错 。查了一下发现需要配置网卡。1.首先需要进入目录 /etc/sysconfig/network-scripts这里我的centos的 iso版本是:CentOS-7-x86_64-DVD-1708.iso。进入目录之后可以看到有个ifcfg-ens33的文件。我们需要对这个文件做些修改。2.vi i..._wsl2 centos7 网卡配置

Android 通过蓝牙采集音频_android 蓝牙麦克风采集mic音频 无声-程序员宅基地

文章浏览阅读8.8k次。通过蓝牙的麦克风进行录音MainActivity.javapackage com.example.bluetothrecord;import android.app.Activity;import android.content.BroadcastReceiver;import android.content.Context;import android.content.In_android 蓝牙麦克风采集mic音频 无声

Accessing static Data and Functions in Legacy C_setyearanddayofyear-程序员宅基地

文章浏览阅读1.1k次。http://www.renaissancesoftware.net/blog/archives/430http://www.renaissancesoftware.net/blog/archives/450It’s a new year; last year was a leap year; so the quadrennial reports of leap y_setyearanddayofyear

vue把字符串分割成等长的若干字符串,根据特定字符分割字符串_vue 分割字符串-程序员宅基地

文章浏览阅读1.6w次,点赞2次,收藏20次。把字符串分割成等长的若干字符串,根据特定字符分割字符串_vue 分割字符串

朴素贝叶斯分类器的例子_朴素贝叶斯分类器 例子-程序员宅基地

文章浏览阅读1.1k次。一、病人分类的例子让我从一个例子开始讲起,你会看到贝叶斯分类器很好懂,一点都不难。某个医院早上收了六个门诊病人,如下表。  症状  职业   疾病  打喷嚏 护士   感冒   打喷嚏 农夫   过敏   头痛  建筑工人 脑震荡   头痛  建筑工人 感冒   打喷嚏 教师   感冒   头痛  教师   脑震荡现在又来了第七个病人,是一个打喷嚏的建筑工人。请问他患上感冒的概率有多大?根据贝叶斯..._朴素贝叶斯分类器 例子

推荐文章

热门文章

相关标签