docker安装kafaka单节点并使用Springboot集成

公司项目需要对接kafaka,记一次开发环境安装。

一、安装kafaka

创建docker网络

docker network create app-tier --driver bridge

安装zookeeper

因为kafaka依赖于zookeeper运行,所以先安装zookeeper。zookeeper的默认端口为:2181
ALLOW_ANONYMOUS_LOGIN 表示可以不需要密码。
下面为快捷安装指令,生产环境需要将配置、数据文件等文件夹挂载到宿主机。

docker run -d --name zookeeper-server \
    --network app-tier \
    -e ALLOW_ANONYMOUS_LOGIN=yes \
    bitnami/zookeeper:latest

安装Kafka

因为kafaka依赖于zookeeper运行,所以先安装zookeeper。zookeeper的默认端口为:2181
ALLOW_PLAINTEXT_LISTENER 表示任何人可以访问。
KAFKA_CFG_ZOOKEEPER_CONNECT 表示zookeeper的地址
KAFKA_CFG_ADVERTISED_LISTENERS 表示当前主机IP或地址,监听端口
下面为快捷安装指令,生产环境需要将配置、数据文件等文件夹挂载到宿主机。

docker run -d --name kafka-server \
    --network app-tier \
    -p 9092:9092 \
    -e ALLOW_PLAINTEXT_LISTENER=yes \
    -e KAFKA_CFG_ZOOKEEPER_CONNECT=zookeeper-server:2181 \
    -e KAFKA_CFG_ADVERTISED_LISTENERS=PLAINTEXT://192.168.21.131:9092 \
    bitnami/kafka:latest

查看kafka容器日志

docker logs -f kafka

可视化管理工具kafka-map安装

docker run -d --name kafka-map \
    --network app-tier \
    -p 9001:8080 \
    -v /opt/kafka-map/data:/usr/local/kafka-map/data \
    -e DEFAULT_USERNAME=admin \
    -e DEFAULT_PASSWORD=admin123 \
    --restart always dushixiang/kafka-map:latest

访问测试

访问地址:http://服务器IP:9001/
DEFAULT_USERNAME:默认账号admin
DEFAULT_PASSWORD:默认密码admin123
Git 地址:https://github.com/dushixiang/kafka-map/blob/master/README-zh_CN.md

二、SpringBoot 项目集成kafaka

依赖导入

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

配置文件

spring:
  kafka:
    #集群配置
    bootstrap-servers: 192.168.21.131:9092
    #生产者配置
    producer:
      #采用的ack机制
      acks: 1
      #批量提交的数据大小 16kb
      batch-size: 16384
      #生产者暂存数据的缓冲区大小
      buffer-memory: 33554432
      retries: 0
      #系列化方式
      key-serializer: org.apache.kafka.common.serialization.StringSerializer
      value-serializer: org.apache.kafka.common.serialization.StringSerializer
    #消费者配置
    consumer:
      #是否自动提交偏移量
      enable-auto-commit: true
      #消费消息后间隔多长时间提交偏移量
      auto-commit-interval: 100
      #默认的消费者组,代码中可以热键修改
      group-id: test
      # earliest:当各分区下有已提交的offset时,从提交的offset开始消费;无提交的offset时,从头开始消费
      # latest:当各分区下有已提交的offset时,从提交的offset开始消费;无提交的offset时,消费新产生的该分区下的数据
      # none:topic各分区都存在已提交的offset时,从offset后开始消费;只要有一个分区不存在已提交的offset,则抛出异常
      auto-offset-reset: latest
      key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
      value-deserializer: org.apache.kafka.common.serialization.StringDeserializer

测试实体


import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.time.LocalDateTime;

/**
 * @describe 订单类javaBean实体
 */
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class Order {
    /**
     * 订单id
     */
    private long orderId;
    /**
     * 订单号
     */
    private String orderNum;
    /**
     * 订单创建时间
     */
    private LocalDateTime createTime;
}

生产者

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.kafka.support.SendResult;
import org.springframework.stereotype.Component;
import org.springframework.util.concurrent.ListenableFuture;
import org.springframework.util.concurrent.ListenableFutureCallback;

import java.time.LocalDateTime;

/**
 * @describe 话题的创建类,使用它向kafka中创建一个关于Order的订单主题
 */
@Component
@Slf4j
public class KafkaProvider {
    /**
     * 消息 TOPIC
     */
    private static final String TOPIC = "shopping";

    @Autowired
    private KafkaTemplate<String, String> kafkaTemplate;

    public void sendMessage(long orderId, String orderNum, LocalDateTime createTime) {
        // 构建一个订单类
        Order order = Order.builder()
                .orderId(orderId)
                .orderNum(orderNum)
                .createTime(createTime)
                .build();

        // 发送消息,订单类的 json 作为消息体
        ListenableFuture<SendResult<String, String>> future =
                kafkaTemplate.send(TOPIC, JSONObject.toJSONString(order));

        // 监听回调
        future.addCallback(new ListenableFutureCallback<SendResult<String, String>>() {
            @Override
            public void onFailure(Throwable throwable) {
                log.info("## Send message fail ...");
            }

            @Override
            public void onSuccess(SendResult<String, String> result) {
                log.info("## Send message success ...");
            }
        });
    }
}

消费者

import lombok.extern.slf4j.Slf4j;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.stereotype.Component;

/**
 * @create 2022-10-08 1:25
 * @describe 通过指定的话题和分组来消费对应的话题
 */
@Component
@Slf4j
public class KafkaConsumer {
    @KafkaListener(topics = "shopping", groupId = "group_id") //这个groupId是在yml中配置的
    public void consumer(String message) {
        log.info("## consumer message: {}", message);
    }
}

测试类

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Component
public class KafakaUtil {


    @Autowired
    private KafkaProvider kafkaProvider;

    public void sendMessage() throws InterruptedException {
        //如果这里打印为null,要么是zk或kafka没正常启动,此时进入linux分别查看他们状态接口,另外也需要排查一下你的yum文件配置的kafka的地址,最后排查自己的注解是否引入错误的package
        System.out.println("是否为空??+" + kafkaProvider);
        // 发送 1000 个消息
        for (int i = 0; i < 1000; i++) {
            long orderId = i + 1;
            String orderNum = UUID.randomUUID().toString();
            kafkaProvider.sendMessage(orderId, orderNum, LocalDateTime.now());
        }

        TimeUnit.MINUTES.sleep(1);
    }
}
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值