springboot集成kafka | 分布式消息发布和订阅系统

5 篇文章 0 订阅
4 篇文章 0 订阅

什么是 Kafka:

Kafka 是一款分布式消息发布和订阅系统,具有高性能、高吞吐量的特点。最初由 LinkedIn 公司开发,后贡献给 Apache 基金会成为顶级开源项目。

基本认识

设计目标

1.以时间复杂度为 O(1)的方式提供消息持久化能力,即使对 TB 级以上数据也能保证常数时间的访问性能。

2.高吞吐率,单机支持每秒 100k 条消息的传输。

3.支持 Kafka server 间的消息分区,及分布式消费,同时保证每个 partition 内的消息顺序传输。

4.同时支持离线数据处理和实时数据处理。

5.支持在线水平扩展(scale out)。

应用场景

行为跟踪:用于跟踪用户浏览页面、搜索及其他行为,通过发布-订阅模式实时记录到对应的 topic 中,再进行处理分析和监控。

日志收集系统:可作为日志聚合的代理,将应用程序的日志集中到 Kafka 上,然后分布导入到其他系统进行实时检索分析和离线统计数据备份等。

消息系统。

Kafka 名词解释

Broker:Kafka 集群中包含的服务器,一个或多个服务器构成 broker。Broker 端不维护数据的消费状态,直接使用磁盘进行存储,提升了性能,避免了内存复制和垃圾回收的性能损耗。

Producer:负责发布消息到 Kafka broker。

Consumer:负责从 broker 拉取(pull)数据并进行处理。

Topic:每条发布到 Kafka 集群的消息都有一个类别,即 topic。物理上不同 topic 的消息分开存储,逻辑上用户只需指定消费的 topic 即可生产或消费数据,而不必关心数据存于何处。

Partition:是物理上的概念,每个 topic 可包含一个或多个 partition,Kafka 分配的单位是 partition。

Consumer Group:每个 consumer 属于一个特定的 consumer group。可为每个 consumer 指定 group name,若不指定则属于默认的 group。每条消息只可以被 consumer group 组中的一个 consumer 消费,但可以指定多个 consumer group。

Kafka 分布式消息原理

topic 和 partition:

topic 可被视为一个逻辑上的队列。

partition 是 topic 的物理分区,每个 partition 是一个有序的队列,其中的消息都有一个连续的序列号(offset),用于唯一标识消息。

生产者消息分发:

Kafka 生产消息分发策略可自定义,默认情况下通常采用负载均衡机制随机选择分区,也可通过特定的分区函数选择分区。

消息默认的分发机制根据具体策略进行。

涉及到 metadata 类的相关操作。

消费者的消费原理:

kafaka 消息消费原理演示+测试:包括环境演示和测试等步骤,得出相应结论。

消费者分区分配策略有 rangeAssignor、roundRobinAssignor、stickyAssignor 等。

coordinator 在其中起到协调的作用。

coordinator:

确定方式有特定的算法和规则。

joinGroup 的过程包括 joinGroup、synchronizingGroupState 等步骤。

offset 的维护方式,包括 Kafka 怎么维护消费端的 offset、consumer 的 offset 分区算法、查看 offset 的命令等。

partition 的副本机制:

创建带副本机制的 topic。查看各个分区中对应的 leader。介绍副本的相关名词。阐述副本的协同工作方式。

isr(in-sync replicas,同步副本集合):明确加入 isr 集合的条件、lastCaughtUpTimeMs 标志的作用、kafka 副本管理器的工作原理,以及在所有 replica 不工作情况下的处理方式。

副本数据同步原理:

涉及数据处理过程、初始状态以及不同情况下的数据同步方式,还包括数据丢失原理和解决方案,以及 leader 副本的选举过程。

消息的存储

消息的文件存储机制:将消息存储在文件中,以实现持久化。

logSegment 逻辑概念:包括 segment 文件命令规则、index 和 log 的对应关系,以及通过 offset 查找 message 的方式。

log 文件:分析 log 文件中的消息、日志清除策略(如删除或压缩)。

磁盘存储的性能问题:探讨如何优化磁盘存储以提高性能。

Kafka 消息的可靠性:确保消息在传输和存储过程中的可靠性,防止数据丢失等问题。

springboot集成kafka

1.导入spring-kafka依赖信息

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!-- kafkfa -->
    <dependency>
        <groupId>org.springframework.kafka</groupId>
        <artifactId>spring-kafka</artifactId>
        <exclusions>
            <exclusion>
                <groupId>org.apache.kafka</groupId>
                <artifactId>kafka-clients</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>org.apache.kafka</groupId>
        <artifactId>kafka-clients</artifactId>
    </dependency>
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
    </dependency>
</dependencies>

2.在resources下创建文件application.yml

server:
  port: 9991
spring:
  application:
    name: kafka-demo
  kafka:
    bootstrap-servers: 192.168.200.130:9092
    producer:
      retries: 10
      key-serializer: org.apache.kafka.common.serialization.StringSerializer
      value-serializer: org.apache.kafka.common.serialization.StringSerializer
    consumer:
      group-id: ${spring.application.name}-test
      key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
      value-deserializer: org.apache.kafka.common.serialization.StringDeserializer

3.消息生产者

package com.heima.kafka.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
    @Autowired
    private KafkaTemplate<String,String> kafkaTemplate;
    @GetMapping("/hello")
    public String hello(){
        kafkaTemplate.send("itcast-topic","代码星辰阁");
        return "ok";
    }
}

4.消息消费者

package com.heima.kafka.listener;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
@Component
public class HelloListener {
    @KafkaListener(topics = "itcast-topic")
    public void onMessage(String message){
        if(!StringUtils.isEmpty(message)){
            System.out.println(message);
        }
    }
}

传递消息为对象

目前springboot整合后的kafka,因为序列化器是StringSerializer,这个时候如果需要传递对象可以有两种方式

方式一:可以自定义序列化器,对象类型众多,这种方式通用性不强,本章节不介绍

方式二:可以把要传递的对象进行转json字符串,接收消息后再转为对象即可,本项目采用这种方式

发送消息

@GetMapping("/hello")
public String hello(){
    User user = new User();
    user.setUsername("xiaowang");
    user.setAge(18);
    kafkaTemplate.send("user-topic", JSON.toJSONString(user));
    return "ok";
}

接收消息

package com.heima.kafka.listener;
import com.alibaba.fastjson.JSON;
import com.heima.kafka.pojo.User;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
@Component
public class HelloListener {
    @KafkaListener(topics = "user-topic")
    public void onMessage(String message){
        if(!StringUtils.isEmpty(message)){
            User user = JSON.parseObject(message, User.class);
            System.out.println(user);
        }
    }
}

END

文字丨代码星辰阁

图片丨代码星辰阁

  • 42
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值