同样的代码,开发环境生效,测试环境不生效,记一次问题排查过程和原因分析

我的公众号:IT周瑜

今天有同事遇到这样一个问题,有一个新增接口在本地和开发环境的swagger上都能看到,但是在测试环境的swagger上却看不到,并且确定测试环境是最新的代码,并重新构建和部署了。

按照同事的描述,首先我得确定是不是swagger的问题,我先检查我们平台组是否有对swagger做了改造,发现确实做了改造,但都是很久以前的提交记录了,最近并没有改动。

那有什么办法确定到底是不是swagger的问题呢?问题场景是测试环境swagger上没有看到接口信息,那这个接口到底生效没有呢?调用一下不就知道了,所以我调了一下,404了,所以并不是swagger的问题,而是这个接口本身就没有生效。

那这个接口为什么在测试环境不生效,本地和开发环境却生效呢?为了确认到底是不是代码问题,我把测试环境对应分支的代码在本地跑了起来,发现接口和swagger都是生效的,所以测试分支代码是没有问题的。

那是测试环境有问题?可是要排查环境问题更加毫无头绪,而且我们测试环境是K8S集群,问了运维同事,最近也没有做什么改动。

测试分支代码没有问题,测试环境也假设没有问题,那还有哪里可能会有问题呢?

Jar包!代码没有问题,但是打出来的Jar包到底对不对呢?于是我把测试环境的Jar下载下来,解压,找到问题接口所属Controller类的class文件,用IDEA反编译这个类,发现没错啊!是最新的代码啊!有那个接口啊!怎么明明有Controller,有接口,但接口却没有生效啊?

代码没问题,Jar包似乎也没问题,难道真是环境问题?可是环境问题也不太可能只针对某一个接口,其他接口都不受影响呀。

Jar包的静态代码确实没问题,那运行时的代码呢?这是有可能的,比如某个agent正好把这个接口的代码改掉了?带着这个猜想,我用arthas查看这个类,让我发现了一个惊天大秘密!怎么arthas查看到的代码和Jar包里的代码不一样!怎么arthas查到的类中没有那个接口?也就是说应用运行时的Controller类并不是前面看到的Jar包中的类。

明明类名包名都一样,怎么内容不一样?再仔细看看arthas,发现运行时的这个Controller类所属的Jar包是另外一个Jar包!

这里得解释一下我们微服务工程的目录结构,包含一个server模块和一个或多个core模块,现在问题微服务中就有两个core模块,我分别把它们叫做core1和core2。

回到前面的场景,相当于,在代码中,问题接口Controller类是在core1模块的,core2模块没有这个Controller,但是用arthas查看时,却发现这个Controller在core2,这是为什么?

紧接着,我查看Git提交记录,发现这个Controller本来是在core2的,是最近移动到了core1,并新增了这个出现问题的接口,是移动,并不是复制,所以现有的代码中core2是没有这个Controller类的,那为什么arthas查看到这个Controller在core2?

我接着解压测试环境中core2的jar包,发现这个jar包中确实有这个Controller,也就是当前微服务用到的两个core中都有这个Controller,包名类名都一样,但是内容不一样,core2中是旧版本,core1中是新版本,好了,现在问题的表面原因就是core1中新版本Controller没有生效,而旧版本的Controller生效了,这是因为它们两个类名一样,相当于beanName冲突了,所以只有其中一个生效,而此时旧版本胜出了,它生效了,从而导致新增的接口没有生效。

可是为什么明明现在core2的代码中没有这个Controller了,它对应的Jar中却还有呢?

真相呼之欲出,打包出问题了,是不是jenkons拉的分支被人改了?导致拉到的代码不对,导致打出来的包不对?检查jenkins,发现分支是对的,我直接下载解压jenkins页面上的打包结果,发现确实打出来的包是有问题的,那问题到底在哪?

正当没有头绪,盯着Jenkins的流水线配置发呆时,看到了mvn命令,不对劲!!!不对劲!!!,怎么只有install,没有clean参数啊,再对照开发环境,发现开发环境是有clean参数的,所以开发环境没有问题,测试环境没有clean,所以测试环境有问题!!!!!

到此,问题的根本原因找到了,因为打包时没有clean,由于core2只前有这个Controller,所以target目录下还有它编译出来的class文件,尽管后面把代码从core2移到了core1,但是target目录并没有发生变化,又因为没有clean,所以打出来的core2包中还有历史版本的Controller字节码,从而最终运行时覆盖了core1中的新版本Controller,从而导致新接口没有生效,从而导致swagger页面中没有看到新接口!

这就是解决问题的快乐!

我是IT周瑜,实践出真知,关注我,我将分享更多的实战干货!

相关推荐
luoluoal3 分钟前
java项目之基于Spring Boot智能无人仓库管理源码(springboot+vue)
java·vue.js·spring boot
ChinaRainbowSea8 分钟前
十三,Spring Boot 中注入 Servlet,Filter,Listener
java·spring boot·spring·servlet·web
小游鱼KF11 分钟前
Spring学习前置知识
java·学习·spring
扎克begod15 分钟前
JAVA并发编程系列(9)CyclicBarrier循环屏障原理分析
java·开发语言·python
青灯文案116 分钟前
SpringBoot 项目统一 API 响应结果封装示例
java·spring boot·后端
我就是程序猿26 分钟前
tomcat的配置
java·tomcat
阳光阿盖尔32 分钟前
EasyExcel的基本使用——Java导入Excel数据
java·开发语言·excel
二十雨辰34 分钟前
[苍穹外卖]-12Apache POI入门与实战
java·spring boot·mybatis
程序员皮皮林34 分钟前
开源PDF工具 Apache PDFBox 认识及使用(知识点+案例)
java·pdf·开源·apache
蔚一35 分钟前
Java设计模式—面向对象设计原则(三) -----> 依赖倒转原则DIP(完整详解,附有代码+案例)
java·开发语言·设计模式·intellij-idea·依赖倒置原则