[spring-projects/spring-boot]CommandLineRunner 完成后应用程序不再终止

2024-07-08 357 views
9

我使用以下代码结构运行一些 Java 批处理进程:

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @Bean
    public CommandLineRunner commandLineRunner(MyServiceInstance service) {
        return args -> {
            service.doJob();
        };
    }

}

在 Spring 2.4.2 之前,我的服务/进程在完成作业后终止,因此代码很方便运行批处理作业。从 Spring 2.4.2 开始,服务实例不会终止。因此想象一下结果,我的所有实例都在我的 AWS Batch 帐户中运行,导致成本增加并阻止其他作业。

<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.2</version>

回答

2

@eduardobarrena-tc 感谢您的报告,但我们需要更多信息才能确定 Spring Boot 2.4.2 中发生了哪些更改导致此行为发生变化。请提供一个可重现问题的最小示例,以便我们查看。您可以添加一条带有 GitHub 上项目链接的评论,或将项目作为 zip 文件附加到问题中。

3

@eduardobarrena-tc 我认为您描述中的大写字母没什么用。要隔离应用程序中的守​​护线程(Spring Boot 不应该),您可以在作业完成时触发线程转储并分析线程转储。

7

@eduardobarrena-tc 我认为您描述中的大写字母没什么用。要隔离应用程序中的守​​护线程(Spring Boot 不应该),您可以在作业完成时触发线程转储并分析线程转储。

只是情绪而已……我会调查并提供更多信息,目前还不确定发生了什么。我有一个 maven 父结构,其中包含多个依赖项,因此这并不容易。我正在从“2.2.5.RELEASE”更新

5

这是线程转储。如果我从“2.2.5.RELEASE”更新到“2.4.2”,就会出现此问题

2021-04-06 10:05:28
Full thread dump OpenJDK 64-Bit Server VM (11.0.2+9 mixed mode):

Threads class SMR info:
_java_thread_list=0x00007efdd0001ec0, length=19, elements={
0x00007efe18268800, 0x00007efe1826c800, 0x00007efe1827f000, 0x00007efe18281000,
0x00007efe18283800, 0x00007efe18285800, 0x00007efe18334000, 0x00007efe1833f800,
0x00007efe1917c800, 0x00007efe18ef1800, 0x00007efe19564000, 0x00007efe18a34800,
0x00007efd6c096000, 0x00007efe19b83800, 0x00007efe18011000, 0x00007efd6c011000,
0x00007efd6c03a000, 0x00007efd6c065000, 0x00007efdd0001000
}

"Reference Handler" #2 daemon prio=10 os_prio=0 cpu=7.55ms elapsed=27.33s tid=0x00007efe18268800 nid=0x4802 waiting on condition  [0x00007efde35fa000]
   java.lang.Thread.State: RUNNABLE
    at java.lang.ref.Reference.waitForReferencePendingList(java.base@11.0.2/Native Method)
    at java.lang.ref.Reference.processPendingReferences(java.base@11.0.2/Reference.java:241)
    at java.lang.ref.Reference$ReferenceHandler.run(java.base@11.0.2/Reference.java:213)

   Locked ownable synchronizers:
    - None

"Finalizer" #3 daemon prio=8 os_prio=0 cpu=0.47ms elapsed=27.33s tid=0x00007efe1826c800 nid=0x4803 in Object.wait()  [0x00007efde34f9000]
   java.lang.Thread.State: WAITING (on object monitor)
    at java.lang.Object.wait(java.base@11.0.2/Native Method)
    - waiting on <0x0000000709c03358> (a java.lang.ref.ReferenceQueue$Lock)
    at java.lang.ref.ReferenceQueue.remove(java.base@11.0.2/ReferenceQueue.java:155)
    - waiting to re-lock in wait() <0x0000000709c03358> (a java.lang.ref.ReferenceQueue$Lock)
    at java.lang.ref.ReferenceQueue.remove(java.base@11.0.2/ReferenceQueue.java:176)
    at java.lang.ref.Finalizer$FinalizerThread.run(java.base@11.0.2/Finalizer.java:170)

   Locked ownable synchronizers:
    - None

