自己在使用Spring Kafka 的消费者消费消息的时候的实践总结:

接口 KafkaDataListener 是spring-kafka提供的一个供消费者接受消息的顶层接口,也是一个空接口;
public interface KafkaDataListener<T> {} 对于消费端接收消息的时候,spring-kafka的设计思路是,提供一个顶层接口,提供两个子类,一个子类是自动提交offset的,另一个子类是手动提交offset的.
无论是自动提交offset还是手动提交offset,又各分为两种,一种是一次只处理一条消息,另一种是一次可以处理一批消息. 该 KafkaDataListener 顶层接口有两个实现类:GenericMessageListener 和 GenericAcknowledgingMessageListener,
二者的区别是,前者是自动提交offset,后者是手动提交offset。 1、 GenericMessageListener
该接口是自动提交offset,它的onMessage方法的参数只有一个,就是传递过来的一条消息;
public interface GenericMessageListener<T> extends KafkaDataListener<T> {void onMessage(T data);}
这个接口又有两个子接口:MessageListener 和 BatchMessageListener
这两个接口也都是空接口,二者的区别是,前者一次只处理一条消息,后者一次处理一批消息. //一次处理一条消息
//消费者如果实现该接口的话,如果配置中设置max.poll.records参数大于1的话是无效的,因为它一次只处理一条消息
public interface MessageListener<K, V> extends GenericMessageListener<ConsumerRecord<K, V>> {}
//一次可以处理一批消息,每一批次的消息总条数是随机的,但可以在消费者的配置中设置一个最大值(max.poll.records,
//比如设置了最大拉取的消息条数为100,那么onMessage方法每次接受到的消息条数是随机的,但最大不会超过100)
public interface BatchMessageListener<K, V> extends GenericMessageListener<List<ConsumerRecord<K, V>>> {} 2、 GenericAcknowledgingMessageListener
该接口是手动提交offset,它的onMessage方法的参数有两个,第一个是传递过来的一条消息,第二个参数是用于提交offset的对象
public interface GenericAcknowledgingMessageListener<T> extends KafkaDataListener<T> {void onMessage(T data, Acknowledgment acknowledgment);} 这个接口也有两个子接口:AcknowledgingMessageListener 和 BatchAcknowledgingMessageListener,这两个接口也都是空接口.
//一次只处理一条消息,并手动提交offset,需要在消费者的配置中设置<property name="ackMode" value="MANUAL_IMMEDIATE"/>
public interface AcknowledgingMessageListener<K, V> extends GenericAcknowledgingMessageListener<ConsumerRecord<K, V>> {}
//一次处理一批消息,处理完这一批消息之后,在批量提交offset,需要在消费者的配置中设置<property name="ackMode" value="MANUAL"/>
public interface BatchAcknowledgingMessageListener<K, V> extends GenericAcknowledgingMessageListener<List<ConsumerRecord<K, V>>> {}

下面的消费者继承的是MessageListener这个监听器,就是一次处理一条消息,而且是自动提交offset:

 import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.xxxxxx.consumer.dto.FriendRelationDto;
import com.xxxxxx.consumer.dto.MessageDto;
import com.xxxxxx.consumer.service.FriendRelationService;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.listener.MessageListener;
import org.springframework.stereotype.Service;
import java.io.IOException; /**
* Created by SYJ on 2017/3/21.
*/
@Service
public class ConsumerService implements MessageListener<Integer, String> { private static final Logger logger = LoggerFactory.getLogger(ConsumerService.class);
@Autowired
private FriendRelationService friendRelationService; /**
* 消息监听方法
* @param record
*/
@Override
public void onMessage(ConsumerRecord<Integer, String> record) {
logger.info("Before receiving:" + record.toString());
String value = record.value();
MessageDto<FriendRelationDto> message = JSON.parseObject(value, new TypeReference<MessageDto<FriendRelationDto>>(){});
try {
friendRelationService.process(message.getData());
} catch (IOException e) {
e.printStackTrace();
}
}
}

下面的消费者实现的BatchMessageListener这个监听器,就是一次接受一批消息,消息的数量是随机的,但最大不会超过"max.poll.records"参数配置的数量:

 import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.xxxxxx.consumer.dto.FriendRelationDto;
