我在部署时遇到了一个奇怪的问题 SpringBootApplication
Package 为 war
到tomcat服务器。
有时,tomcat服务器无法识别应用程序启动(或者更准确地说,需要很长时间),尽管应用程序已成功启动。-如果我说成功,我的意思是应用程序可以执行备份作业,例如。 cron
作业,访问其数据库,并通过 SOAP
.
tomcat服务器无法识别启动时的问题是应用程序的 REST
端点不可访问,更糟糕的是,如果在将应用程序放入webapps文件夹时重新启动tomcat服务器,整个tomcat服务器将被冻结。
老实说,我不知道可能是什么问题,甚至不知道从哪里开始寻找。
不知怎么的,我怀疑这个习俗 ThreadPoolTaskScheduler
(见下文)触发此问题。但即使我将池大小设置为1,也会出现此问题。
从显示启动时间的日志文件中提取:
正常启动:
应用程序日志文件: Started CrewAlertApplication in 17.358 seconds (JVM running for 58.215)
catalina.out: Deployment of web application archive [/srv/prod/cpappp/tomcat/webapps/crew-alert##1.2.1.war] has finished in [21.691] ms
缓慢启动:
应用程序日志文件: Started CrewAlertApplication in 25.161 seconds (JVM running for 75.633)
catalina.out: Deployment of web application archive [/srv/prod/cpappp/tomcat/webapps/crew-alert##1.2.1.war] has finished in [1.056.389] ms
以下是一些有关环境的信息:
tomcat(在一个机器上运行) VMWare
机器,有4个芯)
Server Version: Apache Tomcat/9.0.43
Server built: Jan 28 2021 20:25:45 UTC
Server version number: 9.0.43.0
OS Name: Linux
OS Version: 5.8.0-0.bpo.2-amd64
Architektur: amd64
Java Home: /srv/jdk-11.0.9+11
JVM Version: 11.0.9+11
JVM Hersteller: Eclipse OpenJ9
应用程序本身基于:
springboot:2.0.5
java :11
如上所述,我们使用自定义 ThreadPoolTaskScheduler
```
@Bean
public ThreadPoolTaskScheduler threadPoolTaskScheduler() {
ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler();
threadPoolTaskScheduler.setPoolSize(5);
threadPoolTaskScheduler.setThreadNamePrefix("CrewAlertThreadPool");
threadPoolTaskScheduler.setRemoveOnCancelPolicy(true);
return threadPoolTaskScheduler;
}
下图显示了tomcat管理器。启动tomcat,然后部署应用程序(部署在tomcat上的其他应用程序都已成功启动)。
![](https://i.stack.imgur.com/NhKLf.png)
一段时间后,tomcat管理器显示应用程序已成功启动
![](https://i.stack.imgur.com/lLlvG.png)
更新1:
正如@andywilkinson指出的,问题发生在我的 `@EventListener` 方法调用 `JpaRepository` 方法
List findByScheduledTimeBetween(ZonedDateTime from, ZonedDateTime to)
它被“翻译”成
Hibernate: select scheduledn0_.id as id1_6_, scheduledn0_.alert_id as alert_id3_6_, scheduledn0_.scheduled_time as scheduled_time2_6_
from scheduled_notification scheduledn0_
where scheduledn0_.scheduled_time between ? and ?
以下是该实体的摘录:
@Entity(name = "SCHEDULED_NOTIFICATION")
@Table(indexes = { @Index(name = "IDX_SCHED_NOTIF_SCHEDTIME", columnList = "SCHEDULED_TIME") })
public class ScheduledNotification extends AbstractId implements Comparable {
@ManyToOne(optional = false)
@JoinColumn(name = "ALERT_ID", nullable = false)
private Alert alert;
@Column(name = "SCHEDULED_TIME", nullable = false, columnDefinition = "TIMESTAMP")
@Convert(converter = ZonedDateTimeConverterUtc.class)
private ZonedDateTime scheduledTime;
@OneToMany(mappedBy = "scheduledNotification", cascade = ALL, orphanRemoval = true, fetch = EAGER)
private Set<Leg> legs;
...
这个电话实际上需要将近18分钟。这有点令人惊讶,因为这个表从未包含超过100个条目(在本例中返回了3个结果)。
2021-07-14 12:53:34.506 INFO [] --- [Catalina-utility-3] c.lalacomp.alert.CrewAlertApplication : Started CrewAlertApplication in 26.577 seconds (JVM running for 108237.294)
2021-07-14 12:53:34.509 INFO [] --- [Catalina-utility-3] c.l.a.scheduler.NotificationExecutor : ApplicationReadyEvent received.
2021-07-14 12:53:34.528 DEBUG [] --- [Catalina-utility-3] c.l.a.s.ScheduledNotificationServiceImpl : findImmediate() - Looking up schedules between: 2021-07-14T10:38:34Z[UTC] and 2021-07-14T11:08:34Z[UTC]
2021-07-14 12:53:34.572 INFO [] --- [Catalina-utility-3] o.h.h.i.QueryTranslatorFactoryInitiator : HHH000397: Using ASTQueryTranslatorFactory
...
2021-07-14 13:11:27.637 TRACE [] --- [Catalina-utility-3] c.l.a.s.ScheduledNotificationServiceImpl : We've found: ...
2021-07-14 13:11:27.639 INFO [] --- [Catalina-utility-3] c.l.a.scheduler.NotificationExecutor : Adding 3 new ScheduledNotifications at startup.
...
等等,如果时间戳不匹配,应用程序将被识别为正在运行:
14-Jul-2021 13:11:27.662 INFORMATION [Catalina-utility-3] org.apache.catalina.startup.HostConfig.deployWAR Deployment of web application archive [/srv/prod/cpappp/tomcat/webapps/crew-alert##1.2.2.war] has finished in [1.103.405] ms
所以现在我必须弄清楚,为什么要花这么长时间?因为针对数据库(其他表)的其他查询正常执行。
更新2:
如果我运行类似的 `sql` 语句直接显示在控制台上,运行时是绝对正常的。
select * from scheduled_notification sn
join leg l on sn.id = l.SCHEDULED_NOTIFICATION_ID
join alert a on sn.ALERT_ID = a.id
where scheduled_time between SYSTIMESTAMP and SYSTIMESTAMP + 2 /24;
Fetched 30 rows in 0.015 secs
我还想知道为什么 `Hibernate` 上面的语句(更新1)不包括“连接关系”。
暂无答案!
目前还没有任何答案,快来回答吧!