Kafka集群搭建

来源:互联网 发布:飞剑问道好看吗 知乎 编辑:程序博客网 时间:2024/06/05 14:51

Kafka 集群搭建
Kafka是一种高吞吐量的分布式发布订阅消息系统,它可以处理消费者规模的网站中的所有动作流数据。本篇文档主要介绍下kafka集群的搭建及使用,和个人在搭建kafka集群中碰到的问题和解决方案。
首先,需要准备的软件:
1、Kafka (http://kafka.apache.org/downloads)
2、Zookeeper(搭建集群,kafka启动依赖zookeeper)
3、Kafka-manager 主要负责监控kafka的信息流量,以及消费的信息(https://github.com/yahoo/kafka-manager)
Kafka集群是把状态保存在Zookeeper中的,首先要搭建Zookeeper集群。(搭建zookeeper集群的过程这边就不做介绍了)
软件环境
(3台服务器-我的测试)
192.168.181.90 server90
192.168.181.91 server91
192.168.181.92 server92
搭好zookeeper集群后的地址为:192.168.181.90:48881,192.168.181.91:48881,192.168.181.92:48881
Kafka集群搭建
1、软件环境
Linux 3台
已经搭建好的zookeeper集群
软件版本kafka_2.10-0.10.2.0
2、修改配置文件
进入到config目录 : cd /home/qcj/kafka_2.10-0.10.2.0/
主要关注:server.properties 这个文件即可,
修改配置文件(这里主要说明下需要修改的地方):
broker.id=0 每台服务器的broker.id都不能相同,三台分别为0,1,2
listeners=PLAINTEXT://192.168.181.90:9092(这里特别说明下,ip一定要配,不然consumer消费的时候可能会找不到地址),三台分别为192.168.181.90:9092,192.168.181.91:9092,192.168.181.92:9092
zookeeper.connect=192.168.181.90:48881,192.168.181.91:48881,192.168.181.92:48881
这些都改好后,就可以启动每台服务器上的kafka了。

.bin/kafka-server-start.sh config/server.properties

在通过ps -ef|grep kafka 检查下kafka是否成功启动。
Ps:这里说明一下,如果不是第一次启动kafka,可能会报broker.id和meta.properties中的broker.id不匹配的错,只要修改/tmp/kafka/meta.properties中broker.id,改成跟server.properties中的相同即可。
3、创建topic
./kafka-topics.sh –create –zookeeper 192.168.181.90:48881,192.168.181.91:48881,192.168.181.92:48881 –replication-factor 3 –partitions 1 –topic cluster1
这里说明一下,eplication-factor要跟集群的台数保持一致。分区partitions根据自己的需求设定。
4、通过./kafka-topics.sh –describe –zookeeper 192.168.181.90:48881,192.168.181.91:48881,192.168.181.92:48881 –topic cluster1可以查看topic的状态。

至此,kafka集群搭建,和topic创建已经完成。

5、JAVA端producer和consumer的配置。
接下里的代码只做demo测试用,并无任何业务处理。
Producer端:

public class KafkaProcuderService2 {    private static final Logger logger = LoggerFactory.getLogger(KafkaProcuderService2.class);    private KafkaProducer<String, String> kafkaProducer =new KafkaProducer<>(getKafkaProps());    public void sendSync(String key, String value) {        ProducerRecord<String, String> record = new ProducerRecord<>("cluster1", key, value);        try {            RecordMetadata result = this.kafkaProducer.send(record).get();        } catch (InterruptedException e) {            logger.error("Catch InterruptedException: ", e);        } catch (ExecutionException e) {            logger.error("Catch ExecutionException: ", e);        } catch (Exception e) {            logger.error("Catch Exception: ", e);        }    }    private Properties getKafkaProps() {        Properties props = new Properties();        props.put("bootstrap.servers", "192.168.181.90:9092,192.168.181.91:9092,192.168.181.92:9092");//        props.put("client.id", "DemoProducer");        props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");        props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");        return props;    }    public static void main(String[] args) throws InterruptedException {        KafkaProcuderService2 kafkaProcuderService2 =  new KafkaProcuderService2();        int i = 0;        while(true){            kafkaProcuderService2.sendSync("i",String.valueOf(i));            Thread.sleep(2000);            i++;        }    }}

Consumer端:

public class KafkaConsumerService2 {    private KafkaConsumer<String, String> consumer;    private Properties getProps() {        Properties props = new Properties();        props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "192.168.181.90:9092,192.168.181.91:9092,192.168.181.92:9092");        props.put(ConsumerConfig.GROUP_ID_CONFIG, "test-consumer-group");        props.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, "true");        props.put(ConsumerConfig.AUTO_COMMIT_INTERVAL_MS_CONFIG, "1000");        props.put(ConsumerConfig.SESSION_TIMEOUT_MS_CONFIG, "30000");        props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringDeserializer");        props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringDeserializer");        return props;    }    public void sub() {        this.consumer = new KafkaConsumer<>(getProps());        this.consumer.subscribe(Collections.singletonList("cluster1"));        while(true) {            try {                ConsumerRecords<String, String> records = this.consumer.poll(1000);                records.forEach(stringStringRecord -> {                    String key = stringStringRecord.key();                    String value = stringStringRecord.value();                    System.out.println("key:"+key+"   value"+value);                });            } catch (Exception e) {            }        }    }    public static void main(String[] args) {        KafkaConsumerService2 kafkaConsumerService2 = new KafkaConsumerService2();        kafkaConsumerService2.sub();    }}

启动producer,和consumer就能看到消费者端在不停的接受生产者发出的消息,并且可以复制多份consumer模拟多个消费者。中断其中任意一台kafka的server,仍能正常消费。中断任意一个consumer,其余的consumer会接着几首消息。(这里说明一下,如果多个消费的group.id设为相同,则只要有一台有在接收消息,其余就等待。如果group.id不相同则全部接受同样的消息。具体根据需求自行配置)
6、遇到的问题和解决方案:
最严重的一个问题就是我们发现中断broker.id=0的kafka server后消费者就无法正常消费。在这个点上我们研究了很久,发现是因为之前kafka运行残留的一些配置信息导致的。然后针对该问题我们总结出了一种解决方案,实测可行,通过链接zookeeper。将上面的kafka配置全部清空。然后重启kafka就能正常消费了。
7、关于kafka-manager的使用:
下载,编绎
编绎,生成发布包: git clone https://github.com/yahoo/kafka-manager
下好后:
cd kafka-manager
sbt clean dist
生成的包会在kafka-manager/target/universal 下面。生成的包只需要Java环境就可以运行了,在部署的机器上不需要安装sbt。
(这一步可能需要比较长的时间)
部署
打好包好,在部署机器上解压,修改好配置文件,就可以运行了。
- 解压
unzip kafka-manager-1.0-SNAPSHOT.zip
修改conf/application.conf,把kafka-manager.zkhosts改为自己的zookeeper服务器地址
kafka-manager.zkhosts=”localhost:2181”
启动
cd kafka-manager-1.0-SNAPSHOT/bin
./kafka-manager -Dconfig.file=../conf/application.conf
查看帮助 和 后台运行:
./kafka-manager -h
nohup ./kafka-manager -Dconfig.file=../conf/application.conf >/dev/null 2>&1 &
默认http端口是9000,可以修改配置文件里的http.port的值,或者通过命令行参数传递:
./kafka-manager -Dhttp.port=9001
接着可以访问localhost(你部署的服务器):9000就可以访问manager页面了。下面是页面展示:

原创粉丝点击