集群规划,3个容器,由最初的centos:latest镜像开始制作
主机名 | IP地址 |
---|---|
kafka-node1 | 172.19.0.71 |
kafka-node2 | 172.19.0.72 |
kafka-node3 | 172.19.0.73 |
宿主机(虚拟机centos6.5) | 10.20.0.128 |
172.19.0.0/16网段是docker内部使用的桥接网段,外网是无法直接访问的
安装和配置zookeeper
下载解压添加到环境变量即可,zoo.cfg配置如下
server.1=kafka-node1:2888:3888
server.2=kafka-node2:2888:3888
server.3=kafka-node3:2888:3888
注意配置的data目录下面的myid文件需要对应的id编号即可
安装和配置kafka
下载解压添加到环境变量,server.properties修改如下参数:
broker.id=1 //1,2,3因为配了3台
listeners=PLAINTEXT://kafka-node1:9092 //这个参数非常重要,想要外网访问docker内的集群,只能配置主机名,不能配置IP地址
zookeeper.connect=172.19.0.71:2181,172.19.0.72:2181,172.19.0.73:2181
broker.id=2
listeners=PLAINTEXT://kafka-node2:9093 //注意不要在用9092端口,最好和docker暴露出去的端口一致
zookeeper.connect=172.19.0.71:2181,172.19.0.72:2181,172.19.0.73:2181
broker.id=3
listeners=PLAINTEXT://kafka-node3:9094
zookeeper.connect=172.19.0.71:2181,172.19.0.72:2181,172.19.0.73:2181
其他具体细节的配置参照官网说明,作为测试,默认不会有什么影响
Docker容器创建语句
docker run -d --name kafka-node1 --ip 172.19.0.71 --net mariadb-net -p 9092:9092 -v /home/kafka-node1:/mnt -i -t cluster/hadoop:1.1-kafka /bin/bash
docker run -d --name kafka-node2 --ip 172.19.0.72 --net mariadb-net -p 9093:9093 -v /home/kafka-node2:/mnt -i -t cluster/hadoop:1.1-kafka /bin/bash
docker run -d --name kafka-node3 --ip 172.19.0.73 --net mariadb-net -p 9094:9094 -v /home/kafka-node3:/mnt -i -t cluster/hadoop:1.1-kafka /bin/bash
(把镜像换成centos:latest即可)
启动zookeeper
在3台机器上分别执行
zkServer.sh start
启动kafka集群
在3台机器上分别执行
kafka-server-start.sh -daemon /usr/local/kafka/config/server.properties(修改成自己的地址)
本机测试
创建topic
kafka-topics.sh --create --zookeeper kafka-node1:2181 --replication-factor 1 --partitions 1 --topic test1
发送一些消息
kafka-console-producer.sh --broker-list kafka-node1:9092 --topic test1 //注意这里不能在用localhost
查看消息
kafka-console-consumer.sh --bootstrap-server kafka-node2:9092 --topic test1 --from-beginning
本机测试发现没有问题
Java客户端测试(其他机器,可以访问宿主机,但不能访问docker)
参照官网构建maven项目,代码如下:
public class DemoProducer {
public static void main(String[] args) {
long events = 10;
Random rnd = new Random();
Properties props = new Properties();
props.put("bootstrap.servers", "10.20.0.128:9092");
props.put("acks", "all");
props.put("retries", 0);
props.put("batch.size", 16384);
props.put("linger.ms", 1);
props.put("buffer.memory", 33554432);
props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");
Producer<String, String> producer = new KafkaProducer<>(props);
for (long nEvents = 0; nEvents < events; nEvents++) {
long runtime = new Date().getTime();
String ip = "192.168.2." + rnd.nextInt(255);
String msg = runtime + ",www.example.com," + ip;
ProducerRecord<String, String> data = new ProducerRecord<String, String>("test1", msg);
producer.send(data);
System.out.println(nEvents);
}
producer.close();
}
}
发现一直卡在那里,最终以超时异常退出,或者报broker找不到的错误,跟进去之后发现,程序获得了cluster集群的信息,包括节点和分区等元信息,但是无法进一步访问,因为返回的信息是kafka-node1、kafka-node2和kafka-node3,这就是为什么在kafka的配置中不要配IP地址的原因,如果返回的是IP地址,那么肯定是无法访问的,现在返回的是主机名,很简单,在客户端的hosts文件中添加:
10.20.0.128 kafka-node1
10.20.0.128 kafka-node2
10.20.0.128 kafka-node3
把所有的主机名都映射到宿主机的IP,OK,问题解决