【问题标题】:Stop properly SpringBoot jmsApplication正确停止 Spring Boot jms 应用程序
【发布时间】:2020-09-17 22:23:21
【问题描述】:

我想正确停止一个 jms 应用程序,我有以下代码,我正在从侦听器调用关闭方法:

   public void initiateAppShutDown(int returnCode){
        SpringApplication.exit(context, ()-> returnCode);
   }
    
   public void shudDownApplication(){
        LOGGER.debug("Arret de l'application injecteur");
        initiateAppShutDown(0);
   }

我正在从侦听器的方法onMessageReceived() 执行关闭,但我有以下警告,似乎消息被侦听器拒绝:

Failed to shut down 1 bean with phase value 2147483647 within timeout of 30000: [org.springframework.jms.config.internalJmsListenerEndpointRegistry]

还有以下内容:

DefaultMessageListenerContainer:由于监听容器同时停止而拒绝接收到的消息:

更新

这是我的反声明

// we increment the counter. incrementer nombre de messages traités
final AtomicInteger counter = new AtomicInteger(0); 

incrementCounter() 方法递增counter

public void incrementCounter() {
    counter.getAndIncrement();
}

public int get() {
    return counter.get();
}

这里是调用关闭时的方法:

private void checkNumberMessagesProcessed() {
    if(this.get() == Integer.parseInt(nbrMaxMessages)){
        LOGGER.debug("fin de traitement reprise backout avec nombre de messages traites:  " + this.get());
        //close listeners
        //shutdown();
        //close application
        shudDownApplication();
    }
}

即使我达到了nbrMaxMessages=1000 参数化,我仍然有消息被处理,并且应用程序自动重新启动:这里是日志:

2020-09-18 11:59:34,702 DEBUG --- [Backout-1-2] g.c.s.b.c.GdrBackoutListener             : end  process  backout with number of treated messages :  1000
2020-09-18 11:59:34,704 DEBUG --- [Backout-1-9] g.c.s.b.c.GdrBackoutListener             : inject message 49585321304740080b5f1487913fe5270000000000000000 dans INTERNAL_QUEUE with number of messages to trate to 1000
2020-09-18 11:59:34,705 DEBUG --- [Backout-1-5] g.c.s.b.c.GdrBackoutListener             : inject message 495853213045f0080b5f08647b4ab6760000000000000000 dans INTERNAL_QUEUE with number of messages to trate to 1000
2020-09-18 11:59:34,705 DEBUG --- [Backout-1-3] g.c.s.b.c.GdrBackoutListener             : inject message 49585321304740080b5f116d7b4de1960000000000000000 dans INTERNAL_QUEUE with number of messages to trate to 1000
2020-09-18 11:59:34,705 DEBUG --- [Backout-1-4] g.c.s.b.c.GdrBackoutListener             : inject message 49585321304750080b5f136b3193b7690000000000000000 dans INTERNAL_QUEUE with number of messages to trate to 1000
2020-09-18 11:59:34,708 DEBUG --- [pool-7-thread-1] g.c.s.b.c.GdrBackoutListener             : Shutdown application injecteur backout
2020-09-18 11:59:34,709 DEBUG --- [Backout-1-4] g.c.s.b.c.GdrBackoutListener             : inject message 495853213045f0080b5f14f4120ec5b60000000000000000 dans INTERNAL_QUEUE with number of messages to trate to 1000
2020-09-18 11:59:34,709 DEBUG --- [Backout-1-3] g.c.s.b.c.GdrBackoutListener             : inject message 495853213045f0080b5f14003c676edb0000000000000000 dans INTERNAL_QUEUE with number of messages to trate to 1000
2020-09-18 11:59:34,711 DEBUG --- [Backout-1-5] g.c.s.b.c.GdrBackoutListener             : inject message 49585321304750080b5f1394ecc8bc480000000000000000 dans INTERNAL_QUEUE with number of messages to trate to 1000
2020-09-18 11:59:34,711 DEBUG --- [Backout-1-2] g.c.s.b.c.GdrBackoutListener             : inject message 495853213045f0080b5f15042af6ac7b0000000000000000 dans INTERNAL_QUEUE with number of messages to trate to 1000
2020-09-18 11:59:34,712 DEBUG --- [Backout-1-8] g.c.s.b.c.GdrBackoutListener             : inject message 495853213045b0080b5f150c84093cf60000000000000000 dans INTERNAL_QUEUE with number of messages to trate to 1000
2020-09-18 11:59:34,712 DEBUG --- [ackout-1-10] g.c.s.b.c.GdrBackoutListener             : inject message 495853213045b0080b5f0887a7225de50000000000000000 dans INTERNAL_QUEUE with number of messages to trate to 1000
2020-09-18 11:59:34,714 DEBUG --- [Backout-1-3] g.c.s.b.c.GdrBackoutListener             : inject message 49585321304730080b5f1649ac4348a70000000000000000 dans INTERNAL_QUEUE with number of messages to trate to 1000
2020-09-18 11:59:34,714 DEBUG --- [Backout-1-4] g.c.s.b.c.GdrBackoutListener             : inject message 49585321304730080b5f14fffe80e4a10000000000000000 dans INTERNAL_QUEUE with number of messages to trate to 1000
2020-09-18 11:59:34,716 DEBUG --- [Backout-1-5] g.c.s.b.c.GdrBackoutListener             : inject message 49585321304740080b5f146dee9feec60000000000000000 dans INTERNAL_QUEUE with number of messages to trate to 1000
2020-09-18 11:59:34,716 DEBUG --- [Backout-1-2] g.c.s.b.c.GdrBackoutListener             : inject message 495853213045b0080b5f158b80eac21f0000000000000000 dans INTERNAL_QUEUE with number of messages to trate to 1000
2020-09-18 11:59:34,718  INFO --- [pool-7-thread-1] s.c.a.AnnotationConfigApplicationContext : Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@53dbe163: startup date [Fri Sep 18 11:59:32 CEST 2020]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@7a5ceedd
2020-09-18 11:59:34,719 DEBUG --- [Backout-1-3] g.c.s.b.c.GdrBackoutListener             : inject message 495853213045b0080b5f08b16224e18f0000000000000000 dans INTERNAL_QUEUE with number of messages to trate to 1000
2020-09-18 11:59:34,720 DEBUG --- [Backout-1-4] g.c.s.b.c.GdrBackoutListener             : inject message 495853213047e0080b5f16b62be157e60000000000000000 dans INTERNAL_QUEUE with number of messages to trate to 1000
2020-09-18 11:59:34,721 DEBUG --- [Backout-1-5] g.c.s.b.c.GdrBackoutListener             : inject message 49585321304730080b5f15dd2ce0d2df0000000000000000 dans INTERNAL_QUEUE with number of messages to trate to 1000
2020-09-18 11:59:34,721 DEBUG --- [Backout-1-2] g.c.s.b.c.GdrBackoutListener             : inject message 495853213047e0080b5f084d3a3b00260000000000000000 dans INTERNAL_QUEUE with number of messages to trate to 1000
2020-09-18 11:59:34,723  INFO --- [pool-7-thread-1] o.s.c.s.DefaultLifecycleProcessor        : Stopping beans in phase 2147483647

