太长不看(TLNR)的直接看总结就好

现象

前几天服务(commonservice)上线的时分,疯狂报NPE,看了下代码似乎是一个不可能抛反常的当地,尤其是在本地运转正常的情况下就更显怪异了。找了下银泉帮助定位到问题,日志的切面连接点有点问题,可是仍是不清楚触发原因,并且也不能解说为啥本地正常。折腾了半天IDEA,发现原来是引进的jar版别不正确,其实本地也是有问题的。这种问题似乎是IDEA一向尿性了,仅仅在这里忽然呈现又浪费了几个小时。忍不了了,遂晋级IDEA到最新版别,目前来看,感觉良好,pom文件有变动的时分会有一个Sync窗口,可以直观地了解jar包导入情况,也没有再呈现版别过错的问题(当然,这本来就不是必现的问题)。废话少说,定位到了问题现象之后,接下来就要找到它的本源了。

本源

关于没有啥思路的问题,只能经过排除法就溯源了。首先找到问题引进的时间,经过测验了几轮不同版别的服务代码,承认了问题引进的代码提交记载。然后看下提交记载,大部分是业务代码,仅仅晋级了一个jar包,可是这是个soa主动生成的api啊,能有啥问题?绞尽脑汁也百思不得其解。仍是先承认一下问题本源吧,于是在另一个服务(vendor)也引进了这个jar包,这个服务更怪异,直接起不来了。。所以基本上可以承认这个jar包有问题。但这也正是最令人费解的当地,由于这便是个刚刚从soa后台生成下载的还热乎着的api jar包。vendor发动之后报了一些错,可以经过一些“奇淫巧技”处理,银泉就根据报错处理了问题然后发动了,但不承认还有没有问题(我感觉大概率是有的),并且也并没有解说为啥这个包“有毒”。
由于要上堡垒测验,暂时先把这个jar回退了,涉及到的新功能也注释掉了,好在影响的不多,先推动需求要紧。有空的时分,再来看看这个问题。 吃完晚饭之后,测验都完毕了,这个问题仍是要处理的。先晋级jar包看看问题还在不。。md,还在。要不,比照下发动日志?尽管看起来差不多,但也许有些许差异呢?运用beyond compare比照日志后发现,正常的版别会多一条日志

[03:16:46.109] [INFO] [main] – Bean ‘org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration’ of type [class org.springframework.transaction.annotation.ProxyTransactionManagementConfigurationEnhancerBySpringCGLIBEnhancerBySpringCGLIB51de14ac] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)

有端倪了,再去vendor承认一下,也是同样的差异。可是这个类正常的和反常的服务都有,这他么怎么看。不过,既然这个类都有,那是不是有其他类(或者jar)的差异,由于这个类是个auto-configure相关的类,在有某些类或者jar的情况下会主动加载。阐明依靠是有不同的(之前没往这上边想是由于一切的api依靠都是一样的,按道理不应该,并且这个jar的老版别依靠很少(其实不然))。那就再比照一下运转时加载的jar包吧。写了段测验代码

    public static void main(String[] args) throws IOException {
       File file7 = new File("D:\\Users\\wang.wei\\Documents\\task\\8月\\71.txt");
       File file10 = new File("D:\\Users\\wang.wei\\Documents\\task\\8月\\101.txt");
       Pattern p = Pattern.compile("-classpath \"(.*)\"");
       String libs7 = Files.readFirstLine(file7, Charsets.UTF_8);
       Matcher m7 = p.matcher(libs7);
       m7.find();
       libs7 = m7.group(1);
       Set<String> set7 = Sets.newHashSet(Splitter.on(";").omitEmptyStrings().trimResults().split(libs7));
       String libs10 = Files.readFirstLine(file10, Charsets.UTF_8);
       Matcher m10 = p.matcher(libs10);
       m10.find();
       libs10 = m10.group(1);
       Set<String> set10 = Sets.newHashSet(Splitter.on(";").omitEmptyStrings().trimResults().split(libs10));
       Collection c710 = CollectionUtils.subtract(set7, set10);
       Collection c107 = CollectionUtils.subtract(set10, set7);
       System.out.println(c710);
       System.out.println(c107);
   }

成果如下:

  1. 正常版别-反常版别
[D:\Users\wang.wei\.m2\repository\org\springframework\boot\spring-boot-starter-jdbc\1.4.3.RELEASE\spring-boot-starter-jdbc-1.4.3.RELEASE.jar, D:\Users\wang.wei\.m2\repository\org\springframework\boot\spring-boot-starter-aop\1.4.3.RELEASE\spring-boot-starter-aop-1.4.3.RELEASE.jar, D:\Users\wang.wei\.m2\repository\org\springframework\spring-jdbc\4.3.4.RELEASE\spring-jdbc-4.3.4.RELEASE.jar, D:\Users\wang.wei\.m2\repository\com\ctrip\train\ordercentre\outboundcall_service_client\1.0.7\outboundcall_service_client-1.0.7.jar]

2. 反常版别-正常版别

[D:\Users\wang.wei\.m2\repository\com\ctrip\train\ordercentre\outboundcall_service_client\1.0.10\outboundcall_service_client-1.0.10.jar]

一望而知了,我他么走了多少弯路。。。

正常版别比反常版别多了几个jar,而这几个jar的差异是由于outboundcall_service_client的版别不一样,仔细观察了下outboundcall_service_client-1.0.7.jar的pom文件,发现它竟然有个parent,而这个parent里引进了许多依靠,其中就包括上述的差异jar包(不主张在父pom中直接引进依靠,而应该声明为dependencyManagement)

一次api升级引发的“血案”

一次api升级引发的“血案”
接下来的事就简单了,在service模块补上spring-boot-starter-aop依靠,在dal模块补上spring-boot-starter-jdbc依靠,妥了!

总结

由于现在绝大部分项目都依靠许多公共组件,而公共组件又依靠许多第三方jar包,导致咱们起一个项目简直不用显式声明依靠,一朝一夕关于项目所真实需求依靠的jar包现已没什么概念了,横竖只需服务起来了就好,大多数情况下确实服务能起来就能确保不会出啥问题,但这次的“血案”告知咱们,仍是需求严厉对待jar包依靠这个问题。当然,这次的问题主要是晋级的api jar包的老版别在父pom里强制声明许多依靠,而晋级之后这些依靠没了,导致咱们缺失了一些依靠。在父pom应尽量少声明依靠,需求统一管理版别的应该声明为dependencyManagement,正是由于他们依靠了 之前不必要的jar包,才使咱们没有在第一时间发现问题。

我已将tieyouflightcommon依靠的outboundcall_service_client晋级为1.0.10,强烈主张各位依靠此版别发动下服务,这个版别没有关于spring-boot-starter-aopspring-boot-starter-jdbc的依靠,所以如果之前的服务是经过依靠tieyouflightcommon依靠outboundcall_service_client从而取得这两个jar包的依靠的话,主张显式在自己的项目声明,究竟这两个jar包并非需求强制依靠(spring-boot相关的依靠只在spring-boot服务才需求,而tieyouflightcommon是适用于一切spring应用的)。

outboundcall_service_client是推送相关的api,这次晋级是由于旧的版别不支持跳转落地页,没想到晋级出事来了。。记载一下希望后续其他同学需求晋级此api的时分不要踩到相同的坑了。