Java 当使用带有Kafka的Spring Cloud Stream时,如何执行优雅的应用程序关闭?

Java 当使用带有Kafka的Spring Cloud Stream时,如何执行优雅的应用程序关闭?,java,spring-boot,apache-kafka,spring-cloud-stream,Java,Spring Boot,Apache Kafka,Spring Cloud Stream,我有一个springboot(v.1.57)应用程序,它使用springcloudstream(v1.3.0)和Kafka(v1.1.6)。我希望能够优雅地关闭它,也就是说,在关闭时,所有流侦听器(即,用@StreamListener注释)应该: 停止轮询新邮件 完成他们的工作 将偏移提交给卡夫卡 我注意到ContainerProperties中有一个名为“shutdownTimeout”的属性(默认设置为10000ms),因此我尝试通过反射将ConcurrentKafkAlisterConta

我有一个springboot(v.1.57)应用程序,它使用springcloudstream(v1.3.0)和Kafka(v1.1.6)。我希望能够优雅地关闭它,也就是说,在关闭时,所有流侦听器(即,用@StreamListener注释)应该:

  • 停止轮询新邮件
  • 完成他们的工作
  • 将偏移提交给卡夫卡
  • 我注意到ContainerProperties中有一个名为“shutdownTimeout”的属性(默认设置为10000ms),因此我尝试通过反射将ConcurrentKafkAlisterContainerFactoryConfigurer类(因为它有@ConditionalOnMissingBean注释)扩展到30000,如下所示:

    @Slf4j
    @组成部分
    公共类行为ConcurrentKafkaListenerContainerFactoryConfigurer扩展了ConcurrentKafkaListenerContainerFactoryConfigurer{
    @自动连线
    卡夫卡私人财产;
    @凌驾
    public void configure(ConcurrentKafkaListenerContainerFactory listenerContainerFactory,
    消费者工厂(消费者工厂){
    PropertyAccessor myAccessor=PropertyAccessorFactory.forDirectFieldAccess(此);
    setPropertyValue(“properties”,kproperties);
    ContainerProperties ContainerProperties=listenerContainerFactory
    .getContainerProperties();
    super.configure(listenerContainerFactory、consumerFactory);
    containerProperties.setShutdownTimeout(30000);
    }
    }
    
    但这并不成功。还尝试将它(shutdownTimeout:30000)放在application.yml的SpringCloudStreamBinder设置下,但同样没有帮助

    有什么方法可以控制关机过程并实现我的目标吗?

    编辑

    不再需要进行这种反射黑客;只需在应用程序上下文中添加一个ListenerContainerCustomizer。看

    编辑\u结束

    不再支持spring kafka 1.1.x;您应该在boot 1.5.x中使用1.3.9

    当前的Boot 1.5.x版本是1.5.21

    你应该立即升级

    然而,所有这些项目都有更新的版本

    SpringCloudStream不使用该工厂或引导属性来创建其容器;它不公开在容器上配置该属性的机制

    SpringCloudStream2.1添加了
    ListenerContainerCustomizer
    ,它允许您通过设置绑定容器上的任何属性来定制绑定容器

    我建议您升级到boot2.1.6和springcloudstreamgermantown(2.2.0)

    编辑

    这是一个有点黑客,但它应该工作,直到你可以升级到一个新的流版本

    @springboot应用程序
    @EnableBinding(Sink.class)
    公共类SO56883620应用程序{
    公共静态void main(字符串[]args){
    run(So56883620Application.class,args.close();
    }
    专用最终倒计时闩锁=新倒计时闩锁(1);
    @StreamListener(Sink.INPUT)
    public void listen(字符串输入)抛出InterruptedException{
    这个.latch.countDown();
    系统输出打印项次(输入);
    睡眠(6_000);
    系统输出打印项次(“退出”);
    }
    @豆子
    公共应用程序运行程序(KafkaTemplate模板){
    返回参数->{
    IntStream.range(0,2).forEach(i->template.send(“mytopic”,“foo”+i.getBytes());
    //等待侦听器启动
    这个.闩锁.等待(10,时间单位.秒);
    System.out.println(“关闭”);
    };
    }
    @豆子
    公共SmartLifecycle bindingFixer(BindingService BindingService){
    返回新的SmartLifecycle(){
    @凌驾
    公共int getPhase(){
    返回Integer.MAX_值;
    }
    @凌驾
    公共停车场(){
    //无操作
    }
    @凌驾
    公开作废开始(){
    @抑制警告(“未选中”)
    映射inputBinding=((列表)新的DirectFieldAccessor(inputBinding)
    .getPropertyValue(“lifecycle.messageListenerContainer”))
    .getContainerProperties().setShutdownTimeout(30_000L);
    }
    @凌驾
    公共布尔值正在运行(){
    返回false;
    }
    @凌驾
    公共无效停止(可运行回调){
    callback.run();
    }
    @凌驾
    公共布尔值isAutoStartup(){
    返回true;
    }
    };
    }
    }
    
    我只是想说明一下,我使用的是Kafka v1.1.6,我没有使用spring Kafka(而是使用spring cloud stream,我想它在某种程度上使用了它)。我们计划在不久的将来(几个月后)升级到spring boot 2(无论它的最新版本是什么),但不幸的是我们现在无法做到。如果springcloudstream不允许我们配置该属性,那么还有其他方法可以执行正常关闭吗?可能使用另一种机制或自定义解决方案?不管怎样,您都需要覆盖流拉入的版本。使用start.spring.io创建的新1.5启动应用程序会自动执行此操作。我今天休息。我将试着看看下个星期是否有工作;我找到了一份工作——不过有点像黑客。请看编辑。谢谢Gary-我将用我的代码测试它,a将返回报告