"Signal Dispatcher" #4 daemon prio=9 os_prio=0 cpu=0.24ms elapsed=27.32s tid=0x00007efe1827f000 nid=0x4804 runnable  [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
    - None

"C2 CompilerThread0" #5 daemon prio=9 os_prio=0 cpu=6310.45ms elapsed=27.32s tid=0x00007efe18281000 nid=0x4805 waiting on condition  [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE
   No compile task

   Locked ownable synchronizers:
    - None

"C1 CompilerThread0" #8 daemon prio=9 os_prio=0 cpu=2834.72ms elapsed=27.32s tid=0x00007efe18283800 nid=0x4806 waiting on condition  [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE
   No compile task

   Locked ownable synchronizers:
    - None

"Sweeper thread" #9 daemon prio=9 os_prio=0 cpu=81.79ms elapsed=27.32s tid=0x00007efe18285800 nid=0x4807 runnable  [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
    - None

"Service Thread" #10 daemon prio=9 os_prio=0 cpu=0.16ms elapsed=27.30s tid=0x00007efe18334000 nid=0x4808 runnable  [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
    - None

"Common-Cleaner" #11 daemon prio=8 os_prio=0 cpu=11.68ms elapsed=27.30s tid=0x00007efe1833f800 nid=0x480a in Object.wait()  [0x00007efde2b0c000]
   java.lang.Thread.State: TIMED_WAITING (on object monitor)
    at java.lang.Object.wait(java.base@11.0.2/Native Method)
    - waiting on <0x0000000709c04288> (a java.lang.ref.ReferenceQueue$Lock)
    at java.lang.ref.ReferenceQueue.remove(java.base@11.0.2/ReferenceQueue.java:155)
    - waiting to re-lock in wait() <0x0000000709c04288> (a java.lang.ref.ReferenceQueue$Lock)
    at jdk.internal.ref.CleanerImpl.run(java.base@11.0.2/CleanerImpl.java:148)
    at java.lang.Thread.run(java.base@11.0.2/Thread.java:834)
    at jdk.internal.misc.InnocuousThread.run(java.base@11.0.2/InnocuousThread.java:134)

   Locked ownable synchronizers:
    - None

"mysql-cj-abandoned-connection-cleanup" #16 daemon prio=5 os_prio=0 cpu=1.11ms elapsed=24.87s tid=0x00007efe1917c800 nid=0x4814 in Object.wait()  [0x00007efde10f9000]
   java.lang.Thread.State: TIMED_WAITING (on object monitor)
    at java.lang.Object.wait(java.base@11.0.2/Native Method)
    - waiting on <0x000000070a7c1578> (a java.lang.ref.ReferenceQueue$Lock)
    at java.lang.ref.ReferenceQueue.remove(java.base@11.0.2/ReferenceQueue.java:155)
    - waiting to re-lock in wait() <0x000000070a7c1578> (a java.lang.ref.ReferenceQueue$Lock)
    at com.mysql.cj.jdbc.AbandonedConnectionCleanupThread.run(AbandonedConnectionCleanupThread.java:91)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(java.base@11.0.2/ThreadPoolExecutor.java:1128)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(java.base@11.0.2/ThreadPoolExecutor.java:628)
    at java.lang.Thread.run(java.base@11.0.2/Thread.java:834)

   Locked ownable synchronizers:
    - <0x000000070a7c1720> (a java.util.concurrent.ThreadPoolExecutor$Worker)

