Docker中搭建Kafka集群以及让外网访问

集群规划,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,问题解决

你可能感兴趣的:(docker,kafka)