import com.xxxxxx.consumer.dto.MessageDto;
import com.xxxxxx.consumer.service.FriendRelationService;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.listener.BatchMessageListener;
import org.springframework.stereotype.Service; import java.io.IOException;
import java.util.List; /**
* Created by SYJ on 2017/3/21.
*/
@Service
public class ConsumerService implements BatchMessageListener<Integer, String> { private static final Logger logger = LoggerFactory.getLogger(ConsumerService.class);
@Autowired
private FriendRelationService friendRelationService; @Override
public void onMessage(List<ConsumerRecord<Integer, String>> recordList) {
for (ConsumerRecord<Integer, String> record : recordList) {
logger.info("Before receiving:" + record.toString());
String value = record.value();
MessageDto<FriendRelationDto> message = JSON.parseObject(value, new TypeReference<MessageDto<FriendRelationDto>>(){});
try {
friendRelationService.process(message.getData());
} catch (IOException e) {
e.printStackTrace();
}
} }
}

下面的消费者实现的是AcknowledgingMessageListener这个监听器,它的特点是一次接收一条消息,可以通过acknowledgment来手动提交offset,需要在消费者的配置中指定<property name="ackMode" value="MANUAL_IMMEDIATE"/>:

 import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.xxxxxx.consumer.dto.FriendRelationDto;
import com.xxxxxx.consumer.dto.MessageDto;
import com.xxxxxx.consumer.service.FriendRelationService;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.listener.AcknowledgingMessageListener;
import org.springframework.kafka.support.Acknowledgment;
import org.springframework.stereotype.Service; import java.io.IOException; /**
* Created by SYJ on 2017/3/21.
*/
@Service
public class ConsumerService implements AcknowledgingMessageListener<Integer, String> { private static final Logger logger = LoggerFactory.getLogger(ConsumerService.class);
@Autowired
private FriendRelationService friendRelationService; @Override
public void onMessage(ConsumerRecord<Integer, String> record, Acknowledgment acknowledgment) {
logger.info("Before receiving:" + record.toString());
String value = record.value();
MessageDto<FriendRelationDto> message = JSON.parseObject(value, new TypeReference<MessageDto<FriendRelationDto>>(){});
try {
friendRelationService.process(message.getData());
logger.info("===========开始提交offset=============");
acknowledgment.acknowledge();//提交offset
logger.info("===========已经提交offset=============");
} catch (IOException e) {
e.printStackTrace();
}
}
}

下面的消费者实现的是BatchAcknowledgingMessageListener这个监听器,它的特点是一次可以处理一批消息,并且可以在处理完这一批消息之后提交offset,需要在消费者的配置文件中配置"max.poll.records"参数指定本批消息可以达到的最大值,并指定<property name="ackMode" value="MANUAL"/>:

 import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.xxxxxx.consumer.dto.FriendRelationDto;
import com.xxxxxx.consumer.dto.MessageDto;
import com.xxxxxx.consumer.service.FriendRelationService;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.listener.BatchAcknowledgingMessageListener;
import org.springframework.kafka.support.Acknowledgment;
import org.springframework.stereotype.Service; import java.io.IOException;
import java.util.List; /**
* Created by SYJ on 2017/3/21.
*/
@Service
public class ConsumerService implements BatchAcknowledgingMessageListener<Integer, String> { private static final Logger logger = LoggerFactory.getLogger(ConsumerService.class);
@Autowired
private FriendRelationService friendRelationService; @Override
public void onMessage(List<ConsumerRecord<Integer, String>> recordList, Acknowledgment acknowledgment) {
logger.info("Before receiving:" + recordList.toString());
logger.info("本次消息总数:" + recordList.size());
for (ConsumerRecord<Integer, String> record : recordList) {
String value = record.value();
MessageDto<FriendRelationDto> message = JSON.parseObject(value, new TypeReference<MessageDto<FriendRelationDto>>() {
});
try {
friendRelationService.process(message.getData());
} catch (IOException e) {
e.printStackTrace();
}
}
logger.info("===========开始提交offset=============");
acknowledgment.acknowledge();//提交offset
logger.info("===========已经提交offset=============");
}
}