"HikariPool-1 housekeeper" #17 daemon prio=5 os_prio=0 cpu=1.29ms elapsed=19.95s tid=0x00007efe18ef1800 nid=0x481b waiting on condition  [0x00007efde25e2000]
   java.lang.Thread.State: TIMED_WAITING (parking)
    at jdk.internal.misc.Unsafe.park(java.base@11.0.2/Native Method)
    - parking to wait for  <0x000000070ab14578> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
    at java.util.concurrent.locks.LockSupport.parkNanos(java.base@11.0.2/LockSupport.java:234)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(java.base@11.0.2/AbstractQueuedSynchronizer.java:2123)
    at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(java.base@11.0.2/ScheduledThreadPoolExecutor.java:1182)
    at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(java.base@11.0.2/ScheduledThreadPoolExecutor.java:899)
    at java.util.concurrent.ThreadPoolExecutor.getTask(java.base@11.0.2/ThreadPoolExecutor.java:1054)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(java.base@11.0.2/ThreadPoolExecutor.java:1114)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(java.base@11.0.2/ThreadPoolExecutor.java:628)
    at java.lang.Thread.run(java.base@11.0.2/Thread.java:834)

   Locked ownable synchronizers:
    - None

"Thread-1" #19 daemon prio=5 os_prio=0 cpu=11.62ms elapsed=16.43s tid=0x00007efe19564000 nid=0x4824 runnable  [0x00007efde24e1000]
   java.lang.Thread.State: RUNNABLE
    at sun.nio.ch.EPoll.wait(java.base@11.0.2/Native Method)
    at sun.nio.ch.EPollSelectorImpl.doSelect(java.base@11.0.2/EPollSelectorImpl.java:120)
    at sun.nio.ch.SelectorImpl.lockAndDoSelect(java.base@11.0.2/SelectorImpl.java:124)
    - locked <0x000000070b3063d0> (a sun.nio.ch.Util$2)
    - locked <0x000000070b306378> (a sun.nio.ch.EPollSelectorImpl)
    at sun.nio.ch.SelectorImpl.select(java.base@11.0.2/SelectorImpl.java:136)
    at com.amazon.jdbc.communications.InboundMessagesThread.run(Unknown Source)

   Locked ownable synchronizers:
    - None

"HikariPool-2 housekeeper" #21 daemon prio=5 os_prio=0 cpu=0.35ms elapsed=15.84s tid=0x00007efe18a34800 nid=0x4826 waiting on condition  [0x00007efd931b1000]
   java.lang.Thread.State: TIMED_WAITING (parking)
    at jdk.internal.misc.Unsafe.park(java.base@11.0.2/Native Method)
    - parking to wait for  <0x000000070b2fac00> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
    at java.util.concurrent.locks.LockSupport.parkNanos(java.base@11.0.2/LockSupport.java:234)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(java.base@11.0.2/AbstractQueuedSynchronizer.java:2123)
    at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(java.base@11.0.2/ScheduledThreadPoolExecutor.java:1182)
    at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(java.base@11.0.2/ScheduledThreadPoolExecutor.java:899)
    at java.util.concurrent.ThreadPoolExecutor.getTask(java.base@11.0.2/ThreadPoolExecutor.java:1054)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(java.base@11.0.2/ThreadPoolExecutor.java:1114)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(java.base@11.0.2/ThreadPoolExecutor.java:628)
    at java.lang.Thread.run(java.base@11.0.2/Thread.java:834)

   Locked ownable synchronizers:
    - None

"Thread-2" #23 daemon prio=5 os_prio=0 cpu=4.09ms elapsed=14.31s tid=0x00007efd6c096000 nid=0x482a runnable  [0x00007efd915aa000]
   java.lang.Thread.State: RUNNABLE
    at sun.nio.ch.EPoll.wait(java.base@11.0.2/Native Method)
    at sun.nio.ch.EPollSelectorImpl.doSelect(java.base@11.0.2/EPollSelectorImpl.java:120)
    at sun.nio.ch.SelectorImpl.lockAndDoSelect(java.base@11.0.2/SelectorImpl.java:124)
    - locked <0x000000070b43cfa0> (a sun.nio.ch.Util$2)
    - locked <0x000000070b43cf48> (a sun.nio.ch.EPollSelectorImpl)
    at sun.nio.ch.SelectorImpl.select(java.base@11.0.2/SelectorImpl.java:136)
    at com.amazon.jdbc.communications.InboundMessagesThread.run(Unknown Source)

   Locked ownable synchronizers:
    - None

