kafka 入门使用

文章介绍了ApacheKafka的基本概念和特性,包括其作为分布式流媒体平台的角色,高吞吐量、消息持久化和高可扩展性的特点。详细步骤展示了如何配置和启动Kafka及Zookeeper,以及创建主题、发送和消费消息。此外,还讲解了如何在SpringBoot应用中整合Kafka,包括配置、生产者和消费者组件的实现。
摘要由CSDN通过智能技术生成

入门

简介

kafka(发布订阅模式)是一个分布式的流媒体平台。
应用:消息系统、日志收集、用户行为追踪、流式处理。

特点

高吞吐量(处理消息能力强)、
消息持久化(硬盘顺序存储),
高可靠性(分布式),
高可拓展性。

术语

Broker(kafka集群中的服务器)、
Zookeeper(独立软件,管理集群,kafka也内置了Zookeeper)
Topic(保存消息的位置)、Partition(保存topic的分区)、Offset(消息在分区内存放的索引)
Leader Replica (主副本,可以做响应)、 Follower Replica(随从副本,只负责备份数据)

下载

https://kafka.apache.org/downloads

配置

1、修改Zookeeper.properties配置文件

# 文件保存路径
dataDir=/tmp/zookeeper

2、server.properties 配置log存放位置

log.dirs=/tmp/kafka-logs

启动(windows下)

1、首先启动Zookeeper

启动一个cmd窗口,切换到kafka的目录,输入命令

zookeeper-server-start.bat config\zookeeper.properties

2、接着启动kafka

新启动一个cmd窗口,切换到kafka的目录,输入命令

bin\windows\kafka-server-start.bat config\server.properties

3、创建主题

新启动cmd窗口,切换到kafka的bin目录下输入命令

kafka-topics.bat --create --bootstrap-server localhost:9092 --replication-factor 1 --partitions 1 --topic test

命令解释
kafka-topics.bat
–create ip 创建主题的目标。
–replication-factor 创建副本的数量
–partitions 创建分区的数量
–topic 名字 主题名字
–list ----bootstrap-server ip 查询ip服务器的主题。

4、发送消息

kafka-console-producuer.bat --broker-list localhost:9092 --topic test

–broker-list +ip 发送信息的目标

5、消费消息

kafka-console-consumer.bat --bootstrap-server localhost:9092 --topic test --from-beginning

–from-beginning 读消息从头到尾

SpringBoot整合

1、引入依赖

<dependency>  
    <groupId>org.springframework.kafka</groupId>  
    <artifactId>spring-kafka</artifactId>  
    <version>2.8.2</version>  
</dependency>

2、配置Kafka

配置server,consumer
# Kafka配置  
spring.kafka.bootstrap-servers=localhost:9092  
#消费者组id  
spring.kafka.consumer.group-id=test-consumer-group  
#是否自动提交偏移量  
spring.kafka.consumer.enable-auto-commit=true  
#多久提交一次  
spring.kafka.consumer.auto-commit-interval=3000

3、Kafka 测试

生产者

kafkaTemplate.send(topic, data);

消费者

@KafkaListener(topics={“test”})
public void handleMessage(ConsumerRecord record){}

测试用例
package com.community.windy;   
import org.apache.kafka.clients.consumer.ConsumerRecord;  
import org.junit.Test;  
import org.junit.runner.RunWith;  
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;  
import org.springframework.test.context.ContextConfiguration;  
import org.springframework.test.context.junit4.SpringRunner;  
  
@RunWith(SpringRunner.class)  
@SpringBootTest  
@ContextConfiguration(classes = WindyCommunityApplication.class)  
public class KafkaTests {  
  
    @Autowired  
    KafkaProducer kafkaProducer;  
  
    @Test  
    public void  testKafka(){  
        kafkaProducer.sendMessage("test","你好");  
        kafkaProducer.sendMessage("test","你多大");  
        try {  
            Thread.sleep(1000*10);  
        } catch (InterruptedException e) {  
            throw new RuntimeException(e);  
        }  
  
    }  
}  
  
@Component  
class KafkaProducer{  
  
    @Autowired  
    private KafkaTemplate kafkaTemplate;  
  
    public void sendMessage(String topic,String content) {  
        kafkaTemplate.send(topic,content);  
    }  
}  
  
@Component  
class KafkaConsumer{  
  
    @KafkaListener(topics = {"test"})  
    public void handleMessage(ConsumerRecord record){  
        System.out.println(record.value());  
    }  
}

4、实际使用

消息生产者
package com.community.windy.event;  
  
import com.alibaba.fastjson.JSONObject;  
import com.community.windy.entity.Event;  
import netscape.javascript.JSObject;  
import org.springframework.beans.factory.annotation.Autowired;  
import org.springframework.kafka.core.KafkaTemplate;  
import org.springframework.stereotype.Component;  
  
@Component  
public class EventProducer {  
  
    @Autowired  
    private KafkaTemplate kafkaTemplate;  
  
    //处理事件  
    public void fireEvent(Event event){  
        //将事件发送到指定的主题  
        kafkaTemplate.send(event.getTopic(), JSONObject.toJSONString(event));  
    }  
}
消息消费者
package com.community.windy.event;  
  
import com.alibaba.fastjson.JSONObject;  
import com.community.windy.entity.Event;  
import com.community.windy.entity.Message;  
import com.community.windy.service.MessageService;  
import com.community.windy.util.CommunityConstant;  
import org.apache.kafka.clients.consumer.ConsumerRecord;  
import org.apache.kafka.common.protocol.types.Field;  
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;  
  
@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());  
  
        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);  
    }  
  
  
}
控制层调用
@Autowired  
private EventProducer eventProducer;


@PostMapping(path = "add/{discussPostId}")  
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())  
            .setEntityId(comment.getEntityId())  
            .setEntityType(comment.getEntityType())  
            .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.getTargetId());  
        event.setEntityUserId(target.getUserId());  
    }  
    //发送kafka消息  
    eventProducer.fireEvent(event);  
    return "redirect:/discuss/detail/"+discussPostId;  
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值