簡體   English   中英

Tomcat需要很長時間才能識別spring-boot應用程序的啟動

[英]Tomcat requires long time to recognizes the start of spring-boot application

將打包為warSpringBootApplication部署到 tomcat 服務器時,我遇到了一個奇怪的問題。

有時,即使應用程序啟動成功,tomcat 服務器也無法識別(或更准確地說,需要很長時間)應用程序啟動。 - 如果我說成功,我的意思是應用程序可以執行備份作業,例如cron作業,訪問其數據庫並通過SOAP連接到第三方服務。

當 tomcat 服務器無法識別啟動時,問題是應用程序的REST端點無法訪問,更糟糕的是,如果我在應用程序位於 webapps 文件夾中時重新啟動 tomcat 服務器,整個 tomcat 服務器將被凍結。

老實說,我不知道可能是什么問題,甚至不知道從哪里開始尋找。

我懷疑,不知何故,自定義ThreadPoolTaskScheduler (見下文)觸發了這個問題。 但即使我將池大小設置為 1,也會出現此問題。

從顯示啟動時間的日志文件中提取:

  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
  2. 慢啟動:
    • 應用程序日志文件: 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

該應用程序本身基於:

  • 彈簧引導: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上的其他應用全部啟動成功)。 在此處輸入圖像描述

一段時間后,tomcat 管理器顯示應用程序已成功啟動在此處輸入圖像描述


更新 1:

正如@AndyWilkinson 指出的那樣,問題出現在我調用@EventListener方法的JpaRepository方法中

List<ScheduledNotification> 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<ScheduledNotification> {
    @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)不包括“連接關系”。

正如@AndyWilkinson 指出的那樣,問題出在ApplicationReadyEvent中。 在連接到此事件的方法中,我從數據庫中獲取數據,由於一些昂貴的關系,這花費了很長時間。

我更新了實體並簡化了其中的一些關系。 現在該方法按預期執行。

非常感謝,所有的功勞都歸功於 Andy!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM