[spring-projects/spring-boot]BufferingApplicationStartup 失败并出现 NoSuchElementException

2024-06-26 821 views
6

我的应用程序运行很少会失败并出现以下错误:

[main] ERROR o.s.boot.SpringApplication - Application run failed
java.util.NoSuchElementException: null
at java.base/java.util.ArrayDeque.removeFirst(Unknown Source)
at org.springframework.boot.context.metrics.buffering.BufferingApplicationStartup.record(BufferingApplicationStartup.java:138)
at org.springframework.boot.context.metrics.buffering.BufferedStartupStep.end(BufferedStartupStep.java:92)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:614)
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:144)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:767)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:759)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:426)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:326)

Spring boot 版本是 2.4.1. 我有以下与 spring 相关的依赖项:

<dependency>                                                    
    <groupId>org.springframework.boot</groupId>                 
    <artifactId>spring-boot-starter</artifactId>                
</dependency>                                                   
<dependency>                                                    
    <groupId>de.codecentric</groupId>                           
    <artifactId>spring-boot-admin-starter-client</artifactId>   
</dependency>                                                   
<dependency>                                                    
    <groupId>org.springframework.boot</groupId>                 
    <artifactId>spring-boot-autoconfigure</artifactId>          
</dependency>                                                   
<dependency>                                                    
    <groupId>org.springframework.boot</groupId>                 
    <artifactId>spring-boot-starter-web</artifactId>            
</dependency>                                                   
<dependency>                                                    
    <groupId>org.springframework.boot</groupId>                 
    <artifactId>spring-boot-starter-security</artifactId>       
</dependency>                                                   
<dependency>                                                    
    <groupId>org.springframework.boot</groupId>                 
    <artifactId>spring-boot-configuration-processor</artifactId>
    <optional>true</optional>                                   
</dependency>                                                   
<dependency>                                                    
    <groupId>org.springframework.boot</groupId>                 
    <artifactId>spring-boot-starter-data-mongodb</artifactId>   
</dependency>                                                   

回答

5

不幸的是,这并没有提供足够的信息来解决这个问题。

这种情况只应在上下文刷新期间启动事件同时发生时发生;由于上下文刷新是单线程的,因此不应该发生这种情况。我很想了解有关此实例的更多线索。

  • 是否有ApplicationRunner实例或应用程序 bean 在初始化期间执行多线程工作?
  • 您是否为 设置了特定值spring.data.jpa.repositories.bootstrap-mode

我对此并不乐观,因为从定义上讲,重现这个问题确实很困难。但我们可以重新利用这个问题来探索缓解这个问题的方法,或在发生故障时提供更多有用的信息。

7

我没有为 设定特定值spring.data.jpa.repositories.bootstrap-mode。我认为我没有具有ApplicationRunner此类逻辑的实例,但常规 bean 可以执行多线程工作。这个项目相当大,所以我不确定能否找到根本原因。如果您能告诉我在哪里可以检查您需要调查的内容,那就太好了

4

我想知道是否BufferedStartupStep.end()以某种方式被调用了两次?我们是否应该改为currentSteps.removeFirst删除BufferedStartupStep.id

4

实际上我不能确定,但​​我不会手动使用它或类似的东西。我只是在从 2.3.x 迁移到 spring boot 2.4.1 时将应用程序运行器添加到现有应用程序中。

2

作为第一步,我们将尝试添加更多日志记录

5

我们有同样的问题(Spring Boot 2.4.5),可能是由于大量使用自定义请求范围 bean 而产生的

java.util.NoSuchElementException: null
        at java.base/java.util.ArrayDeque.removeFirst(Unknown Source)
        at org.springframework.boot.context.metrics.buffering.BufferingApplicationStartup.record(BufferingApplicationStartup.java:138)
        at org.springframework.boot.context.metrics.buffering.BufferedStartupStep.end(BufferedStartupStep.java:92)
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:394)
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208)
        at org.springframework.aop.target.SimpleBeanTargetSource.getTarget(SimpleBeanTargetSource.java:35)
        at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:676)

我们用以下代码初始化启动Bean:

SpringApplication app = new SpringApplication(Application.class);
app.setApplicationStartup(new BufferingApplicationStartup(10000));
5

@gbrehmer 我认为您无法在小示例应用程序中复制该问题?

1

抱歉,没那么简单,我尝试了并发 MockMVC 测试,但无法重现该问题。可能是因为 junit 测试中的上下文启动与普通应用程序启动不同。当前ArrayDeque使用的是非线程安全的。那么使用线程安全的变体怎么样Deque

4

可以说,我们不应该跟踪请求范围 bean 的启动指标 - 应用程序已经启动,并且它不是设计为在运行时连续使用的。也许我们应该在上下文完全刷新后停止跟踪?这可能会限制此类问题,但也可能错过重要数据。这将在 Spring 框架级别处理。

@gbrehmer 此功能用于跟踪上下文启动,它是单线程的。我们选择此变体是为了避免测量时的性能开销。

3

@gbrehmer 此功能用于跟踪上下文启动,它是单线程的。我们选择此变体是为了避免测量时的性能开销。

我知道这个功能的作用,但我不知道存在哪些依赖项或如何拦截生命周期。从我的角度来看,这个问题应该很快就会得到解决,可能通过排除请求范围 bean 来解决(我假设在启动期间创建时没有请求范围 bean)

1

@philwebb — 我们在使用 Spring Boot 2.4.4 版本时也遇到了同样的问题,我们是否有计划将其移植回去或者针对旧版本进行一些临时修复。

6

@bharatnpti 它已在 2.4.6 中修复。

2

@bclozel - 是的,我看到了,但我们目前正在使用 2.4.4,所以我想唯一的选择是转移到 2.4.6,如果没有反向移植

5

@bharatnpti2.4.6是 的补丁版本2.4.4。此行中的最后一个是2.4.13。同一行上不存在“反向移植”之类的事情。