kafka_0.10.1.0集群部署

1. 背景简介

Kafka是一个分布式流平台,原本开发自LinkedIn,之后成为Apache项目的一部分,用于构建实时数据管道和流媒体应用,水平扩展、容错,很多公司都在生产环境中使用:LinkedIn,Yahoo,Twitter,Uber,Oracle…..。
Kafka背景及架构介绍:
http://www.infoq.com/cn/articles/kafka-analysis-part-1/
http://sanwen8.cn/p/2036To3.html

2. 分布式部署

以3个节点为例,分别是master,slave1,slave2

2.1 配置java环境

Kafka是由scala语言编写的,所以它运行于jvm上面,首先各个节点要安装jdk以及配置环境变量:

export JAVA_HOME=/usr/java/default/
export PATH=$JAVA_HOME/bin:$PATH
export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar

从安全层面考虑,推荐使用JDK1.8,因为较旧的免费版本已经公开了安全漏洞。LinkedIn目前正在使用的是JDK1.8 u5(G1垃圾收集器),如果决定在JDK1.7上使用G1垃圾收集器,确定版本为u51或者更新(kafka默认是使用G1垃圾收集器的)。

2.2 安装zookeeper集群

Kafka内置有zookeeper服务,最好把zookeeper独立出来,其它组件服务(hbase等)也可以共享。Kafka使用ZkClient与ZooKeepe交互,0.10.1.0版本对应ZkClient-0.9,而ZkClient-0.9则对应zookeeper-3.4.8。具体的集群部署不再详述,参考网上的文章。

2.3 下载kafka安装包

选择0.10.1.0版本安装包,地址如下:http://kafka.apache.org/downloads.html
上传安装包到任意一个节点,解压:tar -zxvf kafka_2.11-0.10.1.0.tgz
PS:2.11表示的是scala版本,安装包已经内置scala库,所以无需独立安装scala.

2.4 修改配置文件

如果是想单纯地快速启动一个broker进行尝试kafka的功能,则可以使用默认的配置,在分布式环境中建议至少修改以下4个配置项目,其它的配置再根据实际项目环境进行调优。以master节点配置为示例,其余节点根据参数说明作相应调整:

broker.id=0
listeners=PLAINTEXT://master:9092   
log.dirs=/tmp/kafka-logs
zookeeper.connect=master:2181,slave1:2181,slave2:2181

配置说明:
broker.id:broker的id,必需是一个全局(集群)唯一的整数值,即集群中每个kafka server的配置不能相同。
listeners:socket监听的地址,格式为listeners = security_protocol://host_name:port.如果没有配置该参数,则默认通过java的api(java.net.InetAddress.getCanonicalHostName())来获取主机名,端口默认为9092,建议进行显式配置,避免多网卡时解析有误。
log.dirs:日志保存目录,其实保存着各个主题的消息数据。多个目录可以以逗号隔开,默认值为/tmp/kafka-logs,可以每个日志目录挂在不同的磁盘做来负载均衡。
zookeeper.connect:zookeeper连接地址,根据实际配置。

2.5 启动集群

启动kafka服务之前先确定zookeeper集群已启动,通过以下命令以守护进程的方式启动每个kafka节点:

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

启动成功后可以看到:

这里写图片描述

PS:这里有一个地方要注意,停止脚本(kafka-server-stop.sh)好像不能把服务停止,实际上这个脚本也只是把”Kafka”进程kill掉,而脚本不能正常获取到进程pid,可以使用以下两种方式来结束进程:
1. 先通过jps来获取pid,然后: kill -s TERM $PIDS (不要直接kill -9)
2. 修改脚本,使得可以正确解析出pid:

PIDS=$(ps ax | grep -i 'Kafka\.kafka' | grep java | grep -v grep | awk '{print $1}')

改成:

PIDS=$(ps ax | grep -i 'kafka' | grep java | grep -v grep | awk '{print $1}')

2.6 测试集群

1.创建topic

bin/kafka-topics.sh --zookeeper master:2181 --create --replication-factor 1 --partitions 1 --topic test

创建了一个test主题,分区数为1,没有备份数

2.查看topic
这里写图片描述

__consumer_offsets:这个是kafka内部的topic,不允许删除

3.创建生产者producer
Kafka自带命令行的客户端,可以将文件或者标准输入的消息发送到kafka集群中,默认一行作为一个消息:
这里写图片描述
可以看到,已经从生产者中发送了两个消息(“hello”,”my kafka”)到test主题,接着创建一个消费者来消费这些消息。

4.创建消费者consumer
这里写图片描述
消费者已经接收到了刚才生产者发送到test主题的消息。由此,通过简单的测试验证了集群能够正常运行。

PS:当使用delete命令删除主题是,默认只是进行标记,并没有真正的删除
这里写图片描述
需要在config/server.properties配置文件中开启delete.topic.enable=true

3. API开发

Kafka通过独立的协议来暴露它的所有功能,所有客户端可以使用各种语言进行编程,但只有java作为kafka项目的一部分在维护,至于其它的语言则可以通过一些开源的项目。下面通过java api模拟生产者消费者,同时向集群生产消息以及消费消息。

3.1 引入依赖包

<dependency>
        <groupId>org.apache.kafka</groupId>
        <artifactId>kafka-clients</artifactId>
        <version>0.10.1.0</version>
</dependency>

3.2 编写生产者程序

编写一个生产者,定时向kafka集群中的test主题发送一些测试的消息:

Properties props = new Properties();
props.put("bootstrap.servers", "master: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 (int i = 0; i < 100; i++){
    System.out.println("producer sends message: " + i);
    producer.send(new ProducerRecord<String, String>("test", i + "", i + ""));
}
producer.close();

3.3 编写消费者程序

编写消费者程序,从kafka集群中的test主题消费消息:

Properties props = new Properties();
props.put("bootstrap.servers", "master:9092");
props.put("group.id", "test");
props.put("enable.auto.commit", "true");
props.put("auto.commit.interval.ms", "1000");
props.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
props.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
KafkaConsumer<String, String> consumer = new KafkaConsumer<>(props);
consumer.subscribe(Arrays.asList("test"));
while (true) {
    ConsumerRecords<String, String> records = consumer.poll(100);
    for (ConsumerRecord<String, String> record : records)
System.out.printf("offset = %d, key = %s, value = %s%n", record.offset(), record.key(), record.value());
}

3.4 测试运行

分别启动生产者与消费者程序,并观察运行结果,生产者不断发送消息:
这里写图片描述

消费者程序接收消息:
这里写图片描述

同时通过脚本启动的消费者也接收到消息:
这里写图片描述

4. 进阶内容

Kafka Connect:
https://kafka.apache.org/documentation/#connect
http://docs.confluent.io/2.0.0/connect/connect-jdbc/docs/index.html

Kafka Stream:
https://kafka.apache.org/documentation/streams
https://spark.apache.org/docs/1.6.1/streaming-kafka-integration.html

kafka monitor:
https://kafka.apache.org/documentation/#monitoring
https://github.com/quantifind/KafkaOffsetMonitor
https://github.com/yahoo/kafka-manager

kafka生态圈:
https://cwiki.apache.org/confluence/display/KAFKA/Ecosystem

其它
http://www.infoq.com/cn/kafka/
中文翻译(建议看官方文档):http://orchome.com/kafka/index
博客系列:http://www.jasongj.com/2015/03/10/KafkaColumn1/

猜你喜欢

转载自blog.csdn.net/czmacd/article/details/54410508
今日推荐