1.创建zookeeper容器(直接创建容器时如果没有镜像会自动拉取最新版本的镜像)
docker run -d --name zookeeper -p 2181:2181 -v /etc/localtime:/etc/localtime wurstmeister/zookeeper
2.创建kafka容器
## KAFKA_ZOOKEEPER_CONNECT 需要修改成zookeeper所在容器IP,容器之间是可以通过IP访问的
docker run -d --name kafka -p 9092:9092 -e KAFKA_BROKER_ID=1 -e KAFKA_ZOOKEEPER_CONNECT=172.17.0.9:2181 -e KAFKA_ADVERTISED_LISTENERS=PLAINTEXT://47.100.215.27:9092 -e KAFKA_LISTENERS=PLAINTEXT://0.0.0.0:9092 -v /etc/localtime:/etc/localtime -t wurstmeister/kafka:latest
参数
-e KAFKA_BROKER_ID=0 //在kafka集群中,每个kafka都有一个BROKER_ID来区分自己
-e KAFKA_ZOOKEEPER_CONNECT=172.17.0.9:2181//kafka 配置zookeeper管理kafka的路径 //zookeeper地址
-e KAFKA_ADVERTISED_LISTENERS=PLAINTEXT://47.100.215.27:9092 //把kafka的地址端口注册给zookeeper
-e KAFKA_LISTENERS=PLAINTEXT://0.0.0.0:9092 //配置kafka的监听端口
-v /etc/localtime:/etc/localtime //容器时间同步虚拟机的时间
zookeeper容器的ip地址使用docker inspect [容器id] 查看如下图
tips:创建过程中遇到的问题时记得用docker logs查看容器日志,如果free -h查看的内存不足可以通过增加swap空间解决
三种创建方式
·作用于内网
## KAFKA_ZOOKEEPER_CONNECT 需要修改成zookeeper所在容器IP(docker inspect查看),容器之间是可以通过IP访问的,但是不能填写成虚拟IP
docker run -d --name kafka -p 9092:9092 -e KAFKA_BROKER_ID=1 -e KAFKA_ZOOKEEPER_CONNECT=172.17.0.9:2181 -e KAFKA_ADVERTISED_LISTENERS=PLAINTEXT://localhost:9092 -e KAFKA_LISTENERS=PLAINTEXT://0.0.0.0:9092 -v /etc/localtime:/etc/localtime -t wurstmeister/kafka:latest
·作用于外网(一般不存在)
docker run -d --name kafka -p 9092:9092 -e KAFKA_BROKER_ID=1 -e KAFKA_ZOOKEEPER_CONNECT=(服务器外网IP):2181 -e KAFKA_ADVERTISED_LISTENERS=PLAINTEXT://(服务器外网IP):9092 -e KAFKA_LISTENERS=PLAINTEXT://0.0.0.0:9092 -v /etc/localtime:/etc/localtime -t wurstmeister/kafka:latest
# 2.然后再本机的hosts文件中中添加 服务器的外网ip和对应的服务器名字,例如:(服务器外网IP) VM-24-5-centos
# 3.java代码中直接使用代码:
# // 设置配置文件的方式
Properties properties = new Properties();
# // 设置链接的主服务器
# // 连接当前远程的服务器出现了url错误,需要进行修改,切记加上9092
properties.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "VM-24-5-centos:9092");
·整合SpringBoot
docker run -d --name kafka -p 9092:9092 -e KAFKA_BROKER_ID=0 -e KAFKA_ZOOKEEPER_CONNECT=(服务器内网IP):2181 -e KAFKA_ADVERTISED_LISTENERS=PLAINTEXT://(服务器外网IP):9092 -e KAFKA_LISTENERS=PLAINTEXT://0.0.0.0:9092 -t wurstmeister/kafka:latest
内网ip和外网ip可以去自己的云服务器看
3.创建好后可以进入容器测试kafka
4.后端代码
yml配置
kafka:
bootstrap-servers: kafka服务器ip:端口
producer: # producer 生产者
retries: 0 # 重试次数
acks: 1 # 应答级别:多少个分区副本备份完成时向生产者发送ack确认(可选0、1、all/-1)
batch-size: 16384 # 批量大小
buffer-memory: 33554432 # 生产端缓冲区大小
key-serializer: org.apache.kafka.common.serialization.StringSerializer
# value-serializer: com.itheima.demo.config.MySerializer
value-serializer: org.apache.kafka.common.serialization.StringSerializer
consumer: # consumer消费者
group-id: defaultConsumerGroup # 默认的消费组ID
enable-auto-commit: true # 是否自动提交offset
auto-commit-interval-ms: 1000 # 提交offset延时(接收到消息后多久提交offset)
# 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: com.itheima.demo.config.MyDeserializer
value-deserializer: org.apache.kafka.common.serialization.StringDeserializer
生产者(一般是在控制层或者业务层调用)
package com.example.demo.component;
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;
/**
* @Date 2022/7/7 15:07
* @ClassName kafkaProducer
* @Description ToDo
* @Author LongX
**/
@Component
public class KafkaProducer {
/**
* KafkaTemplate泛型类型跟消费者ConsumerRecord的泛型类型保持一致
*/
@Autowired
private KafkaTemplate<String,String> kafkaTemplate;
/**
* 发送消息
*/
public void sendMessage() {
try{
//生产消息
String message = "hello ! 测试kafka ";
ListenableFuture<SendResult<String, String>> listenableFuture = kafkaTemplate.send("hello","hello", message);
listenableFuture.addCallback(new ListenableFutureCallback<SendResult<String, String>>() {
@Override
public void onSuccess(SendResult<String, String> result) {
System.out.println("sendMessage success");
}
@Override
public void onFailure(Throwable ex) {
System.out.println("sendMessage error");
}
});
}catch (Exception e){
System.out.println("sendMessage exception");
}
}
}
消费者(监听某些topic就可以了)
package com.example.demo.component;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.stereotype.Component;
/**
* @Date 2022/7/7 15:36
* @ClassName TopicComponent
* @Description ToDo
* @Author LongX
**/
@Component
public class TopicComponent {
@KafkaListener(topics = {"hello","hello2"})
public void handMessage(ConsumerRecord<String, String> record){
String topic = record.topic();
String msg = record.value();
System.out.println("消费者接受消息:topic-->"+topic+",msg->>"+msg);
}
}
生产调用实例(控制层)
package com.example.demo.controller;
import com.example.demo.component.KafkaProducer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @Date 2022/7/7 15:30
* @ClassName KafkaProController
* @Description ToDo
* @Author LongX
**/
@RestController
public class KafkaProController {
@Autowired
private KafkaProducer kafkaProducer;
@RequestMapping("/hello")
public String hello(){
System.out.println("------->测试生产者发送消息");
kafkaProducer.sendMessage();
return "kafka消息已发送.";
}
}