启动上下文之前如何在内存中加载压缩主题

时间:2019-05-07 07:39:23

标签: spring spring-boot spring-kafka

我在kafka中使用了一个压缩的主题,该主题在应用程序启动时加载到HashMap中。 然后,我正在听一个普通的消息主题,并使用从压缩的主题构造的HashMap处理它们。

在开始收听其他主题之前,如何确保完全阅读压缩的主题并完全初始化HashMap? (与RestControllers相同)

2 个答案:

答案 0 :(得分:1)

实施SmartLifecycle并将地图加载到start()中。确保phase早于需要映射的任何其他对象。

答案 1 :(得分:0)

这是一个老问题,我知道,但我想提供一个更完整的解决方案代码示例,当我自己解决这个问题时,我最终得到了这个解决方案。

这个想法是,就像加里在他自己的答案的评论中提到的那样,在初始化期间使用侦听器不是正确的 - 之后会出现。然而,Garry 的 SmartLifecycle 想法的替代方案是 InitializingBean,我发现它实现起来并不复杂,因为它只是一种方法:afterPropertiesSet()

@Slf4j
@Configuration
@RequiredArgsConstructor
public class MyCacheInitializer implements InitializingBean {

    private final ApplicationProperties applicationProperties; // A custom ConfigurationProperties-class
    private final KafkaProperties kafkaProperties;
    private final ConsumerFactory<String, Bytes> consumerFactory;
    private final MyKafkaMessageProcessor messageProcessor;

    @Override
    public void afterPropertiesSet() {
        String topicName = applicationProperties.getKafka().getConsumer().get("my-consumer").getTopic();
        Duration pollTimeout = kafkaProperties.getListener().getPollTimeout();

        try (Consumer<String, Bytes> consumer = consumerFactory.createConsumer()) {
            consumer.subscribe(List.of(topicName));

            log.info("Starting to cache the contents of {}", topicName);

            ConsumerRecords<String, Bytes> records;

            do {
                records = consumer.poll(pollTimeout);
                records.forEach(messageProcessor::process);
            } while (!records.isEmpty());
        }

        log.info("Completed caching {}", topicName);
    }
}

为简洁起见,我使用 Lombok 的 @Slf4j@RequiredArgsConstructor 注释,但这些注释可以轻松替换。 ApplicationProperties 类只是我获取我感兴趣的主题名称的方式。它可以用其他东西替换,但我的实现使用 Lombok 的 @Data 注释,看起来像这样:

@Data
@Configuration
@ConfigurationProperties(prefix = "app")
public class ApplicationProperties {

    private Kafka kafka = new Kafka();

    @Data
    public static class Kafka {
        private Map<String, KafkaConsumer> consumer = new HashMap<>();
    }

    @Data
    public static class KafkaConsumer {
        private String topic;
    }
}