数据库Mock方案设计

举报
chenhuaping 发表于 2020/11/03 10:13:02 2020/11/03
【摘要】 一、需求分析1.背景华为导流测试平台通过对线上流量回放到被测环境中,利用线上真实流量进行充分测试,保证业务系统稳定上线。但是业务在导流测试过程中现网数据库往往难以同步到测试环境,导致现网数据无法正常回放,测试价值降低。由此提出回放过程中对数据库进行mock,以保证回放过程正常进行。2.方案分析数据库Mock方案大致分为以下3种: 3.方案对比 方案实现原理难点优点缺点当前研究进展①...

一、需求分析

1.背景

华为导流测试平台通过对线上流量回放到被测环境中,利用线上真实流量进行充分测试,保证业务系统稳定上线。但是业务在导流测试过程中现网数据库往往难以同步到测试环境,导致现网数据无法正常回放,测试价值降低。由此提出回放过程中对数据库进行mock,以保证回放过程正常进行。

2.方案分析

数据库Mock方案大致分为以下3种:

 

 image.png

 

 

 

3.方案对比

 

方案

实现原理

难点

优点

缺点

当前研究进展

数据库中间件接收的是字节码序列化数据,要实现Mock,就必须从Service发送给数据库的查询语句字节码中解析出select语句,并且再从数据库返回给Service的字节码中解析出结果数据再进行Mock数据的字节码替换。

已实现从Service发给数据库的字节码序列中解出了select语句,但是从数据库返回的结果字节码序列非常复杂,解析存在一定的困难,需要对mysql数据库底层序列化协议非常清楚才能实现解析算法,该方案在持续研究中。

数据库中间件是一个独立的TCP服务进程,只需要在一台机器上启动该进程,然后将要Mock服务的数据库连接指向该TCP进程的IP端口即可,不需要被测服务代码、服务器做任何改动

功能可以实现,但方案最难最花时间,需要研究mysql协议

该方案已通过Vertex实现了一个TCP服务,并解析出了select语句,mysql结果数据解析替换Mock数据需要在对mysql序列化协议熟悉之后才能进一步开发,持续研究中。

该方案和LuBan,OneAPM等监控工具原理一样,采用基于javaagent的javassist无侵入字节码动态修改技术和class反射技术将mysql驱动的原始类字节码进行修改,实现在sql语句执行后并在ResultSet真实数据结果返回替换成Mock数据返回。

需要熟悉javassist字节码动态修改技术,java反射技术,以及熟悉mysql驱动的源码逻辑,要知道在源码中什么地方替换返回的ResultSet对象中的结果集数据。

该方案生成一个dbmockagent.jar,在启动要Mock的服务时只需增加-javaagent参数指向该jar包即可,不需要被Mock的服务修改代码。

该方案适配MySQL数据库,无需考虑使用何种数据库访问框架(MyBatis等)。

相对第一种方案对业务服务器部署有一定的要求,需将dbmockagent.jar部署在所有想要Mock服务的机器上,再修改启动命令指向该jar包。

1、已开发出第一版并上线用户生产环境使用:

(1)mock数据预置redis。

(2)mockAgent改造,回放时从redis拉取数据。

2、后续计划:

(1)开发mock server,用户配置mockAgent后,自动向mockServer注册;mockServer可以实现对mockAgent管理。

(2)并行回放,mockAgent   V2.0开发,开发是否可以通过luban通信获取唯一id映射关系。

和第种方案类似,不同的是,不是修改mysql驱动字节码,而是修改mybatis返回结果的字节码。

和第种方案类似,需要了解mybatis的源码。

该方案和第种方案一样生成一个dbmockagent.jar,在启动要Mock的服务时增加-javaagent参数指向该jar包即可,不需要被Mock的服务修改代码。

该方案只适配于MyBatis框架,和具体的数据库无关。

 

同第种部署方案。

该方案只适配MyBatis框架,如果访问框架换成其它比如Hibernate就需要重新开发。

已实现

 

二、方案2MySQL驱动字节码修改增强方案详细说明

1.方案设计

字节码增强:通过分析MySQL数据库驱动源码可知,获取数据库返回的ResultSet结果集的方法在com.mysql.jdbc.PreparedStatement类中的executeQuery方法,和执行完execute方法之后再调用getResultSet方法两种方式,所以我们需要对executeQuery和execute两个方法进行字节码修改增强。即在这两个方法执行完成之后,注入以下代码:获取Mock文件中的行列数据,转成MySQL需要的字节码对象,再设置到ResultSet实例化对象中替换原数据库的真实数据即可。

圆角矩形标注: 数据库mock插件工程  image.png

 

Mock数据设计和解析:一次请求链路中,比如有下面三次查询语句,并且存在相同sql执行多次并且返回结果不同的情况,那么我们在回放请求过程时,就得按顺序去依次取得每条sql执行的结果数据,而且能做到可对链路中其中一些sql结果进行mock,不mock的sql返回数据库的真实数据。

 image.png

 

2.使用说明

1.在需要数据库Mock功能的第三方服务的启动命令中增加-javaagent参数指向该jar包,方式如下:

  java -javaagent:D:/dbmockagent.jar -jar  **.jar

2.参数设置:       

 (1)可设置dbmock.file参数指定Mock数据文件,不设置时默认为C:/dbmock.data。目前只实现了从文件中读取mock数据,可扩展从接口等其它地方获取Mock数据。         

   java -javaagent:D:/dbmockagent.jar     -Ddbmock.file="D:/dbmock.data" –jar **.jar         

(2)可设置dbmock.port参数指定重载Mock数据接口调用的端口,可不设置,默认为8888: 

   java -javaagent:D:/dbmockagent.jar     -Ddbmock.file="D:/dbmock.data" -Ddbmock.port=8088 -jar  **.jar


3.方案测试

3.1 使用MySQL驱动直连数据库

image.png

 

3.1.1 不使用插件

         image.png

    

3.1.2 使用插件

         image.png

        再次运行上面的代码,执行结果如下,输出了DBMock相关的log信息,返回的数据正好为上面mock的数据,并且两次sql语句虽然相同,但是返回的结果数据是按照mock文件里的顺序返回的。

         image.png

3.2 SpringBoot工程中通过MyBatis连接数据库

       image.png

 image.png


3.2.1 不使用插件

 image.png




 

image.png

3.2.2 使用插件

 image.png

 

image.png

 

 

3.3 Mock数据更新

 image.png


 

 image.png

image.png

 


【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。