1、准备工作
工欲善其事必先利其器,首先安装kafka,我们这里使用docker容器进行安装,这里可参考之前的一篇博文docker快速部署pg/redis/kafka/es等中间件
说明:文中提到的所有代码都在我的github项目里面,项目地址:https://github.com/chenxiangweifeng/study
搭建好kafka服务端之后。首先在pom文件中引入kafka的依赖:
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka</artifactId>
<version>2.2.12.RELEASE</version>
</dependency>
<dependency>
<groupId>org.apache.kafka</groupId>
<artifactId>kafka-clients</artifactId>
<version>2.2.0</version>
</dependency>
springboot的配置文件中配置上kafka的连接地址以及生产者和消费者序列化方式如下:
kafka:
bootstrap-servers: 192.168.28.200:9092
consumer:
group-id: group_study
auto-offset-reset: earliest
key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
value-deserializer: org.apache.kafka.common.serialization.StringDeserializer
producer:
key-serializer: org.apache.kafka.common.serialization.StringSerializer
value-serializer: org.springframework.kafka.support.serializer.JsonSerializer
acks: all
retries: 3
2、消息发送
我们使用kafkaTemplate发送消息,
@ApiOperation(value = "向kafka中发送简单字符串信息")
@RequestMapping(value = "/testSendSimpleMessage", method = RequestMethod.POST)
public String testSendSimpleMessage(@RequestParam("msg") String msg) {
KafkaTemplate.send(KafkaTopicEnum.SIMPLE_MSG.code,msg);
return "发送消息成功";
}
本项目引入了swagger,可以方便的直接进行接口测试:
通过kafka Tools工具我们可以查询到该topic内的消息,证明消息发送成功。
除了发送这种简单的消息之外,我们还可以向kafka中发送Java中的一个对象构成的消息:如下:
@ApiOperation(value = "向kafka中发送一个对象消息")
@RequestMapping(value = "/testSendMessage", method = RequestMethod.POST)
public String testSendMessage(@RequestParam("personType") Integer personType) {
Person p = new Person();
p.setUserName("赵敏");
p.setPersonType(personType);
p.setPhoneNum("18018576105");
// 向特定的topic发送消息
KafkaTemplate.send(KafkaTopicEnum.TEST_PERSON_MESSAGE.code,p);
return "发送一个对象消息成功";
}
通过swagger向该topic内发送一个对象消息:
通过kafka Tool查看到该消息是通过我们设置的json序列化方式,序列化为一个json字符串
3、消息接收
消费者消费消息是通过监听特定的topic来消费消息
@KafkaListener(topics = "simple-msg",containerFactory = "ackContainerFactory")
public void receiveSimpleKafkaMsg(ConsumerRecord<?,?> consumerRecord, Acknowledgment acknowledgment){
System.out.println("监听服务接收到的简单字符串消息是======"+consumerRecord.value().toString());
System.out.println("=================== end =================");
acknowledgment.acknowledge();
}
result:
监听服务接收到的简单字符串消息是======"hello"
=================== end =================
监听服务接收到的简单字符串消息是======"world"
=================== end =================
监听服务接收到的简单字符串消息是======"kafka"
=================== end =================
当有两个业务想同时消费这一批消息的时候,注意需使用广播模式,设置多个group,通过不同的groupId进行区分,比如我们这里通过两个消费组同时消费对象消息:可以发现,该消息被两个组的消费者各消费一次,达到了广播的效果。
@KafkaListener(topics = "test-person-message",groupId ="serverGroup1",containerFactory = "ackContainerFactory")
public void receiveKafkaMsg1(ConsumerRecord<?,?> consumerRecord, Acknowledgment acknowledgment){
System.out.println("监听服务接收到的消息是:111111111111111111111111");
Person person = JSON.parseObject(consumerRecord.value().toString(), Person.class);
System.out.println(consumerRecord.value().toString());
System.out.println("接收到的person是:"+person);
System.out.println("人员类型是:"+person.getPersonType()+"人员姓名是:"+person.getUserName());
System.out.println("=================== end =================");
}
@KafkaListener(topics = "test-person-message",groupId ="serverGroup2",containerFactory = "ackContainerFactory" )
public void receiveKafkaMsg2(ConsumerRecord<?,?> consumerRecord, Acknowledgment acknowledgment){
System.out.println("监听服务接收到的消息是:22222222222222222222222");
Person person = JSON.parseObject(consumerRecord.value().toString(), Person.class);
System.out.println("接收到的person是:"+person);
System.out.println("人员类型是:"+person.getPersonType()+"人员姓名是:"+person.getUserName());
System.out.println("=================== end =================");
/**
* ack 提交掉 监听服务222 已经被ack提交掉,历史消息不会被再次消费
*/
acknowledgment.acknowledge();
}
result:
监听服务接收到的消息是:111111111111111111111111
{"id":null,"userName":"赵敏","phoneNum":"18018576105","age":null,"createTime":null,"finish":null,"addr":null,"height":null,"introduction":null,"personType":22}
接收到的person是:Person(id=null, userName=赵敏, phoneNum=18018576105, age=null, createTime=null, finish=null, addr=null, height=null, introduction=null, personType=22)
人员类型是:22人员姓名是:赵敏
=================== end =================
监听服务接收到的消息是:22222222222222222222222
接收到的person是:Person(id=null, userName=赵敏, phoneNum=18018576105, age=null, createTime=null, finish=null, addr=null, height=null, introduction=null, personType=22)
人员类型是:22人员姓名是:赵敏
=================== end =================