转载来自:http://blog.csdn.net/czmacd/article/details/54410508
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
- 1
- 2
- 3
从安全层面考虑,推荐使用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 (后来公司爱心同事,ycsb告诉我,这块可以直接写端口,因为kafka自动识别本机ip)
log.dirs=/tmp/kafka-logs
zookeeper.connect=master:2181,slave1:2181,slave2:2181
- 1
- 2
- 3
- 4
配置说明:
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连接地址,根据实际配置。
broker.id=0 (每个集群机器标识唯一)
listeners=PLAINTEXT://192.168.1.54:9092 (每个机器对应IP)
zookeeper.connect=zk1:2181,zk2:2181,zk3:2181 (zookeeper 安装机器)
auto.create.topics.enable=false 免得程序中写错了topic名字时被自动创建了
delete.topic.enable 可以物理上删除一个topic
2.5 启动集群
启动kafka服务之前先确定zookeeper集群已启动,通过以下命令以守护进程(后台)的方式启动每个kafka节点:
bin/kafka-server-start.sh -daemon config/server.properties
- 1
启动成功后可以看到:
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}')
- 1
改成:
PIDS=$(ps ax | grep -i 'kafka' | grep java | grep -v grep | awk '{print $1}')
- 1
2.6 测试集群
1.创建topic
bin/kafka-topics.sh --zookeeper master:2181 --create --replication-factor 1 --partitions 1 --topic test
- 1
创建了一个test主题,分区数为1,没有备份数
2.查看topic
kafka-topics.sh --list --zookeeper master:2181
__consumer_offsets:这个是kafka内部的topic,不允许删除
3.创建生产者producer
Kafka自带命令行的客户端,可以将文件或者标准输入的消息发送到kafka集群中,默认一行作为一个消息:
kafka-console-producer.sh --broker-list mer:9092 --topic test
可以看到,已经从生产者中发送了两个消息(“hello”,”my kafka”)到test主题,接着创建一个消费者来消费这些消息。
4.创建消费者consumer
kafka-console-consumer.sh --bootstrap-servermaster:9092 --topic test --from-beginning
或者用老方式:
kafka-console-consumer.sh --zookeeper master:2181 --topic test --from-beginning
注:这种方式会出现警告
Using the ConsoleConsumer with old consumer is deprecated and will be removed in a future major release. Consider using the new consumer by passing [bootstrap-server] instead of [zookeeper].
消费者已经接收到了刚才生产者发送到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>
- 1
- 2
- 3
- 4
- 5
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();
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
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());
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
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/