"lettuce-timer-3-1" #24 prio=5 os_prio=0 cpu=14.68ms elapsed=14.14s tid=0x00007efe19b83800 nid=0x482b sleeping [0x00007efd914a9000]
   java.lang.Thread.State: TIMED_WAITING (sleeping)
    at java.lang.Thread.sleep(java.base@11.0.2/Native Method)
    at io.netty.util.HashedWheelTimer$Worker.waitForNextTick(HashedWheelTimer.java:567)
    at io.netty.util.HashedWheelTimer$Worker.run(HashedWheelTimer.java:466)
    at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
    at java.lang.Thread.run(java.base@11.0.2/Thread.java:834)

   Locked ownable synchronizers:
    - None

"DestroyJavaVM" #25 prio=5 os_prio=0 cpu=7302.73ms elapsed=13.73s tid=0x00007efe18011000 nid=0x47fb waiting on condition  [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
    - None

"Thread-3" #26 daemon prio=5 os_prio=0 cpu=5.26ms elapsed=12.18s tid=0x00007efd6c011000 nid=0x4832 runnable  [0x00007efd91ead000]
   java.lang.Thread.State: RUNNABLE
    at sun.nio.ch.EPoll.wait(java.base@11.0.2/Native Method)
    at sun.nio.ch.EPollSelectorImpl.doSelect(java.base@11.0.2/EPollSelectorImpl.java:120)
    at sun.nio.ch.SelectorImpl.lockAndDoSelect(java.base@11.0.2/SelectorImpl.java:124)
    - locked <0x000000070bd257a0> (a sun.nio.ch.Util$2)
    - locked <0x000000070bd25748> (a sun.nio.ch.EPollSelectorImpl)
    at sun.nio.ch.SelectorImpl.select(java.base@11.0.2/SelectorImpl.java:136)
    at com.amazon.jdbc.communications.InboundMessagesThread.run(Unknown Source)

   Locked ownable synchronizers:
    - None

"Thread-4" #27 daemon prio=5 os_prio=0 cpu=4.97ms elapsed=10.06s tid=0x00007efd6c03a000 nid=0x4833 runnable  [0x00007efd91bac000]
   java.lang.Thread.State: RUNNABLE
    at sun.nio.ch.EPoll.wait(java.base@11.0.2/Native Method)
    at sun.nio.ch.EPollSelectorImpl.doSelect(java.base@11.0.2/EPollSelectorImpl.java:120)
    at sun.nio.ch.SelectorImpl.lockAndDoSelect(java.base@11.0.2/SelectorImpl.java:124)
    - locked <0x0000000716a706c8> (a sun.nio.ch.Util$2)
    - locked <0x0000000716a70670> (a sun.nio.ch.EPollSelectorImpl)
    at sun.nio.ch.SelectorImpl.select(java.base@11.0.2/SelectorImpl.java:136)
    at com.amazon.jdbc.communications.InboundMessagesThread.run(Unknown Source)

   Locked ownable synchronizers:
    - None

"Thread-5" #28 daemon prio=5 os_prio=0 cpu=5.01ms elapsed=7.98s tid=0x00007efd6c065000 nid=0x4834 runnable  [0x00007efd90cb0000]
   java.lang.Thread.State: RUNNABLE
    at sun.nio.ch.EPoll.wait(java.base@11.0.2/Native Method)
    at sun.nio.ch.EPollSelectorImpl.doSelect(java.base@11.0.2/EPollSelectorImpl.java:120)
    at sun.nio.ch.SelectorImpl.lockAndDoSelect(java.base@11.0.2/SelectorImpl.java:124)
    - locked <0x0000000716ab1ee0> (a sun.nio.ch.Util$2)
    - locked <0x0000000716ab1d90> (a sun.nio.ch.EPollSelectorImpl)
    at sun.nio.ch.SelectorImpl.select(java.base@11.0.2/SelectorImpl.java:136)
    at com.amazon.jdbc.communications.InboundMessagesThread.run(Unknown Source)

   Locked ownable synchronizers:
    - None