下面是spring-kafka消费端的配置文件示例:

 <?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="consumerProperties" class="java.util.HashMap">
<constructor-arg>
<map>
<entry key="bootstrap.servers" value="${bootstrap.servers}"/>
<!-- 指定消费组名 -->
<entry key="group.id" value="friend-group"/>
<entry key="enable.auto.commit" value="false"/>
<entry key="auto.commit.interval.ms" value="1000"/>
<entry key="session.timeout.ms" value="15000"/>
<!-- 当使用批量处理消息的时候,每次onMessage方法获取到的消息总条数虽然是随机的,但是不会超过此最大值 -->
<entry key="max.poll.records" value="50"/>
<entry key="key.deserializer" value="org.apache.kafka.common.serialization.IntegerDeserializer"/>
<!--<entry key="key.deserializer" value="org.apache.kafka.common.serialization.StringDeserializer"/>-->
<entry key="value.deserializer" value="org.apache.kafka.common.serialization.StringDeserializer"/>
</map>
</constructor-arg>
</bean> <bean id="consumerFactory" class="org.springframework.kafka.core.DefaultKafkaConsumerFactory">
<constructor-arg>
<ref bean="consumerProperties"/>
</constructor-arg>
</bean> <!-- 消费消息的服务类 -->
<bean id="messageListernerConsumerService" class="com.xxxxxxx.consumer.ConsumerService"/> <!-- 消费者容器配置信息 -->
<bean id="containerProperties" class="org.springframework.kafka.listener.config.ContainerProperties">
<constructor-arg value="friend"/>
<!--<constructor-arg>
<list>
<value>zptopic</value>
<value>ssmk</value>
<value>friend</value>
</list>
</constructor-arg>-->
<property name="messageListener" ref="messageListernerConsumerService"/> <!-- 提交offset,批量提交 -->
<property name="ackMode" value="MANUAL"/>
<!-- 提交offset的方式,处理完一条消息就立即提交 -->
<!--<property name="ackMode" value="MANUAL_IMMEDIATE"/>-->
</bean> <!-- 单线程消息监听容器,每启动一个消费者客户端,只会开启一个线程来消费 -->
<!--<bean id="messageListenerContainer" class="org.springframework.kafka.listener.KafkaMessageListenerContainer" init-method="doStart">
<constructor-arg ref="consumerFactory"/>
<constructor-arg ref="containerProperties"/>
</bean>--> <!-- 多线程消息监听容器,每启动一个消费者客户端,可以开启多个线程,开启多少个线程自己可以通过concurrency来指定 -->
<bean id="messageListenerContainer" class="org.springframework.kafka.listener.ConcurrentMessageListenerContainer" init-method="doStart">
<constructor-arg ref="consumerFactory"/>
<constructor-arg ref="containerProperties"/>
<property name="concurrency" value="5"/>
</bean> </beans>

