与AI结对编程,一路同行:一款数据库稳定性保障插件之AI设计开发结对编程实践之路

0 阅读7分钟

背景

在日常工作中,有时会遇到一些突发流量,突发流量虽然持续时间短,但形成的流量洪峰不容小觑,对于系统来说也是较大的冲击。应用、数据库等方面都会有明显的跳点,持续时间越长,风险越大。

突发流量的来源,有时是来自JSF、RESTful等远程服务调用,也可能是MQ事件消息,也可能是系统自身的一些定时任务,异步任务等。如果定时任务、异步任务的量大,应用、数据库都会有较大的负载压力。

对于应用而言,直观的指标例如CPU利用率飚高,系统RT时间变长,TP99升高,客户有卡顿感。对于数据库来说,QPS变高,CPU飙升,慢SQL增多,活跃连接升高等现象。











虽然可以从限流、摘流、扩容、隔离等手段对应用保护效果比较好,但有时应用内部已经存在的大量流量,还是会流向数据库,对于数据库的保护效果不一定收到很好的效果。









对于数据库而言,直接操作数据库的三板斧,就是KILL、主从切换、重启。有时如果流量大的SQL持续产生,KILL也KILL不完,KILL后还会有有新的进入,主从切换后,新的主库也会被很快打起来,同样,重启效果也不有限。

如果不是上线变更造成的流量突增,就是某个业务量图上涨起来了,或者大量的数据量,产生了大量的任务,是一种正常的业务增长,部署回滚不能解决问题。很典型的,报表的大量导出就是一个短时间流量突增的案例。



突增的业务量,产生的突增流量,这种场景下,能不能通过一些应用与数据库的交互层面上做一些防御工作呢?

在这个场景下,尝试探索一个保护数据库的方式。下面,我会从设计、开发、测试等方面,借助joycode进行结对编程研发方式进行工作,提升研发效率。



详细设计

prompt

我要写一款MyBatis插件,有以下几方面诉求,请先规划设计,输出设计文档,图文结合,越详细越好:
1、拦截SQL,解析出SQL指纹
2、定义接口,从中基于SQL指纹查询配置的阈值,该接口的默认实现是通过Spring配置文件加载该SQL指纹的阈值,还可以有其他实现,交给该插件的接入方来实现,通过 ServiceLoader SPI方式进行加载具体实现
3、如果被拦截到的SQL,在上述指纹配置中存在,并且单位时间内累积的SQL指纹出现次数超过阈值,则触发对应的处理策略,具体策略在下面展示解释,其中单位时间内累积的SQL指纹出现次数可以在容器内存中累积
4、处理策略有三种,分别如下:
AbortPolicy 策略:抛出 RuntimeException 异常,中断执行
IgnorePolicy 策略:静默丢弃该请求,不抛出异常
DelayPolicy 策略:sleep一段时间,避免执行过快使数据库压力过大
5、请注意,第4步中的执行策略中,结合设置的比例执行策略,比如rate设置的是2/3,策略模式是AbortPolicy 策略,则将2/3的流量抛出RuntimeException 异常,中断执行,其他策略类似处理。



























在上面,我把核心的思路讲给joycode,joycode基本可以理解我的设计意图,可以进行设计拆解和细节规划。产出的设计效果挑一些重点内容预览如下:



























设计文档中除了我给出的规划意图,还包含joycode所展开的具体实现细节,包含类的规划、限流具体算法、SQL指纹的生成逻辑、SPI的接口定义、限流保护策略的定义和实现等。整体看来设计方向没问题,按此实现落地。



编码开发

prompt

请基于刚才的设计文档,在 com.jd.sword.mybatis.plugin.protector.SQLBasedDatabaseProtector 类中进行插件开发



























基于上面的设计文档,joycode可以快速的进行编码开发,各种类的设计和开发还是不错的,基本框架和内容基本上都是由joycode开发实现。二方包和三方包的代码引用可以自动生成,不过美中不足的是maven坐标依赖并没有为我添加,代码飘红,我手动添加进去解决。



打磨优化

有了上面的出版工程代码还不够,我需要进行review检查,对于其中的不合理地方进行检查审阅,发现优化改进的点,提出来与joycode交流优化,详细如下。



代码风格调整

prompt

刚才的插件请基于 com.jd.sword.mybatis.plugin.sql.SQLMarkingInterceptor 的风格进行代码调整









在代码风格上,我希望与其他现有插件的风格保持一致,经过上面的调整,风格基本上可以拉齐。

除了代码风格,代码注释风格我也希望与项目工程保持一致,下面对个别注释进行调整。



prompt

在注释中,@date 要精确到时分秒,格式是 yyyy-MM-dd HH:mm:ss,请基于此调整刚才所生成代码文件中的@date时间。
请基于此,对刚才所生成的插件代码文件注释进行调整。
代码中缺少必要注释,请添加注释信息

















简化代码复杂度

目前生成的代码复杂度较高,我希望可以简化一下代码实现,提升代码可读性。

prompt

com.jd.sword.mybatis.plugin.protector 包下的整个插件实现,看起来略微复杂,请简化实现,提高可读性









去掉多余的代码

prompt

com.jd.sword.mybatis.plugin.protector.SQLBasedDatabaseProtector 这个类是不是多余的,如果多余,请删掉这个类















package分包优化

prompt

在 com.jd.sword.mybatis.plugin.protector 包下,目前是很多类平铺的,需要分一下子包,比如按照策略类、Exception类、计数类相关分包,并把相关的类移入新包中,com.jd.sword.mybatis.plugin.protector.SQLBasedDatabaseProtectorPlugin 的位置不用动









包整理后









在分包优化这块,因为拆分了很多子包,类的package需要调整,引用import也需要调整,joycde也识别到了工作的复杂性,尝试写批量脚本处理,因为来回处理了一会,比较费时,我感觉人工处理更快,选择停止任务,人工调整包。



性能优化

prompt

com.jd.sword.mybatis.plugin.protector.counter.SlidingWindowCounter.Window 起什么作用,可以简化吗?









prompt

com.jd.sword.mybatis.plugin.protector.counter.SlidingWindowCounter#record 这个里面每次都会 new Window,这种实现会使内存升高,请分析优化















无用代码处理

prompt

com.jd.sword.mybatis.plugin.protector.counter.OptimizedSlidingWindowCounter 这个刚优化后的类,看上去并没有被引用,请检查









单元测试

请为 com.jd.sword.mybatis.plugin.protector.SQLBasedDatabaseProtectorPlugin 写单测















单测可以正常编写,个别方法涉及checked exception的处理,需要人工参与下。单测类的分包没有严格按代码中的所在包来划分,不过这些只是风格问题,问题不大。





更新文档

设计期初做了一些设计和规划文档,在开发中做了一些优化调整,与原有设计文档中已有出入,现在开发工作基本结束,对原先的文档进行更新完善。



prompt

请基于目前的最新实现,修改之前的文档
sword-mybatis-plugins/DESIGN_DOCUMENT.md
sword-mybatis-plugins/README.md
sword-mybatis-plugins/SIMPLIFICATION_GUIDE.md









prompt

sword/sword-mybatis-plugins/README.md 中的maven坐标 <artifactId>mybatis-sql-limit-plugin</artifactId> 不对,应该是 <artifactId>sword-mybatis-plugins</artifactId>, 版本 version 也不对









接入运用

maven坐标







插件配置







阈值配置







与joycode结对编程,在设计、开发、测试等方面已经大大提升了研发效率,体感还是不错的。