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

智能推荐

STM32 串口通信介绍及cubemx配置_Nie_Hen的博客-程序员资料

学习理解STM32的串口通信,中断以及I2C的使用。应用:使用中断和串口通通信获取按键值发送出来并显示到数码管上。使用I2C 将获取到的按键值保存到内存中。串口通信计算机的CPU与外部设备之间的信息交换,以及计算机与计算机之间的信息交换过程称为通信。并行通信数据字节的各位同时传送的通信方式。并行通信的优点是数据传送速度快,缺点是占用的传输线条数多,适用于近距离通信。串行通信(Se...

android 背景图缩放,解决android:background背景图片被拉伸问题_weixin_39639600的博客-程序员资料

ImageView中XML属性src和background的区别:background会根据ImageView组件给定的长宽进行拉伸,而src就存放的是原图的大小,不会进行拉伸。src是图片内容(前景),bg是背景,可以同时使用。此外:scaleType只对src起作用;bg可设置透明度,比如在ImageButton中就可以用android:scaleType控制图片的缩放方式如上所述,backg...

qt用odbc连接mysql_【原创】Qt 使用ODBC driver 连接SQL Server_午餐时间到了的博客-程序员资料

最近在做数据库的课程设计。第一个需要解决的问题是使用什么工具来实现这个系统。经过一番资料查找,决定使用SQL Server Express 2012作为服务器,使用Qt作为编写客户端程序语言。问题是client如何连接SQL Server? 下面是我的解决方法。1.开启windows上的SQL Server 的ODBC驱动ODBC 是一个调用级接口,它使得应用程序得以访问任何具有 ODBC 驱动程...

翻页时钟代码大公开_lovefan的博客-程序员资料_翻页钟开源代码

不少朋友向我要翻页时钟的代码,现在贴给大家。代码水平有限,见谅。看不明白的可以问我:)js// miniprogram/pages/flipClock/jsconst moment = require('../../../utils/moment-with-locales.min.js');const Lunar = require('../../../utils/lunar.js');var startX, endX;var moveFlag = true; // 判断执行滑动事件.

JAVA切换不了FTP服务器目录_解决linux下ftp指定访问目录无法修改的问题_豪睿刘爱上楼楼梯的博客-程序员资料

他的系统是CentOS,是RH派系的。我把vsftpd安装配置好了,以为大功告成,但客户端访问提示如下错误:500 OOPS: cannot change directory:/home/ftp原因是他的CentOS系统安装了SELinux,因为默认下是没有开启FTP的支持,所以访问时都被阻止了。//查看SELinux设置# getsebool -a|grep ftpftpd_disable_tr...

.NET实现网络爬虫_hyunbar的博客-程序员资料_.net 爬虫

爬虫的特征和运行方式User-Agent:主要用来将我们的爬虫伪装成浏览器。Cookie:主要用来保存爬虫的登录状态。连接数:主要用来限制单台机器与服务端的连接数量。代理IP:主要用来伪装请求地址,提高单机并发数量。爬虫工作的方式可以归纳为两种:深度优先、广度优先。深度优先就是一个连接一个连接的向内爬,处理完成后再换一下一个连接,这种方式对于我们来说缺点很明显。 广度优先...

随便推点

机器学习中用到的概率知识_机器学习必备的概率统计基础_weixin_40009393的博客-程序员资料

现如今,计算机科学、人工智能、数据科学已成为技术发展的主要推动力。无论是要翻阅这些领域的文章,还是要参与相关任务,你马上就会遇到一些拦路虎:想过滤垃圾邮件,不具备概率论中的贝叶斯思维恐怕不行;想试着进行一段语音识别,则必须要理解随机过程中的隐马尔科夫模型;想通过观察到的样本推断出某类对象的总体特征,估计理论和大数定理的思想必须建立;在统计推断过程中,要理解广泛采用的近似采样方法,蒙特卡洛方法以及马...

oracle使用sqlplus远程连接ASM实例的方式_kadwf123的博客-程序员资料_oracle连接asm实例

sqlplus sys/[email protected]:1521/+ASM as sysasm至于配置成tns,照着普通oracle连接方式配置就行,此处每次不记得命令格式,写在这边记录一下;最后的+ASM指的是服务名,不是实例名,写成实例名连不上。...

一文了解人脸识别:从实现方法到应用场景都讲明白了_大数据v的博客-程序员资料

导读:在本文中,我们将会接触到一个既熟悉又陌生的概念——人脸识别。之所以熟悉,是因为人脸识别技术在我们日常生活中应用极其广泛,例如火车站刷脸验票进站、手机人脸解锁等;之所...

twisted builtins.TypeError: __init__() missing 1 required positional argument: 'dbpool'_锅前带刀小笼包的博客-程序员资料

学习爬虫异步插入,遇到问题Unhandled error in Deferred:2020-05-10 14:41:59 [twisted] CRITICAL: Unhandled error in Deferred:...builtins.TypeError: __init__() missing 1 required positional argument: 'dbpool'发现是函数名写错, 应该是from_settings ,结果写成了from_setting,低级错误,记录一下pip

Paxos、Raft、ZAB算法_知知之之的博客-程序员资料_paxos raft zab

Paxos算法是Leslie Lamport在1990年提出的一种基于消息传递的一致性算法。基于Paxos协议的数据同步与传统主备方式最大的区别在于:Paxos只需超过半数的副本在线且相互通信正常,就可以保证服务的持续可用,且数据不丢失。Paxos将系统中的角色分为提议者 (Proposer),决策者 (Acceptor),和最终决策学习者 (Learner):在多副本状态机中,每个副本同时具有Proposer、Acceptor、Learner三种角色。Paxos算法通过一个决议分为两个阶段(Learn阶段

Bibtex格式类型_小王同学w的博客-程序员资料_bibtex类型

出于保留资源和查找方便,转载自https://blog.csdn.net/kmsj0x00/article/details/85318057类型简介必需关键字可省略关键字@article期刊或杂志上的一篇文章。author, title, journal, year.volume, number, pages, month, [email protected]有确定出版社的书籍。author或editor, title, publisher, year.volume或number, series, address, e

推荐文章

热门文章

相关标签