抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

记录一次生产环境中Tomcat 启动服务报错的排查修复过程,经验总结。

背景

运行许久的两台服务器上部署的Toncat 服务因为功能优化,需要重启,但是重启后B服务器上的Toncat 无论如何总是启动失败。

排查过程

根据Catalina.out 日志的报错记录进行逐步排查问题。

问题1

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'multipartResolver': Failed to introspect bean class [org.springframework.web.multipart.commons.CommonsMultipartResolver] for lookup method metadata: could not find class that it depends on; nested exception is java.lang.NoClassDefFoundError: org/apache/commons/fileupload/FileItemFactory.                                                              

458957e3861e20af5aabeba5bbfbbdf6_MD5

  • Spring Bean 初始化失败:错误栈信息中显示了 BeanCreationException,表示 Spring 在初始化 multipartResolver Bean 时遇到问题。

  • 缺少依赖类:最根本的原因是 java.lang.NoClassDefFoundError,提示缺少 org/apache/commons/fileupload/FileItemFactory 类。这个类属于 Apache Commons FileUpload 库,CommonsMultipartResolver 依赖它来处理文件上传。

  • 检查依赖:确认项目的依赖中包含 commons-fileupload。如果项目使用 Maven 或 Gradle,确保 commons-fileupload 依赖已经正确配置。例如,在 Maven 中可以添加以下依赖:
1
2
3
4
5
<dependency>                                                                                                                                                  
<groupId>commons-fileupload</groupId> 
<artifactId>commons-fileupload</artifactId> 
<version>1.4</version>  
</dependency> 

问题2

org.springframework.amqp.rabbit.connection.CachingConnectionFactory - Could not get host name, using ‘localhost’ as default value 
java.net.UnknownHostException: CustomServer: CustomServer: unknown error 
at java.net.InetAddress.getLocalHost(InetAddress.java:1505) 

d4acc8d542e8b42adc1bb2d86e093005_MD5

  • 错误日志显示 java.net.UnknownHostException: CustomServer: unknown error。这是因为生产环境中未能正确解析主机名 CustomServer

  • 解决方法:确保 CustomServer 主机名在生产环境的 /etc/hosts 文件中被正确配置,或者在 DNS 服务器中解析。如果无法设置此主机名,可以尝试将 AMQP 连接的 hostname 明确设为 localhost 或目标 IP 地址,而不是依赖默认主机名。

因为之前这台Tomcat 部署的服务都正常,我记得之前有同事更改了主机名,但是这个过程中服务是没有重启,所以没有问题。这次重启Tomcat 就把这个问题暴露出来了。
[[编程日志/images/生产环境Tomcat 部署服务报错问题排查/bc96f46c85c7db0300757a7660a3f7ea_MD5.png|Open: Clip_2024-11-06_13-37-43.png]]
bc96f46c85c7db0300757a7660a3f7ea_MD5
因此,增加了hosts 配置,这个问题就解决了。

问题3

registered the JDBC driver [com.alibaba.druid.proxy.DruidDriver] but failed to unregister it when the web application was stopped. To prevent a memory leak, the JDBC Driver has been forcibly unregistered.

224c478c69ee1045af64a45b694e7fdf_MD5

这个问题,一直以为是JDBC 连接没有释放,但是从网上查看资料,说是Tomcat 误报的信息,不用搭理,一直排查了好久,期间我把另一台A 服务器上的Tomcat 整体拷贝过来启动,也是同样的问题,后来怀疑是B 服务器上的JDK 问题,但不确定,查阅Google 有篇博客厄舍屋下|解决:the JDBC Driver has been forcibly unregistered给出了提示,随查看日志,发现问题确定是 JDK 的问题。

ccb82ebb1c8eb4414c7b02d112efc174_MD5
localhost_access_log.2024-11-05.txt 文件报错内容如下

org.apache.catalina.core.StandardContext.filterStart Exception starting filter [javamelody]
java.lang.UnsatisfiedLinkError: /apps/infra/jdk1.8.0_77/jre/lib/amd64/libawt_xawt.so: libXrender.so.1: cannot open shared object file: No such file or directory
at java.lang.ClassLoader$NativeLibrary.load(Native Method)
at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1941)
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1824)
at java.lang.Runtime.load0(Runtime.java:809)
at java.lang.System.load(System.java:1086)

ccb3cafdd4150866a0fe4d0aa0f4be68_MD5

这个错误信息显示在启动 Java 应用程序时,缺少了一个本地库 libXrender.so.1。这个库是 X11 的一部分,通常用于图形显示。在某些 Java 应用程序(如使用 Java AWT 或 Swing 的应用程序)中,需要这个库来进行图形渲染。

使用如下命令对比两台服务器,,查库文件是否存在

1
ldconfig -p | grep libXrender

相比B服务器,A服务有如下结果

1ddb21a3e2320efb5f07b7c88834ac21_MD5

要解决这个问题,可以按照以下步骤操作:

1. 安装 libXrender

1
2
3
4
5
6
# Ubuntu
sudo apt-get update
sudo apt-get install libxrender1

# centos
sudo yum install libXrender

2. 自定义Tomcat 的JDK

但是因为是生产环境,不确定安装后有没有影响,因此我选择了方式2,将A 服务器的JDK 拷贝到B 服务器,然后在Tomcat配置文件中指定JDK版本运行程序。

修改Tomcat的配置文件setclasspath.shcatalina.sh,添加java_homejre_home的环境变量。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# tomcat bin 目录
cd /server/apache-tomcat-8.5.34/bin

vim setclasspath.sh

# jdk、jre 位置
# 在文件最开始位置添加如下配置即可
export JAVA_HOME=/usr/local/java1.8.0_181
export JRE_HOME=$JAVA_HOME/jre

vim catalina.sh

# 在文件最开始位置添加如下配置即可
export JAVA_HOME=/usr/local/java1.8.0_181
export JRE_HOME=$JAVA_HOME/jre

修改完,重启Tomcat 问题解决,发现Tomcat 使用的是我们自定义的JDK。

b75e6ca8857b5cda3917bd2c3c4512e3_MD5

参考文章

评论