【问题讨论】:

    标签: spring spring-boot spring-jms


    【解决方案1】:

    你在同一个线程中触发了一个关闭调用,它就像死锁一样,你的 onMessage 方法正在等待关闭,而 JMS 容器正在等待正在运行的任务被终止,它最终会超时。

    要解决此问题,您可以使用会触发关闭的异步执行器,类似这样。

    @Component
    public class MessageListener {
       ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
       @JmsListener(...)
       public void onShutdownMessage(Message message){
           // increase delay further if observer any issue, it will trigger shutdown call in 1 seconds
           executorService.schedule(() -> {shudDownApplication();}, 1, TimeUnit.SECONDS);
       }
    }
    

    【讨论】:

    • 我更新了帖子,我有错误,监听器和应用程序没有正常停止
    • 似乎线程 Backout-1-2 停止了进程,但线程 Backout-1-9 、 Backout-1-5 、 Backout-1-3 、 Backout-1-4 继续处理,即使 1000 条消息到达。线程池 pool-7-thread-1 停止了应用程序,但我们可以看到线程继续处理,直到线程池 pool-7-thread-1 停止 bean
    • @ArezkiMouaz 这个监听器的并发性是什么?将此设置为 1,因为这仅用于管理目的。
    • 每个监听器可以有自己的并发,因为这个监听器是用来管理的,它不应该同时执行多个命令,
    【解决方案2】:

    我终于解决了这个问题。

    我对我的听众有一个循环依赖。

    我试图告诉侦听器在等待所有线程完成工作后自行停止。

    这作为一种方法是不正确的。所以我创建了一个错误处理程序,然后我从 JmsListener 抛出错误。并且关闭是管理抛出一个shutDownManager类。 在shutDownManager 中,我创建了一个新线程来停止springApplication。 这种方法适用于线程并发上下文。这是代码:

    @Component
    public class AppContextManager implements ApplicationContextAware {
           private static ApplicationContext _appCtx;
    
        @Override
        public void setApplicationContext(ApplicationContext ctx){
             _appCtx = ctx;
        }
    
        public static ApplicationContext getAppContext(){
            return _appCtx;
        }
    
        public static void exit(Integer exitCode) {
            System.exit(SpringApplication.exit(_appCtx,() -> exitCode));
        }
    
        }
    

    在错误处理程序中,当你想关闭你的应用程序时,你会捕获 Jmslistener 抛出的异常,你调用这个方法

    private void shutDown(){
    //JmsListenerEndpointRegistry bean = context.getBean(JmsListenerEndpointRegistry.class);
    ExecutorService executorService = Executors.newSingleThreadExecutor();
    
        executorService.execute(() -> {
            //bean.stop();
            appContext.exit(0);
        });
    
    }
    

    这允许您静默关闭您的侦听器,并且自定义线程会等待所有线程完成执行

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-07-03
      • 2016-09-01
      • 2021-10-19
      • 2019-06-06
      • 2020-01-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多