我有一个使用Spring Cloud Stream(v1.3.0)和Kafka(v1.1.6)的spring boot(v.1.57)应用程序。我希望能够正常关闭它,即在关闭时,所有流侦听器(即,用@StreamListener注释)应:
我注意到ContainerProperties中有一个名为“ shutdownTimeout”的属性(默认设置为10000ms),所以我试图通过反射扩展ConcurrentKafkaListenerContainerFactoryConfigurer类(因为它具有@ConditionalOnMissingBean批注)来将其修改为30000。像这样:
@Slf4j
@Component
public class BehalfConcurrentKafkaListenerContainerFactoryConfigurer extends ConcurrentKafkaListenerContainerFactoryConfigurer {
@Autowired
private KafkaProperties kproperties;
@Override
public void configure(ConcurrentKafkaListenerContainerFactory<Object, Object> listenerContainerFactory,
ConsumerFactory<Object, Object> consumerFactory) {
PropertyAccessor myAccessor = PropertyAccessorFactory.forDirectFieldAccess(this);
myAccessor.setPropertyValue("properties", kproperties);
ContainerProperties containerProperties = listenerContainerFactory
.getContainerProperties();
super.configure(listenerContainerFactory, consumerFactory);
containerProperties.setShutdownTimeout(30000);
}
}
但是没有成功。还尝试将其(shutdownTimeout:30000)放在spring cloud stream活页夹设置下的application.yml中,但同样没有帮助。
有什么方法可以控制关机过程并实现我的目标吗?
答案 0 :(得分:2)
spring-kafka 1.1.x不再受支持;您应该在引导1.5.x上使用1.3.9。
当前的Boot 1.5.x版本是1.5.21。
您应该立即升级。
但是,所有这些项目都有更新的版本。
Spring Cloud Stream不使用该工厂或启动属性来创建其容器;它没有公开在容器上配置该属性的机制。
Spring Cloud Stream 2.1添加了ListenerContainerCustomizer
,它允许您通过在绑定容器上设置任何属性来自定义绑定容器。
我建议您升级到Boot 2.1.6和Spring Cloud Stream Germantown(2.2.0)。
编辑
这是一个小技巧,但是它应该可以工作,直到您可以升级到较新的流发行版为止...
@SpringBootApplication
@EnableBinding(Sink.class)
public class So56883620Application {
public static void main(String[] args) {
SpringApplication.run(So56883620Application.class, args).close();
}
private final CountDownLatch latch = new CountDownLatch(1);
@StreamListener(Sink.INPUT)
public void listen(String in) throws InterruptedException {
this.latch.countDown();
System.out.println(in);
Thread.sleep(6_000);
System.out.println("exiting");
}
@Bean
public ApplicationRunner runner(KafkaTemplate<byte[], byte[]> template) {
return args -> {
IntStream.range(0,2).forEach(i -> template.send("mytopic", ("foo" + i).getBytes()));
// wait for listener to start
this.latch.await(10, TimeUnit.SECONDS);
System.out.println("Shutting down");
};
}
@Bean
public SmartLifecycle bindingFixer(BindingService bindingService) {
return new SmartLifecycle() {
@Override
public int getPhase() {
return Integer.MAX_VALUE;
}
@Override
public void stop() {
// no op
}
@Override
public void start() {
@SuppressWarnings("unchecked")
Map<String, Binding<?>> consumers = (Map<String, Binding<?>>) new DirectFieldAccessor(bindingService)
.getPropertyValue("consumerBindings");
@SuppressWarnings("unchecked")
Binding<?> inputBinding = ((List<Binding<?>>) consumers.get("input")).get(0);
((AbstractMessageListenerContainer<?, ?>) new DirectFieldAccessor(inputBinding)
.getPropertyValue("lifecycle.messageListenerContainer"))
.getContainerProperties().setShutdownTimeout(30_000L);
}
@Override
public boolean isRunning() {
return false;
}
@Override
public void stop(Runnable callback) {
callback.run();
}
@Override
public boolean isAutoStartup() {
return true;
}
};
}
}