阅读 1059

Dubbo 生产者缺少的jar,为什么错在了消费者?

记一次有意思的dubbo服务调用java.lang.NoClassDefFoundError问题排查,尽管现在还不清除具体原理是什么,但是问题已经解决。

背景

  1. 这是一个新的项目,重新搭建开发环境,以及运维部署docker环境,jdk采用1.8。
  2. 项目启动正常,没有任何错误日志,日志级别调成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.

  1. 是不是打包出现了问题? 辛苦运维大哥将服务器上打包的项目拿下来,将服务器端服务kill,在本地启动重新注册到zk上,本地启动消费者(因为网络限制策略,开发部署环境不能连接本机服务),服务并没有出现异常,而是正常提供服务!!!
  2. 运维开始怀疑是不是自己新建环境有问题了?? 将项目打的包拷贝至宿主机使用java -jar project.jar运行,通过dubbo-admin观察,发现服务注册成功,测试调用发现服务也是正常!!!
  3. 唯一有问题的就是将服务部署在新的docker环境了。。。 通过以上2种排查,那剩下的唯一有问题只能是服务+环境
    1. 检查docker环境的jdk环境、classpath环境,均发现正常没有问题。
    2. 检查服务与消费者的网络,发现也是正常没有问题。
    3. 谁能告诉我,这个到底是怎么啦???
  4. 网络搜索到的解决方案
    1. 缺少jar 这个通过检查maven依赖,打包之后的lib发现jar包确实不少
    2. javassist版本不对 有网友说是因为javassist的版本不对导致,通过消费者lib包发现,项目中确实存在两个版本的javassist,如下图,请运维将低版本的删除,然后启动,发现服务依旧是不行~~~~ 能试的,我都试了,为什么你要这么折磨我这个小菜逼,ಥ_ಥ
      image.png
  5. 在服务中写个JUnit测试类,通过dubbo引用服务端的服务吧~ 在本地写了一个JUnit测试类,通过<dubbo:reference id="${serverId}" interface="${serviceInterfaceClass}" version="${version}" group="${group}" url="dubbo://${ip}:${port}"/>直连提供者,终于出现了同样的错误~,😂,尽管还是不知道怎么解决,但是出现了总比不出现要好,对于bug就是这个样子的。。。
  6. 检查服务提供者的jar依赖 发现服务提供者的maven依赖并没有
<dependency>
    <groupId>commons-lang</groupId>
    <artifactId>commons-lang</artifactId>
    <version>2.6</version>
</dependency>
复制代码

会不会就是这个错误呢?有可能的哦!尽管不是很确定,但还是要搞一搞~ 将这个依赖添加上,重新打包部署,好期待奇迹出现哦~ 运行JUnit测试类,What?! 果然奇迹出现了,竟然没有错误了!服务呢?是否也正常了?Yes! 服务也正常了!!!

总结

导致这个错误的原因是因为服务提供者没有提供commons-lang:2.6的依赖包,导致了运行时出错,但是这个异常确抛在了消费端,让人一时懵逼以为真的是因为消费者出现了错误! 通过异常堆栈发现,使用StringUtils工具类的是 cat-dubbo-monitor ,项目使用cat监控dubbo服务状态。 至于为什么这个错误会出现在消费者端,而不是生产者端,具体原因还不知道,还请只到的大牛能够给指点一下,非常感谢!!

文章分类
后端
文章标签