安全关闭kafka使用者

时间:2018-10-05 11:19:40

标签: hazelcast spring-kafka

我正在使用spring-kafka 3.1.6和hazelcast 3.7.4。

关闭我的应用程序时,好像hazelcast在我的kafka使用者面前关闭了。

因此导致错误

nested exception is org.springframework.transaction.CannotCreateTransactionException: Could not open JPA EntityManager for transaction; nested exception is com.hazelcast.core.HazelcastInstanceNotActiveException: Hazelcast instance is not active!; nested exception is org.springframework.transaction.CannotCreateTransactionException: Could not open JPA EntityManager for transaction; nested exception is com.hazelcast.core.HazelcastInstanceNotActiveException: Hazelcast instance is not active!

org.apache.kafka.common.errors.WakeupException: null
at org.apache.kafka.clients.consumer.internals.ConsumerNetworkClient.maybeTriggerWakeup(ConsumerNetworkClient.java:422)
at org.apache.kafka.clients.consumer.internals.ConsumerNetworkClient.poll(ConsumerNetworkClient.java:245)
at org.apache.kafka.clients.consumer.internals.ConsumerNetworkClient.poll(ConsumerNetworkClient.java:208)

我的使用者配置了RetryTemplate。

org.springframework.context.support.DefaultLifecycleProcessor   Failed to shut down 1 bean with phase value 2147483547 within timeout of 30000: [org.springframework.kafka.config.internalKafkaListenerEndpointRegistry]

有人可以通过让hazelcast等待kafka容器停止来帮助我正常关机吗?

谢谢

修改

KafkaContainer和HazelcastInstance都是由spring处理的bean。

HazelcastInstance是手动创建的(不使用默认的springboot自动配置):

@PreDestroy
public void destroy() {
    LOGGER.info("Closing Hazelcast");
    Hazelcast.shutdownAll();
}

@Bean
public HazelcastInstance hazelcastInstance() {
    LOGGER.debug("Configuring Hazelcast");
    Config config = new Config();
    ...

还有Kafka容器:

@Bean(name = "kafkaListenerContainerFactory")
public ConcurrentKafkaListenerContainerFactory<Key, Value> kafkaListenerContainerFactory() {
    ConcurrentKafkaListenerContainerFactory<Key, Value> factory =
            new ConcurrentKafkaListenerContainerFactory<>();
    factory.setConsumerFactory(new DefaultKafkaConsumerFactory<>(consumerConfigs()));
    factory.setRetryTemplate(retryTemplate());
    factory.getContainerProperties().setAckOnError(false);
    factory.getContainerProperties().setAckMode(AbstractMessageListenerContainer.AckMode.RECORD);
    factory.getContainerProperties().setErrorHandler(new DefaultErrorHandler());
    return factory;
}

编辑2:

我正在将应用程序复制3次。所有3个副本已同时关闭。

这是1个副本的关机日志历史记录:

1)18:14:54.427“ ContextClosedEvent”春季事件已被组件捕获并记录

2)18:14:54.441 org.apache.kafka.common.errors.WakeupException:null

3)18:14:55.951 com.hazelcast.core.HazelcastInstanceNotActiveException:Hazelcast实例未激活!

4)从18:14:55.951到18:15:23.103重复3)19次

5)18:15:24.441在30000的超时时间内无法关闭1个相位值为2147483547的bean:[org.springframework.kafka.config.internalKafkaListenerEndpointRegistry]

6)18:15:24.537关闭Hazelcast

2 个答案:

答案 0 :(得分:1)

如果Kafka消费者bean不直接依赖于Hazelcast bean,则可以使用bean定义的depends-on属性在bean之间定义一个顺序(在初始化和销毁​​期间)。喜欢;

<bean id="kafka-consumer" class="KafkaConsumerClassName" depends-on="hazelcast"/>
<bean id="hazelcast" class="HazelcastInstance" />

在这种情况下,将在 Kafka消费者Bean之前创建并初始化Hazelcast bean,并在 Kafka消费者Bean之后销毁它。

请参阅Spring参考手册中的Using depends-on部分。

答案 1 :(得分:0)

这对于基于客户端的安装程序可能是错误的线程,但对于基于嵌入的安装程序来说可能是错误的线程,在这里对我有用。

将此属性设置为false,

hazelcast.shutdownhook.enabled = false

hazelcast.shutdownhook.enabled = true

启用Hazelcast关机钩子线程。启用此功能后, 线程终止Hazelcast实例,而无需等待关机 优雅地。

默认情况下,此设置为true。更多info

帮助我不要强行杀死榛子广播,但我不得不打电话给hazelcastInstance.shutdown() 明确