"Attach Listener" #29 daemon prio=9 os_prio=0 cpu=0.33ms elapsed=0.16s tid=0x00007efdd0001000 nid=0x4856 waiting on condition  [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
    - None

"VM Thread" os_prio=0 cpu=117.33ms elapsed=27.34s tid=0x00007efe18260800 nid=0x4801 runnable  

"GC Thread#0" os_prio=0 cpu=260.05ms elapsed=27.36s tid=0x00007efe18038800 nid=0x47fc runnable  

"GC Thread#1" os_prio=0 cpu=234.61ms elapsed=27.18s tid=0x00007efdd4001000 nid=0x480d runnable  

"GC Thread#2" os_prio=0 cpu=233.74ms elapsed=27.18s tid=0x00007efdd4002800 nid=0x480e runnable  

"GC Thread#3" os_prio=0 cpu=224.87ms elapsed=27.18s tid=0x00007efdd4004000 nid=0x480f runnable  

"GC Thread#4" os_prio=0 cpu=250.96ms elapsed=27.18s tid=0x00007efdd4005800 nid=0x4810 runnable  

"GC Thread#5" os_prio=0 cpu=213.38ms elapsed=24.84s tid=0x00007efdd403d000 nid=0x4815 runnable  

"GC Thread#6" os_prio=0 cpu=215.24ms elapsed=24.84s tid=0x00007efdd403e000 nid=0x4816 runnable  

"GC Thread#7" os_prio=0 cpu=154.08ms elapsed=16.97s tid=0x00007efdd4075000 nid=0x4823 runnable  

"G1 Main Marker" os_prio=0 cpu=1.60ms elapsed=27.36s tid=0x00007efe18095800 nid=0x47fd runnable  

"G1 Conc#0" os_prio=0 cpu=45.39ms elapsed=27.36s tid=0x00007efe18097800 nid=0x47fe runnable  

"G1 Conc#1" os_prio=0 cpu=47.29ms elapsed=26.18s tid=0x00007efdec001000 nid=0x4812 runnable  

"G1 Refine#0" os_prio=0 cpu=2.68ms elapsed=27.35s tid=0x00007efe18195000 nid=0x47ff runnable  

"G1 Young RemSet Sampling" os_prio=0 cpu=9.70ms elapsed=27.35s tid=0x00007efe18197000 nid=0x4800 runnable  
"VM Periodic Task Thread" os_prio=0 cpu=23.86ms elapsed=27.30s tid=0x00007efe18336800 nid=0x4809 waiting on condition  

JNI global refs: 17, weak refs: 0
0

看起来 Lettuce 已启动一个仍在运行的非守护进程线程:

"lettuce-timer-3-1" #24 prio=5 os_prio=0 cpu=14.68ms elapsed=14.14s tid=0x00007efe19b83800 nid=0x482b sleeping [0x00007efd914a9000]
   java.lang.Thread.State: TIMED_WAITING (sleeping)
    at java.lang.Thread.sleep(java.base@11.0.2/Native Method)
    at io.netty.util.HashedWheelTimer$Worker.waitForNextTick(HashedWheelTimer.java:567)
    at io.netty.util.HashedWheelTimer$Worker.run(HashedWheelTimer.java:466)
    at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
    at java.lang.Thread.run(java.base@11.0.2/Thread.java:834)

从您目前分享的内容来看,尚不清楚为什么会出现这种情况。如果您希望我们花更多时间进行调查,我认为我们需要 @scottfrederick上面要求的最小样本。

3

大家好,我在这里附上了一个包含最少工件的项目示例,以便重现错误。我看是自动配置问题,在我的项目中,为了使其工作,我不得不禁用几个自动配置并手动配置。但是,一些模块继承了这些 maven 工件,无法正常结束。最好有一个像 @DisableAutoconfiguration 这样的注释(与 @EnableAutoConfiguration 相反,是属性 spring.autoconfigure.exclude 的友好替代方案)。然而,有些工件的存在会破坏事情,这并不好 :S

