Spring Kafka生产者/消费者样本

我的目的是演示Spring Kafka如何为原始Kafka Producer和Consumer API提供一种易于使用且对具有Spring背景的人熟悉的抽象。

示例场景

示例场景是一个简单的场景,我有一个系统,该系统生成一条消息,另一个系统对其进行处理

kafkaflow

使用Raw Kafka Producer / Consumer API的实施

首先,我使用原始的Kafka Producer和Consumer API来实现此方案。 如果您想看一下代码,可以在我的github仓库中找到它

制片人

以下设置了一个KafkaProducer实例,该实例用于向Kafka主题发送消息:

KafkaProducer<String, WorkUnit> producer 
    = new KafkaProducer<>(kafkaProps, stringKeySerializer(), workUnitJsonSerializer());

我使用了KafkaProducer构造函数的一种变体,该构造函数采用一个自定义的Serializer将域对象转换为json表示形式。

一旦有KafkaProducer实例可用,就可以将其用于向Kafka集群发送消息,这里我使用了同步版本的发送器,它等待响应返回。

ProducerRecord<String, WorkUnit> record 
                = new ProducerRecord<>("workunits", workUnit.getId(), workUnit);

RecordMetadata recordMetadata = this.workUnitProducer.send(record).get();

消费者

在消费者方面,我们创建了一个KafkaConsumer,其中包含构造函数的一种变体,其中包含一个反序列化器 ,该解串器知道如何读取json消息并将其转换为域实例:

KafkaConsumer<String, WorkUnit> consumer
= new KafkaConsumer<>(props, stringKeyDeserializer()
, workUnitJsonValueDeserializer());

一旦KafkaConsumer实例可用,就可以建立一个监听器循环,以读取一批记录,对其进行处理,并等待更多记录通过:

consumer.subscribe("workunits);

try {
    while (true) {
        ConsumerRecords<String, WorkUnit> records = this.consumer.poll(100);
        for (ConsumerRecord<String, WorkUnit> record : records) {
            log.info("consuming from topic = {}, partition = {}, offset = {}, key = {}, value = {}",
                    record.topic(), record.partition(), record.offset(), record.key(), record.value());

        }
    }
} finally {
    this.consumer.close();
}

使用Spring Kafka的实现

我在github repo中有使用Spring-kafka的实现。

制片人

Spring-Kafka提供了一个KafkaTemplate类,作为KafkaProducer上的包装器,用于将消息发送到Kafka主题:

@Bean
public ProducerFactory<String, WorkUnit> producerFactory() {
    return new DefaultKafkaProducerFactory<>(producerConfigs(), stringKeySerializer(), workUnitJsonSerializer());
}

@Bean
public KafkaTemplate<String, WorkUnit> workUnitsKafkaTemplate() {
    KafkaTemplate<String, WorkUnit> kafkaTemplate =  new KafkaTemplate<>(producerFactory());
    kafkaTemplate.setDefaultTopic("workunits");
    return kafkaTemplate;
}

需要注意的一件事是,尽管我之前实现了一个自定义的Serializer / Deserializer,以将域类型作为json发送,然后将其转换回去,但是Spring-Kafka开箱即用地为json提供了Seralizer / Deserializer。

并使用KafkaTemplate发送消息:

SendResult<String, WorkUnit> sendResult = 
    workUnitsKafkaTemplate.sendDefault(workUnit.getId(), workUnit).get();

RecordMetadata recordMetadata = sendResult.getRecordMetadata();

LOGGER.info("topic = {}, partition = {}, offset = {}, workUnit = {}",
        recordMetadata.topic(), recordMetadata.partition(), recordMetadata.offset(), workUnit);

消费者

使用者部分使用侦听器模式实现,对于已为RabbitMQ / ActiveMQ实现侦听器的任何人,应该熟悉该模式。 首先是设置侦听器容器的配置:

@Bean
public ConcurrentKafkaListenerContainerFactory<String, WorkUnit> kafkaListenerContainerFactory() {
    ConcurrentKafkaListenerContainerFactory<String, WorkUnit> factory =
            new ConcurrentKafkaListenerContainerFactory<>();
    factory.setConcurrency(1);
    factory.setConsumerFactory(consumerFactory());
    return factory;
}

@Bean
public ConsumerFactory<String, WorkUnit> consumerFactory() {
    return new DefaultKafkaConsumerFactory<>(consumerProps(), stringKeyDeserializer(), workUnitJsonValueDeserializer());
}

以及响应容器读取的消息的服务:

@Service
public class WorkUnitsConsumer {
    private static final Logger log = LoggerFactory.getLogger(WorkUnitsConsumer.class);

    @KafkaListener(topics = "workunits")
    public void onReceiving(WorkUnit workUnit, @Header(KafkaHeaders.OFFSET) Integer offset,
                            @Header(KafkaHeaders.RECEIVED_PARTITION_ID) int partition,
                            @Header(KafkaHeaders.RECEIVED_TOPIC) String topic) {
        log.info("Processing topic = {}, partition = {}, offset = {}, workUnit = {}",
                topic, partition, offset, workUnit);
    }
}

这样就避免了像设置原始使用者一样设置侦听器循环的所有复杂性,并且很好地被侦听器容器隐藏了。

结论

我已经遍历了设置批处理大小,确认的变化以及不同的API签名的许多内部信息。 我的目的只是演示使用原始Kafka API的常见用例,并展示Spring-Kafka包装器如何简化它。

如果您有兴趣进一步探索, 可以在这里找到原始生产者消费者样本,在这里可以找到 Spring Kafka

翻译自: https://www.javacodegeeks.com/2016/11/spring-kafka-producerconsumer-sample.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值