记一次有意思的dubbo服务调用java.lang.NoClassDefFoundError问题排查,尽管现在还不清除具体原理是什么,但是问题已经解决。
背景
- 这是一个新的项目,重新搭建开发环境,以及运维部署docker环境,jdk采用1.8。
- 项目启动正常,没有任何错误日志,日志级别调成
DEBUG
级别也未发现问题。
异常出现
具体异常
cause: java.lang.NoClassDefFoundError: org/apache/commons/lang/StringUtils
java.lang.NoClassDefFoundError: org/apache/commons/lang/StringUtils
at net.dubboclub.catmonitor.CatTransaction.createProviderCross(CatTransaction.java:187)
at net.dubboclub.catmonitor.CatTransaction.invoke(CatTransaction.java:55)
at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:69)
at com.alibaba.dubbo.rpc.filter.ContextFilter.invoke(ContextFilter.java:61)
at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:69)
at com.alibaba.dubbo.rpc.filter.GenericFilter.invoke(GenericFilter.java:132)
at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:69)
at com.alibaba.dubbo.rpc.filter.ClassLoaderFilter.invoke(ClassLoaderFilter.java:38)
at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:69)
at com.alibaba.dubbo.rpc.filter.EchoFilter.invoke(EchoFilter.java:38)
at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:69)
at com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol$1.reply(DubboProtocol.java:98)
at com.alibaba.dubbo.remoting.exchange.support.header.HeaderExchangeHandler.handleRequest(HeaderExchangeHandler.java:98)
at com.alibaba.dubbo.remoting.exchange.support.header.HeaderExchangeHandler.received(HeaderExchangeHandler.java:170)
at com.alibaba.dubbo.remoting.transport.DecodeHandler.received(DecodeHandler.java:52)
at com.alibaba.dubbo.remoting.transport.dispatcher.ChannelEventRunnable.run(ChannelEventRunnable.java:81)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
这个异常抛出在dubbo服务调用方,也就是消费者端,起初以为是消费者端缺少commons-lang:2.6.jar
导致,排查发现这个jar包确实是存在的!!!但是为什么会报这个异常呢?
本地调试
通过本地idea启动生产者与消费者,采用直连的方式dubbo://localhost:20881
,发现服务竟然能够正常提供服务!!!What's up?
运维改变部署环境
本地启动能够正常提供服务,那是不是运维新建的环境有问题呢?It's possible.
- 是不是打包出现了问题?
辛苦运维大哥将服务器上打包的项目拿下来,将服务器端服务kill,在本地启动重新注册到zk上,本地启动消费者(因为网络限制策略,开发部署环境不能连接本机服务),服务并没有出现异常,而是正常提供服务!!! - 运维开始怀疑是不是自己新建环境有问题了??
将项目打的包拷贝至宿主机使用java -jar project.jar
运行,通过dubbo-admin
观察,发现服务注册成功,测试调用发现服务也是正常!!! - 唯一有问题的就是将服务部署在新的docker环境了。。。
通过以上2种排查,那剩下的唯一有问题只能是服务+环境了- 检查docker环境的jdk环境、classpath环境,均发现正常没有问题。
- 检查服务与消费者的网络,发现也是正常没有问题。
- 谁能告诉我,这个到底是怎么啦???
- 网络搜索到的解决方案
- 缺少jar
这个通过检查maven依赖,打包之后的lib发现jar包确实不少 - javassist版本不对
有网友说是因为javassist
的版本不对导致,通过消费者lib包发现,项目中确实存在两个版本的javassist
,如下图,请运维将低版本的删除,然后启动,发现服务依旧是不行~~~~
能试的,我都试了,为什么你要这么折磨我这个小菜逼,ಥ_ಥ
- 缺少jar
- 在服务中写个JUnit测试类,通过dubbo引用服务端的服务吧~
在本地写了一个JUnit测试类,通过
直连提供者,终于出现了同样的错误~,,尽管还是不知道怎么解决,但是出现了总比不出现要好,对于bug就是这个样子的。。。 - 检查服务提供者的jar依赖
发现服务提供者的maven依赖并没有
commons-lang
commons-lang
2.6
会不会就是这个错误呢?有可能的哦!尽管不是很确定,但还是要搞一搞~
将这个依赖添加上,重新打包部署,好期待奇迹出现哦~
运行JUnit测试类,What?! 果然奇迹出现了,竟然没有错误了!服务呢?是否也正常了?Yes! 服务也正常了!!!
总结
导致这个错误的原因是因为服务提供者没有提供commons-lang:2.6
的依赖包,导致了运行时出错,但是这个异常确抛在了消费端,让人一时懵逼以为真的是因为消费者出现了错误!
通过异常堆栈发现,使用StringUtils
工具类的是 cat-dubbo-monitor ,项目使用cat监控dubbo服务状态。
至于为什么这个错误会出现在消费者端,而不是生产者端,具体原因还不知道,还请只到的大牛能够给指点一下,非常感谢!!