https://github.com/eduardobarrena-tc/demo-spring-boot-bug-4.2.2

ed@pc: $ java -version
openjdk version "11.0.2" 2019-01-15
OpenJDK Runtime Environment 18.9 (build 11.0.2+9)
OpenJDK 64-Bit Server VM 18.9 (build 11.0.2+9, mixed mode)
ed@pc: $ uname -a
Linux pc 4.19.0-6-amd64 #1 SMP Debian 4.19.67-2 (2019-08-28) x86_64 GNU/Linux
5

感谢提供示例项目。这看起来可能是 Lettuce 的问题。添加<lettuce.version>6.0.1.RELEASE</lettuce.version>到 POM 也可以修复此问题。

我将进一步深入挖掘,看看能否找出发生了什么变化。

9

Lettuce 为计时器创建一个非守护线程,类似于默认的Executors.defaultThreadFactory()。 提到的更改是为了修复急切初始化线程的问题,以避免在非阻塞工作负载的上下文中阻塞调用。

ClientResources.shutdown()停止计时器,因此我认为正确处理 bean 也会停止计时器线程。

6

我们陷入了困境。该shutdown()方法确实会被调用,但只有在ApplicationContext关闭时才会调用。如果非守护线程仍处于活动状态,则不会发生这种情况。

@eduardobarrena-tc 你可以将主要方法更改为此以强制关闭上下文:

public static void main(String[] args) {
    SpringApplication.run(DemoApplication.class, args).close();
}
3

感谢@philwebb 提供的简单而酷的解决方案,但我注意到互联网上很多人都在使用我提供的代码作为配方。

建议:在框架中可以有一个很酷的功能,那就是禁用@DisableAutoconfiguration所有自动配置类。我知道我可以排除它们,但在这种情况下,我必须枚举它们,如果我这样做,代码今天可能会起作用,但如果在框架中添加或更改了新的自动配置(如本例所示),则将来就不起作用了。如果无法使用该注释,则另一个选项可能是使用星号,例如“spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.*”;我试过了,但没有用。

谢谢你们 !!

8

我找不到HashedWheelTimer默认使用非守护线程的原因,所以我不能说这样的改变会破坏(或不会破坏)什么。作为解决方法,Boot 可以提供自己的计时器,该计时器由守护线程构成,这将与其应用程序生命周期假设很好地保持一致。

一般来说,这个问题可能会影响所有创建计时器实例的基于 netty 的集成(例如 Cassandra 驱动程序)。

ThreadFactory为不会阻止应用程序关闭的组件提供特定于引导的功能是否有意义?

在 Lettuce 中,我们可以引入这样的方法,这样配置类就不需要计算驱动程序内部结构了。

4

@eduardobarrena-tc 您已经可以在没有自动配置的情况下使用 Spring Boot,如果您看一下,@SpringBootApplication您会发现它实际上是:

@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
        @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {

如果您不想要自动配置,您可以使用以下命令注释您的主类:

@SpringBootConfiguration
@ComponentScan

spring-boot-autoconfigure如果您想完全确保不使用自动配置功能,您也可以排除该jar。

9

标记团队会议来讨论特定于 Boot 的ThreadFactory

8

我不确定 Spring Boot 应用程序是否允许我们假设 Netty 计时器线程应该是非守护进程的。例如,如果 Lettuce 通常不能做出这种假设,那么我认为在 Boot 应用程序中使用它不会改变这种情况。只要 JVM 在上下文关闭后退出(通过显式调用close()或通过由于 SIGTERM 而运行的关闭挂钩),那么我认为我们不应该在这里做任何事情。

5

综合考虑,我认为我们最好保持与 Lettuce 相同的线程设置。显式调用.close()似乎是用户的最佳解决方案。