关于SpringKafka消费者的几个监听器:[一次处理单条消息和一次处理一批消息]以及[自动提交offset和手动提交offset]的更多相关文章

  1. kafka原理和实践(四)spring-kafka消费者源码

    系列目录 kafka原理和实践(一)原理:10分钟入门 kafka原理和实践(二)spring-kafka简单实践 kafka原理和实践(三)spring-kafka生产者源码 kafka原理和实践( ...

  2. spring-kafka手动提交offset

    <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.sp ...

  3. Spring-Kafka —— 实现批量消费和手动提交offset

    spring-kafka的官方文档介绍,可以知道自1.1版本之后, @KafkaListener开始支持批量消费,只需要设置batchListener参数为true 把application.yml中 ...

  4. Kafka消费者手动提交消息偏移

    生产者每次调用poll()方法时,它总是返回由生产者写入Kafka但还没有消费的消息,如果消费者一致处于运行状态,那么分区消息偏移量就没什么用处,但是如果消费者发生崩溃或者有新的消费者加入群组,就会触 ...

  5. Kafka权威指南 读书笔记之(四)Kafka 消费者一一从 Kafka读取数据

    KafkaConsumer概念 消费者和消费者群组 Kafka 消费者从属于消费者群组.一个群组里的消费者订阅的是同一个主题,每个消费者接收主题一部分分区的消息. 往群组里增加消费者是横向伸缩消费能力 ...

  6. 初始 Kafka Consumer 消费者

    温馨提示:整个 Kafka 专栏基于 kafka-2.2.1 版本. 1.KafkaConsumer 概述 根据 KafkaConsumer 类上的注释上来看 KafkaConsumer 具有如下特征 ...

  7. Kafka系列3:深入理解Kafka消费者

    上面两篇聊了Kafka概况和Kafka生产者,包含了Kafka的基本概念.设计原理.设计核心以及生产者的核心原理.本篇单独聊聊Kafka的消费者,包括如下内容: 消费者和消费者组 如何创建消费者 如何 ...

  8. 深入了解Kafka【四】消费者的Offset管理

    1.Offset Topic Consumer通过提交Offset来记录当前消费的最后位置,以便于消费者发生崩溃或者有新的消费者加入消费者组,而引发的分区再均衡操作,每个消费者可能会分到不同的分区.我 ...

  9. kafka知识点详解

    第一部分:kafka概述 一.定义(消息引擎系统) 一句话概括kafka的核心功能就是:高性能的消息发送与高性能的消息消费. kafka刚推出的时候是以消息引擎的身份出现的,它具有强大的消息传输效率和 ...

随机推荐

  1. NSObject协议中方法:description 和 debugDescription

    description基本概念 1.NSLog(@"%@", objectA);这会自动调用objectA的description方法来输出ObjectA的描述信息. 2.desc ...

  2. 双链表实现Queue

    算法导论第10章的东西,感觉用双链表真心简单,就是有点浪费空间,但是时间复杂度O(1): #include <stdio.h> struct LinkNode { LinkNode(): ...

  3. httpd: Could not reliably determine the server's fully qualified domain name(转)

    ttpd: Could not reliably determine the server's fully qualified domain name, using 127.0.0.1 for Ser ...

  4. 【Hibernate】hibernate框架的搭建

    1, Hibernate 是什么 Hibernate是java应用程序与数据库交互的开发的框架. Hibernate是一个开源,轻量级的ORM(对象关系映射)工具. 2,Hibernate框架的优点 ...

  5. 【Servlet】Java Serlvet Listener 监听器

    Listener监听器 Servlet规范中定义的一种特殊的组件,用来监听Servlet容器产生的事件并进行相应的处理 容器产生的事件分类 - 生命周期相关的事件 - 设置和删除Attribute数据 ...

  6. iOS 图标

    iOS icon是一件很头疼的事情 大致多少张呢,忘记了,下面开发者中心给的一个文档,自己捋捋有多少张 180934.jpg 幸亏不是自己画的,不然要骂姥姥,但是多数的UI是妹子啊,让人家做人家会说: ...

  7. Windows 重装系统-用户转移User和Program Files 文件夹

    原文地址:https://blog.csdn.net/sinat_38799924/article/details/74059037 重装系统时为了让系统数据保持可用我们需要做一些备份处理.比如用户数 ...

  8. 【Algorithm】冒泡排序

    一. 算法描述 冒泡排序思想:依次比较相邻的数据,将小数据放在前,大数据放在后:即第一趟先比较第1个和第2个数,大数在后,小数在前,再比较第2个数与第3个数,大数在后,小数在前,以此类推则将最大的数& ...

  9. 下载远程(第三方服务器)文件、图片,保存到本地(服务器)的方法、保存抓取远程文件、图片 将图片的二进制字节字符串在HTML页面以图片形式输出 asp.net 文件 操作方法

    下载远程(第三方服务器)文件.图片,保存到本地(服务器)的方法.保存抓取远程文件.图片   将一台服务器的文件.图片,保存(下载)到另外一台服务器进行保存的方法: 1 #region 图片下载 2 3 ...

  10. SharePoint 2013 Step by Step——使用自定义的List Template

    Overview 对于企业员工来说,"扁平结构"的LIST是日常操作中经常使用到的,LIST的好处是方便数据的录入以及数据的整理分析,尤其是Quick Edit功能,可以实现快速编 ...