升级Liferay时如何禁用或重定向Java 8线程转储日志?
解决Liferay升级时线程转储日志干扰的方案
我之前在帮团队把Liferay 6.1升级到7.0的时候,也碰到过一模一样的问题——16GB级别的PostgreSQL数据库升级时,线程长时间等待数据库操作完成,导致大量线程转储日志刷屏,完全干扰了正常升级日志的查看。分享几个我亲测有效的解决思路:
1. 调整JVM参数关闭自动线程转储
线程转储很多时候是JVM检测到线程长时间阻塞后自动触发的,你可以通过修改升级工具的JVM启动参数来禁用这个机制:
- 如果你用的是HotSpot/OpenJDK,确保启动参数中没有设置
-XX:BlockedThreadDetectionTimeout(或者将其设为0,表示禁用阻塞线程检测); - 移除任何会触发线程转储的参数,比如
-XX:OnError="jstack %p"这类配置; - 如果是OOM相关的堆转储干扰,添加
-XX:-HeapDumpOnOutOfMemoryError关闭自动堆转储(不过你的场景更偏向线程阻塞,这个可能不是重点)。
2. 重定向线程转储日志到单独文件
如果不能完全禁用线程转储,至少可以把它和主升级日志分开,避免干扰。Liferay的升级工具一般用Log4j或SLF4J做日志管理,你可以修改日志配置文件:
- 找到升级工具目录下的
log4j.properties(或logback.xml),添加以下配置(以Log4j为例):
这样所有线程转储日志都会单独存在# 专门存放线程转储的Appender log4j.appender.threaddump=org.apache.log4j.RollingFileAppender log4j.appender.threaddump.File=${liferay.home}/logs/upgrade-thread-dumps.log log4j.appender.threaddump.MaxFileSize=20MB log4j.appender.threaddump.MaxBackupIndex=10 log4j.appender.threaddump.layout=org.apache.log4j.PatternLayout log4j.appender.threaddump.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p [%t] %c - %m%n # 将线程转储相关日志定向到单独文件,关闭日志继承 log4j.logger.com.liferay.portal.kernel.util.ThreadDump=INFO, threaddump log4j.additivity.com.liferay.portal.kernel.util.ThreadDump=falseupgrade-thread-dumps.log里,主升级日志就清爽了。
3. 从根源减少线程阻塞(治本之策)
线程转储的本质是数据库操作太慢导致线程长时间等待,优化数据库性能能从根本上减少这类日志的生成:
- 提前清理数据库:删除Liferay 6.1里的废弃数据——比如垃圾回收站里的内容、过期的用户会话、旧的文档草稿、无人使用的站点数据等,能大幅缩小数据库体积,加快升级速度;
- 优化PostgreSQL配置:调大
shared_buffers(建议设为物理内存的1/4)、work_mem(提升排序/哈希操作的内存分配)、maintenance_work_mem参数,提升数据库处理大任务的能力; - 添加必要索引:针对升级过程中频繁读写的表(比如
User_、Group_、JournalArticle、Layout等),检查是否缺失索引,添加上对应的索引能显著减少查询耗时; - 分批执行升级任务:部分Liferay升级工具支持分批处理数据,你可以在升级配置里设置分批大小,避免一次性处理大量数据导致长时间阻塞。
4. 检查升级工具的内置触发逻辑
有些时候,线程转储是Liferay升级工具自己触发的(比如内置的线程监控逻辑),你可以:
- 查看升级工具的配置文件(比如
portal-upgrade.properties),寻找是否有控制线程转储的开关,比如upgrade.thread.dump.enabled=false这类配置,设置为关闭; - 如果是自定义的升级脚本,检查脚本里是否有调用
jstack命令的代码,直接注释掉相关逻辑。
内容的提问来源于stack exchange,提问作者Maksym Bodnar
相关产品推荐
相关产品推荐

