记一次tomcat部署排错经历(jar冲突)
前景概要
- 通过docker在三台机器上部署了tomcat
- 现有一个应用要部署在这三个tomcat中
- 三台机器中A,B都顺利部署成功,C的服务始终启动失败
通过以上可知,由于我们使用了docker部署,使用的相同镜像,tomcat和jdk的版本一致是可以保证的,那么为什么会出现其中一台服务器启动不起来的情况呢。下面把排查过程说一下,顺便提供一个部署出错后找出问题的思路:
解决过程
1.定位错误
首先可先通过部署结果来看可以得知tomcat启动是成功的,但是webapps下的服务没有部署成功,通过查看tomcat输出日志catalina可以发现对应的部署错误提示
18-Feb-2022 08:32:36.989 INFO [localhost-startStop-1]org.apache.catalina.startup.HostConfig.deployDirectory Deploying web application directory [/usr/local/tomcat/webapps/OSPFlowCenter]
18-Feb-2022 08:32:46.836 SEVERE [localhost-startStop-1] org.apache.catalina.core.StandardContext.startInternal One or more Filters failed to start. Full details will be found in the appropriate container log file
18-Feb-2022 08:32:46.836 SEVERE [localhost-startStop-1] org.apache.catalina.core.StandardContext.startInternal Context [/OSPFlowCenter] startup failed due to previous errors
可以看到上面3行日志分别显示了
- 服务正在部署
- 有一到多个filters启动失败,具体的日志需要去容器日志查看
- 由于前面的错误,服务启动失败
一般通过第1,3行日志我们可以确定问题日志在哪里,通过第2行我们可以得知和filter有关,但是具体的问题还需要我们去容器日志里查看,这里一般是输出到了localhost.log里面。但是为了方便定位,我们可以在启动失败的服务的classes路径下添加logging.properties文件,来将日志输出到Catalina中
org.apache.catalina.core.ContainerBase.[Catalina].level=INFO
org.apache.catalina.core.ContainerBase.[Catalina].handlers=java.util.logging.ConsoleHandler
然后再次重启tomcat观察输出日志:
21-Feb-2022 09:38:48.593 SEVERE [localhost-startStop-1] org.apache.catalina.core.StandardContext.filterStart Exception starting filter [FilterService]
java.lang.NoSuchMethodError: org.jdom.Element.addContent(Lorg/jdom/Element;)Lorg/jdom/Element;
这下一目了然了,错误发生在FilterService中存在NoSuchMethodError的错误,字面意思找不到类中对应的方法,一般是由于包冲突导致的,同一个类路径在多个包存在,tomcat加载了没有使用方法的类所以抛出了异常,可是这就很奇怪了,3台机器明明代码完全一样,为什么其他服务器没有问题呢。
2.解决办法
这里通过查阅资料得到一个结论:
tomcat在加载同一目录下的jar的顺序是无序的
结合我们遇到的问题,我想tomcat加载jar的时候根据机器信息做了一些排序,导致了能启动的服务器一直可以,而不能启动的服务器就jar包的加载顺序一直错误,导致了jar冲突。具体怎么加载的估计需要去看tomcat源码,但是很多时候我们知道结果就可以了,没必要太追究过程,当然如果有时间去了解肯定更好。
解决冲突的办法,tomcat提供了在context.xml可以配置优先加载哪些类
<Resources>
<PreResources className="org.apache.catalina.webresources.FileResourceSet"
base="${catalina.base}/webapps/你的项目名称/WEB-INF/lib/提到前面来的冲突jar包名.jar"
webAppMount="/WEB-INF/lib/提到前面来的冲突jar包名.jar" />
</Resources>

浙公网安备 33010602011771号