Kafka学习笔记
Kafka学习笔记
一、Windows下配置kafka环境
1.下载
https://www.apache.org/dyn/closer.cgi?path=/kafka/2.8.0/kafka_2.12-2.8.0.tgz
如果在windows下kafka出现问题,将kafka目录中的kafka-log删除掉,重启即可
2.修改配置文件
zookeeper.properties
修改zookeeper数据文件位置
#####################################################################
dataDir=C:/Users/ANTIA1/Desktop/DATA/zookeeper
server.properties
#####################################################################
log.dirs=C:/Users/ANTIA1/Desktop/DATA/kafka-logs
3.启动
启动 zookeeper
D:\Dev\Environment\kafka_2.12-2.8.0> bin\windows\zookeeper-server-start.bat config\zookeeper.properties
启动 kafka
D:\Dev\Environment\kafka_2.12-2.8.0> bin\windows\kafka-server-start.bat config\server.properties
使用 kafka 命令工具
--replication-factor [] 副本的数量
--partitions [] 分区的数量
--topic [] 主题的名称
D:\Dev\Environment\kafka_2.12-2.8.0\bin\windows>kafka-topics.bat --create --bootstrap-server localhost:9092 --replication-factor 1 --partitions 1 --topic test
Created topic test. 创建成功
查看主题是否创建成功
D:\Dev\Environment\kafka_2.12-2.8.0\bin\windows>kafka-topics.bat --list --bootstrap-server localhost:9092
test
生产消息
D:\Dev\Environment\kafka_2.12-2.8.0\bin\windows>kafka-console-producer.bat --broker-list localhost:9092 --topic test
>hello
>world
>kafka
消费消息
D:\Dev\Environment\kafka_2.12-2.8.0\bin\windows>kafka-console-consumer.bat --bootstrap-server localhost:9092 --topic test --from-beginning
hello
world
kafka
123
hahah
二、SpringBoot整合Kafka
1.引入依赖
pom.xml
<!-- https://mvnrepository.com/artifact/org.springframework.kafka/spring-kafka -->
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka</artifactId>
</dependency>
2.配置Kafka
application.properties
#KafkaProperties
spring.kafka.boostrap-servers=localhost:9092
spring.kafka.consumer.group-id=community-consumer-group 对应kafka包中的 config/consumer.properties
spring.kafka.consumer.enable-auto-commit=true
spring.kafka.consumer.auto-commit-interval=3000
3.实例演示
package com.zhuantai.community;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Component;
/**
* @author ANTIA1
* @date 2021/7/28 23:58
*/
@SpringBootTest
public class KafkaTests {
@Autowired
KafkaProducer producer;
@Test
public void testKafka() throws InterruptedException {
//生产消息
producer.sendMessage("test","你好");
producer.sendMessage("test","在吗");
Thread.sleep(1000*10);
}
}
/**
* 生产者Bean
*/
@Component
class KafkaProducer {
@Autowired
private KafkaTemplate kafkaTemplate;
public void sendMessage(String topic,String content){
kafkaTemplate.send(topic,content);
}
}
/**
* 消费者Bean
*/
@Component
class KafkaConsumer {
@KafkaListener(topics = {"test"})//监听指定的topic
public void handleMessage(ConsumerRecord record){
System.out.println(record.value());//打印消息中的值
}
}
运行结果
三、发送系统通知
1.编写实体类
方便封装数据
Event.java
package com.zhuantai.community.entity;
import java.util.HashMap;
import java.util.Map;
/**
* @author ANTIA1
* @date 2021/7/29 0:16
*/
public class Event {
private String topic;
private int userId;//事件触发者
private int entityType;
private int entityId;
private int entityUserId;//实体的作者
private Map<String,Object> data = new HashMap<>();
public String getTopic() {
return topic;
}
public Event setTopic(String topic) {
this.topic = topic;
return this;
}
public int getUserId() {
return userId;
}
public Event setUserId(int userId) {
this.userId = userId;
return this;
}
public int getEntityType() {
return entityType;
}
public Event setEntityType(int entityType) {
this.entityType = entityType;
return this;
}
public int getEntityId() {
return entityId;
}
public Event setEntityId(int entityId) {
this.entityId = entityId;
return this;
}
public int getEntityUserId() {
return entityUserId;
}
public Event setEntityUserId(int entityUserId) {
this.entityUserId = entityUserId;
return this;
}
public Map<String, Object> getData() {
return data;
}
public Event setData(String key,Object value) {
this.data.put(key,value);
return this;
}
}
2.消息生产者
EventProducer.java
package com.zhuantai.community.event;
import com.alibaba.fastjson.JSONObject;
import com.zhuantai.community.entity.Event;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Component;
/**
* 消息生产者
* @author ANTIA1
* @date 2021/7/29 0:23
*/
@Component
public class EventProducer {
@Autowired
private KafkaTemplate kafkaTemplate;
//处理事件
public void fireEvent(Event event){
//将事件发布到指定的主题
kafkaTemplate.send(event.getTopic(), JSONObject.toJSONString(event));
}
}
3.消息消费者
EventConsumer.java
package com.zhuantai.community.event;
import com.alibaba.fastjson.JSONObject;
import com.zhuantai.community.entity.Event;
import com.zhuantai.community.entity.Message;
import com.zhuantai.community.service.MessageService;
import com.zhuantai.community.uitls.CommunityConstant;
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.annotation.KafkaListener;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/**
* 消息消费者
* @author ANTIA1
* @date 2021/7/29 0:27
*/
@Component
public class EventConsumer implements CommunityConstant {
private static final Logger LOGGER = LoggerFactory.getLogger(EventConsumer.class);
@Autowired
private MessageService messageService;
@KafkaListener(topics = {TOPIC_COMMENT,TOPIC_LIKE,TOPIC_FOLLOW})
public void handleCommentMessage(ConsumerRecord record){
if (record == null || record.value() == null ){
LOGGER.error("消息内容为空!");
return;
}
Event event = JSONObject.parseObject(record.value().toString(),Event.class);
if (event == null ){
LOGGER.error("消息格式错误!");
return;
}
// 发送站内通知
Message message = new Message();
message.setFromId(SYSTEM_USER_ID);
message.setToId(event.getEntityUserId());
message.setConversationId(event.getTopic());
message.setCreateTime(new Date());
Map<String,Object> content = new HashMap<>();
content.put("userId",event.getUserId());//事件是谁触发的
content.put("entityType",event.getEntityType());//事件实体类型
content.put("entityId",event.getEntityId());//事件实体ID
if(!event.getData().isEmpty()){
for(Map.Entry<String,Object> entry : event.getData().entrySet()){
content.put(entry.getKey(),entry.getValue());
}
}
message.setContent(JSONObject.toJSONString(content));
messageService.addMessage(message);
}
}
4.调用
package com.zhuantai.community.controller;
import com.zhuantai.community.annotation.LoginRequired;
import com.zhuantai.community.entity.Comment;
import com.zhuantai.community.entity.DiscussPost;
import com.zhuantai.community.entity.Event;
import com.zhuantai.community.event.EventProducer;
import com.zhuantai.community.service.CommentService;
import com.zhuantai.community.service.DiscussPostService;
import com.zhuantai.community.uitls.CommunityConstant;
import com.zhuantai.community.uitls.HostHolder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import java.util.Date;
/**
* @author ANTIA1
* @date 2021/7/26 17:37
*/
@Controller
@RequestMapping("/comment")
public class CommentController implements CommunityConstant {
@Autowired
CommentService commentService;
@Autowired
HostHolder hostHolder;
@Autowired
EventProducer producer;
@Autowired
private DiscussPostService discussPostService;
@RequestMapping(path = "/add/{discussPostId}", method = RequestMethod.POST)
public String addComment(@PathVariable("discussPostId") int discussPostId, Comment comment) {
comment.setUserId(hostHolder.getUser().getId());
comment.setStatus(0);
comment.setCreateTime(new Date());
commentService.addComment(comment);
//触发评论事件
Event event = new Event()
.setTopic(TOPIC_COMMENT)
.setUserId(hostHolder.getUser().getId())
.setEntityType(comment.getEntityType())
.setEntityId(comment.getEntityId())
.setData("postId",discussPostId);
if (comment.getEntityType() == ENTITY_TYPE_POST){//如果是给帖子做评论
DiscussPost target = discussPostService.findDiscussPostById(comment.getEntityId());
event.setEntityUserId(target.getUserId());
}else if(comment.getEntityType() == ENTITY_TYPE_COMMENT){
Comment target = commentService.findCommentById(comment.getId());
event.setEntityUserId(target.getUserId());
}
//发布消息
producer.fireEvent(event);
return "redirect:/discuss/detail/" + discussPostId;
}
}