Spring Boot JAR包部署AWS EC2 Ubuntu后启动即触发extShutdownHook自动停止问题
EC2环境下Spring Boot应用启动后自动停止故障排查
项目基本信息
- 技术栈构成:Spring Boot + AWS 服务组件(EC2、S3、RDS(MariaDB))
- 部署方式:在Ubuntu系统的EC2实例上,通过命令
java -jar *.jar运行打包完成的Spring Boot JAR包
故障表现
通过JAR包启动应用后,服务可以走完全部启动流程,但启动完成后立刻自动退出。最初排查方向聚焦于聊天功能的WebSocket配置,已做如下调整但故障未解决:
- 添加
ThreadPoolTaskScheduler线程池任务调度配置 - 配置STOMP跨域允许规则
setAllowedOrigins
多轮自行排查未定位问题根因。
相关WebSocket配置代码
private static final Logger LOGGER = LoggerFactory.getLogger(WebsocketBrokerConfig.class); @Override public void configureMessageBroker(MessageBrokerRegistry registry) { //for subscribe prefix registry.enableSimpleBroker("/user"); //for publish prefix registry.setApplicationDestinationPrefixes("/app"); //user destination provides ability to have unique user queue //registry.setUserDestinationPrefix("/user"); } @Override public void registerStompEndpoints(StompEndpointRegistry registry) { registry.addEndpoint("/broadcast") .setAllowedOrigins("http://ec2....amazonaws.com") .withSockJS() .setHeartbeatTime(60_000); }
启动与自动退出日志
. ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v2.4.3) 2021-03-03 00:44:34.278 INFO 5898 --- [ main] com.example.salle.SalleApplication : Starting SalleApplication v0.0.1-SNAPSHOT using Java 1.8.0_282 on ip-172-31-46-33 with PID 5898 (/home/ubuntu/salle/salle/target/test-0.0.1-SNAPSHOT.jar started by ubuntu in /home/ubuntu/salle/salle) 2021-03-03 00:44:34.283 INFO 5898 --- [ main] com.example.salle.SalleApplication : No active profile set, falling back to default profiles: default 2021-03-03 00:44:36.435 INFO 5898 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JPA repositories in DEFAULT mode. 2021-03-03 00:44:36.489 INFO 5898 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 31 ms. Found 0 JPA repository interfaces. 2021-03-03 00:44:38.298 INFO 5898 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http) 2021-03-03 00:44:38.330 INFO 5898 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat] 2021-03-03 00:44:38.330 INFO 5898 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.43] 2021-03-03 00:44:39.363 INFO 5898 --- [ main] org.apache.jasper.servlet.TldScanner : At least one JAR was scanned for TLDs yet contained no TLDs. Enable debug logging for a complete list of JARs that were scanned but no TLDs were found in them. Skipping unneeded JARs during scanning can improve startup time and JSP compilation time. 2021-03-03 00:44:39.969 INFO 5898 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext 2021-03-03 00:44:39.969 INFO 5898 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 5536 ms 2021-03-03 00:44:41.016 INFO 5898 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting... 2021-03-03 00:44:41.247 INFO 5898 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed. 2021-03-03 00:44:41.408 INFO 5898 --- [ main] o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing PersistenceUnitInfo [name: default] 2021-03-03 00:44:41.600 INFO 5898 --- [ main] org.hibernate.Version : HHH000412: Hibernate ORM core version 5.4.28.Final 2021-03-03 00:44:41.900 INFO 5898 --- [ main] org.hibernate.annotations.common.Version : HCANN000001: Hibernate Commons Annotations {5.1.2.Final} 2021-03-03 00:44:42.217 INFO 5898 --- [ main] org.hibernate.dialect.Dialect : HHH000400: Using dialect: org.hibernate.dialect.MariaDB103Dialect 2021-03-03 00:44:43.125 INFO 5898 --- [ main] o.h.e.t.j.p.i.JtaPlatformInitiator : HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform] 2021-03-03 00:44:43.155 INFO 5898 --- [ main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default' 2021-03-03 00:44:45.786 INFO 5898 --- [ main] o.s.s.c.ThreadPoolTaskScheduler : Initializing ExecutorService 2021-03-03 00:44:45.860 INFO 5898 --- [ main] o.s.s.c.ThreadPoolTaskScheduler : Initializing ExecutorService 'messageBrokerTaskScheduler' 2021-03-03 00:44:46.023 INFO 5898 --- [ main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService 'clientInboundChannelExecutor' 2021-03-03 00:44:46.025 INFO 5898 --- [ main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService 'clientOutboundChannelExecutor' 2021-03-03 00:44:46.035 INFO 5898 --- [ main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService 'brokerChannelExecutor' 2021-03-03 00:44:46.140 WARN 5898 --- [ main] JpaBaseConfiguration$JpaWebConfiguration : spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning 2021-03-03 00:44:47.221 INFO 5898 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path '' 2021-03-03 00:44:47.227 INFO 5898 --- [ main] o.s.m.s.b.SimpleBrokerMessageHandler : Starting... 2021-03-03 00:44:47.227 INFO 5898 --- [ main] o.s.m.s.b.SimpleBrokerMessageHandler : BrokerAvailabilityEvent[available=true, SimpleBrokerMessageHandler [DefaultSubscriptionRegistry[cache[0 destination(s)], registry[0 sessions]]]] 2021-03-03 00:44:47.233 INFO 5898 --- [ main] o.s.m.s.b.SimpleBrokerMessageHandler : Started. 2021-03-03 00:44:47.252 INFO 5898 --- [ main] com.example.salle.SalleApplication : Started SalleApplication in 14.288 seconds (JVM running for 15.469) 2021-03-03 00:45:00.256 INFO 5898 --- [extShutdownHook] o.s.m.s.b.SimpleBrokerMessageHandler : Stopping... 2021-03-03 00:45:00.258 INFO 5898 --- [extShutdownHook] o.s.m.s.b.SimpleBrokerMessageHandler : BrokerAvailabilityEvent[available=false, SimpleBrokerMessageHandler [DefaultSubscriptionRegistry[cache[0 destination(s)], registry[0 sessions]]]] 2021-03-03 00:45:00.258 INFO 5898 --- [extShutdownHook] o.s.m.s.b.SimpleBrokerMessageHandler : Stopped. 2021-03-03 00:45:00.284 INFO 5898 --- [extShutdownHook] o.s.s.concurrent.ThreadPoolTaskExecutor : Shutting down ExecutorService 'brokerChannelExecutor' 2021-03-03 00:45:00.284 INFO 5898 --- [extShutdownHook] o.s.s.concurrent.ThreadPoolTaskExecutor : Shutting down ExecutorService 'clientOutboundChannelExecutor' 2021-03-03 00:45:00.284 INFO 5898 --- [extShutdownHook] o.s.s.concurrent.ThreadPoolTaskExecutor : Shutting down ExecutorService 'clientInboundChannelExecutor' 2021-03-03 00:45:00.284 INFO 5898 --- [extShutdownHook] o.s.s.c.ThreadPoolTaskScheduler : Shutting down ExecutorService 'messageBrokerTaskScheduler' 2021-03-03 00:45:00.296 INFO 5898 --- [extShutdownHook] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default' 2021-03-03 00:45:00.299 INFO 5898 --- [extShutdownHook] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown initiated...
问题根因定位
从日志中可看到,所有应用组件初始化流程全部正常完成,WebSocket相关的任务调度器、消息处理器、线程池均无报错。触发应用停止的执行线程为[extShutdownHook],这是Spring Boot内置的JVM外部信号关闭钩子,故障和WebSocket配置完全无关。
根因是部署方式存在问题:直接在SSH会话中执行java -jar启动的进程,会完全绑定当前SSH终端的会话生命周期。一旦SSH连接断开(包含连接超时自动断开、手动退出、网络波动中断),终端会向关联的进程组发送SIGHUP挂断信号,触发JVM执行关闭流程,对应日志里启动完成13秒后自动退出的现象。
解决方案
- 临时调试场景:改用后台脱离会话的方式启动进程,执行命令替换为
nohup java -jar *.jar > app.log 2>&1 &。该命令会让进程脱离SSH会话绑定,即使SSH断开也不会触发关闭,同时将日志输出到指定文件便于排查。 - 生产部署场景:推荐将应用注册为系统级systemd服务,实现进程生命周期托管。配置完成后可实现开机自启、异常自动重启、日志统一收集,不受SSH会话状态影响,是EC2环境部署Java应用的标准实践。
注:现有WebSocket配置存在两个非致命的可优化点,后续可调整:
- 若后续需要实现点对点单用户消息推送,需要取消代码中
setUserDestinationPrefix("/user")的注释,否则用户维度的消息路由会失效setAllowedOrigins配置的域名不完整,需替换为实际的前端访问域名,避免跨域拦截
内容的提问来源于stack exchange,提问作者baekho
相关产品推荐
相关产品推荐

