Kafka 的简介:

  Kafka 是一款分布式消息发布和订阅系统,具有高性能、高吞吐量的特点而被广泛应用与大数据传输场景。它是由 LinkedIn 公司开发,使用 Scala 语言编写,之后成为 Apache 基金会的一个顶级项目。kafka 提供了类似 JMS 的特性,但是在设计和实现上是完全不同的,而且他也不是 JMS 规范的实现。

kafka 产生的背景:

  kafka 作为一个消息系统,早起设计的目的是用作 LinkedIn 的活动流(Activity Stream)和运营数据处理管道(Pipeline)。活动流数据是所有的网站对用户的使用情况做分析的时候要用到的最常规的部分,活动数据包括页面的访问量(PV)、被查看内容方面的信息以及搜索内容。这种数据通常的处理方式是先把各种活动以日志的形式写入某种文件,然后周期性的对这些文件进行统计分析。运营数据指的是服务器的性能数据(CPU、IO 使用率、请求时间、服务日志等)。

Kafka 的应用场:

  由于 kafka 具有更好的吞吐量、内置分区、冗余及容错性的优点(kafka 每秒可以处理几十万消息),让 kafka 成为了一个很好的大规模消息处理应用的解决方案。所以在企业级应用长,主要会应用于如下几个方面

Ø 行为跟踪:kafka 可以用于跟踪用户浏览页面、搜索及其他行为。通过发布-订阅模式实时记录到对应的 topic 中,通过后端大数据平台接入处理分析,并做更进一步的实时处理和监控

Ø 日志收集:日志收集方面,有很多比较优秀的产品,比如 Apache Flume,很多公司使用kafka 代理日志聚合。日志聚合表示从服务器上收集日志文件,然后放到一个集中的平台(文件服务器)进行处理。在实际应用开发中,我们应用程序的 log 都会输出到本地的磁盘上,排查问题的话通过 linux 命令来搞定,如果应用程序组成了负载均衡集群,并且集群的机器有几十台以上,那么想通过日志快速定位到问题,就是很麻烦的事情了。所以一般都会做一个日志统一收集平台管理 log 日志用来快速查询重要应用的问题。所以很多公司的套路都是把应用日志几种到 kafka 上,然后分别导入到 es 和 hdfs 上,用来做实时检索分析和离线统计数据备份等。而另一方面,kafka 本身又提供了很好的 api 来集成日志并且做日志收集。

Kafka 本身的架构:

  一个典型的 kafka 集群包含若干 Producer(可以是应用节点产生的消息,也可以是通过Flume 收集日志产生的事件),若干个 Broker(kafka 支持水平扩展)、若干个 Consumer Group,以及一个 zookeeper 集群。kafka 通过 zookeeper 管理集群配置及服务协同。Producer 使用 push 模式将消息发布到 broker,consumer 通过监听使用 pull 模式从broker 订阅并消费消息。多个 broker 协同工作,producer 和 consumer 部署在各个业务逻辑中。三者通过zookeeper 管理协调请求和转发。这样就组成了一个高性能的分布式消息发布和订阅系统。图上有一个细节是和其他 mq 中间件不同的点,producer 发送消息到 broker的过程是 push,而 consumer 从 broker 消费消息的过程是 pull,主动去拉数据。而不是 broker 把数据主动发送给 consumer。

kafka 的安装部署:

  1.下载安装包 :http://kafka.apache.org/downloads

   解压 :  tar -zxvf kafka_2.11-1.1.0.tgz 这样子就安装好了。

  2.启动/停止 kafka:

   1. 需要先启动 zookeeper,如果没有搭建 zookeeper 环境,可以直接运行kafka 内嵌的 zookeeper

    启动命令: bin/zookeeper-server-start.sh config/zookeeper.properties

    如果连接外部zookeeper 需要修改 config/server.properties 配置文件来配置我们的zookeeper。修改如下信息。zk集群环境用逗号隔开。

    

zookeeper.connect=192.168.254.135:2181

  

    这个时候可以通过 sh kafka-server-start.sh (-daemon) ../config/server.properties 命令来启动服务后台运行。若不加括号里的参数则在当前进程启动,按CTRL+c退出。

  

3.创建 一个名为 test 的 topic(在bin目录下) :Replication-factor 表示该 topic 需要在不同的 broker 中保存几份,这里设置成 1,表示在两个 broker 中保存两份。Partitions 分区

sh kafka-topics.sh --create --zookeeper 192.168.25.128:2181 --replication-factor 1 --partitions 1 --topic test

  查看 topic 列表:

sh kafka-topics.sh --list --zookeeper 192.168.25.128:2181

  

  4.发送消息:发送两条消息

    

sh kafka-console-producer.sh  --broker-list localhost:9092 --topic testTopic
> This is a message
> This is another message

  

  5.启动消费者:

sh kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic testTopic --from-beginning

  

安装集群环境:

  在 3台机器上都配置上  zookeeper.connect=192.168.254.135:2181 信息。zk要是也做了集群用逗号分开

  修改 server.properties 文件中 broker.id=0 ,在集群中这个 id 要求是唯一的,我们分别改成 1 2 3.

  放开 listeners=PLAINTEXT://:9092 配置,修改为listeners=PLAINTEXT://本机IP:9092,然后先后启动就可以,注意这里先启动的,也就是先到zk上面去注册的就是 leader。

  (出问题记得看日志)

修改集群中 broker.id  

1. 改server.prorperties文件配置(broker.id=值);
2. 改meta.properties,默认情况下,应该在/tmp/kafka-logs目录下;(查在server.prorperties配置的log.dir路径)
同时需注意数据存在多个目录时,需要修改多个目录的meta.propertie。

Kafka JAVA API 的使用:

package com.lf;

import java.util.Properties;

import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.Producer;
import org.apache.kafka.clients.producer.ProducerConfig;
import org.apache.kafka.clients.producer.ProducerRecord;
import org.apache.kafka.common.serialization.IntegerSerializer;
import org.apache.kafka.common.serialization.StringSerializer; public class KafkaProducerDemo extends Thread{ private final KafkaProducer<Integer, String> producer; private final String topic ; public KafkaProducerDemo(String topic) {
Properties properties = new Properties();
properties.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "192.168.25.129:9092,192.168.25.130:9092,192.168.25.131:9092");
// 客户端ID标识
properties.put(ProducerConfig.CLIENT_ID_CONFIG, "KafkaProducerDemo");
//确认记录,保证记录不丢失 总是设置成-1
properties.put(ProducerConfig.ACKS_CONFIG, "-1");
// 键序列化
properties.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.IntegerSerializer");
//值序列化
properties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringSerializer");
producer = new KafkaProducer<Integer, String>(properties);
this.topic = topic;
}
@Override
public void run() {
int num = 0;
while(num<50){
try {
num++;
String message = "message_" + num;
System.out.println("begin send message" + message);
producer.send(new ProducerRecord<Integer, String>(topic, message));
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
new KafkaProducerDemo("lftest").start();
}
}

  

发送端的常用可选配置信息:

ACKS_CONFIG:

  acks 配置表示 producer 发送消息到 broker 上以后的确认值。有三个可选项

Ø 0:表示 producer 不需要等待 broker 的消息确认。这个选项时延最小但同时风险最大(因为当 server 宕机时,数据将会丢失)。

Ø 1:表示 producer 只需要获得 kafka 集群中的 leader 节点确认即可,这个选择时延较小同时确保了 leader 节点确认接收成功。

Ø all(-1):需要 ISR 中所有的 Replica 给予接收确认,速度最慢,安全性最高,但是由于 ISR 可能会缩小到仅包含一个 Replica,所以设置参数为 all 并不能一定避免数据丢失,

BATCH_SIZE_CONFIG :

  生产者发送多个消息到 broker 上的同一个分区时,为了减少网络请求带来的性能开销,通过批量的方式来提交消息,可以通过这个参数来控制批量提交的字节数大小,默认大小是 16384byte,也就是 16kb,意味着当一批消息大小达到指定的 batch.size 的时候会统一发送

LINGER_MS_CONFIG

  Producer 默认会把两次发送时间间隔内收集到的所有 Requests 进行一次聚合然后再发送,以此提高吞吐量,而 linger.ms 就是为每次发送到 broker 的请求增加一些 delay,以此来聚合更多的 Message 请求。 这个有点想 TCP 里面的Nagle 算法,在 TCP 协议的传输中,为了减少大量小数据包的发送,采用了Nagle 算法,也就是基于小包的等-停协议。

Ø BATCH_SIZE_CONFIG 和 LINGER_MS_CONFIG这两个参数是 kafka 性能优化的关键参数,如果两个都配置了,那么怎么工作的呢?实际上,当二者都配置的时候,只要满足其中一个要求,就会发送请求到 broker 上

MAX_REQUEST_SIZE_CONFIG

  设置请求的数据的最大字节数,为了防止发生较大的数据包影响到吞吐量,默认值为 1MB。

Kafka默认是异步发送消息,同步发送消息代码如下:

package com.lf;

import java.util.Properties;

import org.apache.kafka.clients.producer.Callback;
import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.Producer;
import org.apache.kafka.clients.producer.ProducerConfig;
import org.apache.kafka.clients.producer.ProducerRecord;
import org.apache.kafka.clients.producer.RecordMetadata;
import org.apache.kafka.common.serialization.IntegerSerializer;
import org.apache.kafka.common.serialization.StringSerializer; public class KafkaAsyncProducerDemo extends Thread{ private final KafkaProducer<Integer, String> producer; private final String topic ;
private final boolean isAysnc ; public KafkaAsyncProducerDemo(String topic, boolean isAysnc) {
Properties properties = new Properties();
properties.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "192.168.25.129:9092,192.168.25.130:9092,192.168.25.131:9092");
// 客户端ID标识
properties.put(ProducerConfig.CLIENT_ID_CONFIG, "KafkaProducerDemo");
//确认记录,保证记录不丢失 总是设置成-1
properties.put(ProducerConfig.ACKS_CONFIG, "-1");
// 键序列化
properties.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.IntegerSerializer");
//值序列化
properties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringSerializer");
producer = new KafkaProducer<Integer, String>(properties);
this.topic = topic;
this.isAysnc = isAysnc;
}
@Override
public void run() {
int num = 0;
while(num<50){
try {
num++;
String message = "message_" + num;
System.out.println("begin send message" + message);
if(isAysnc){
//异步发送
producer.send(new ProducerRecord<Integer, String>(topic, message), new Callback() { @Override
public void onCompletion(RecordMetadata metadata, Exception exception) {
if(metadata != null){
System.out.println("async-offset:"+metadata.offset()+"->patition"+metadata.partition());
}
}
});
}else{
//同步发送 future /callable get()方法会阻塞
RecordMetadata recordMetadata = producer.send(new ProducerRecord<Integer, String>(topic, message)).get(); }
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
new KafkaAsyncProducerDemo("lftest").start();
}
}

  

消息消费者:

package com.lf;

import java.util.Collections;
import java.util.Properties; import org.apache.kafka.clients.consumer.ConsumerConfig;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.apache.kafka.clients.consumer.ConsumerRecords;
import org.apache.kafka.clients.consumer.KafkaConsumer;
import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.Producer;
import org.apache.kafka.clients.producer.ProducerConfig;
import org.apache.kafka.clients.producer.ProducerRecord;
import org.apache.kafka.common.serialization.IntegerSerializer;
import org.apache.kafka.common.serialization.StringSerializer; public class KafkaConsumerDemo extends Thread{ private final KafkaConsumer consumer; public KafkaConsumerDemo(String topic) {
Properties properties = new Properties();
// 连接的 kafka 集群地址
properties.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "192.168.25.129:9092,192.168.25.130:9092,192.168.25.131:9092");
// 消费者分组
properties.put(ConsumerConfig.GROUP_ID_CONFIG, "KafkaConsumerDemo");
//确认自动提交
properties.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, "true");
// 自动提交间隔
properties.put(ConsumerConfig.AUTO_COMMIT_INTERVAL_MS_CONFIG, "1000");
// 键序列化
properties.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.IntegerDeserializer");
// 值序列化
properties.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringDeserializer");
//对于不同的groupid保证能消费到之前的消息,充值offset
properties.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest");
consumer = new KafkaConsumer(properties);
consumer.subscribe(Collections.singletonList(topic));
}
@Override
public void run() {
while(true){
ConsumerRecords<Integer,String> consumerRecords = consumer.poll(1000);
for(ConsumerRecord consumerRecord: consumerRecords){
System.out.println("message_"+consumerRecord.value());
}
}
}
public static void main(String[] args) {
new KafkaConsumerDemo("lftest").start();
}
}

  

消费端的常用可选配置:

GROUP_ID_CONFIG:

  consumer group 是 kafka 提供的可扩展且具有容错性的消费者机制。既然是一个组,那么组内必然可以有多个消费者或消费者实例(consumer instance),它们共享一个公共的 ID,即 group ID。组内的所有消费者协调在一起来消费订阅主题(subscribed topics)的所有分区(partition)。当然,每个分区只能由同一个消费组内的一个 consumer 来消费.如下图所示,分别有三个消费者,属于两个不同的 group,那么对于 firstTopic 这个 topic 来说,这两个组的消费者都能同时消费这个 topic 中的消息,对于此事的架构来说,这个 firstTopic 就类似于 ActiveMQ 中的 topic 概念。如下图所示,如果 3 个消费者都属于同一个group,那么此事 firstTopic 就是一个 Queue 的概念

ENABLE_AUTO_COMMIT_CONFIG:

  消费者消费消息以后自动提交,只有当消息提交以后,该消息才不会被再次接收到,还可以配合 auto.commit.interval.ms 控制自动提交的频率。当然,我们也可以通过 consumer.commitSync()的方式实现手动提交

AUTO_OFFSET_RESET_CONFIG:

  这个参数是针对新的 groupid 中的消费者而言的,当有新 groupid 的消费者来消费指定的 topic 时,对于该参数的配置,会有不同的语义auto.offset.reset=latest 情况下,新的消费者将会从其他消费者最后消费的offset 处开始消费 Topic 下的消息auto.offset.reset= earliest 情况下,新的消费者会从该 topic 最早的消息开始消费auto.offset.reset=none 情况下,新的消费者加入以后,由于之前不存在offset,则会直接抛出异常。

MAX_POLL_RECORDS_CONFIG:

  此设置限制每次调用 poll 返回的消息数,这样可以更容易的预测每次 poll 间隔要处理的最大值。通过调整此值,可以减少 poll 间隔。

spring集成kafka

生产者配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd"> <bean id="producerProperties" class="java.util.HashMap">
<constructor-arg>
<map>
<entry key="bootstrap.servers"
value="192.168.8.126:9092"/> <entry key="client.id" value="gpmall-sso"/>
<entry key="acks" value="-1"/>
<entry key="key.serializer" value="org.apache.kafka.common.serialization.IntegerSerializer"/>
<entry key="value.serializer" value="org.apache.kafka.common.serialization.StringSerializer"/>
</map>
</constructor-arg>
</bean> <bean id="producerFactory" class="org.springframework.kafka.core.DefaultKafkaProducerFactory">
<constructor-arg ref="producerProperties"/>
</bean> <bean id="kafkaTemplate" class="org.springframework.kafka.core.KafkaTemplate">
<constructor-arg ref="producerFactory"/>
<constructor-arg name="autoFlush" value="true"/>
</bean> </beans>

  消费端配置

  

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd"> <bean id="consumerProperties" class="java.util.HashMap">
<constructor-arg>
<map>
<entry key="bootstrap.servers"
value="192.168.11.153:9092,192.168.11.154:9092,192.168.11.157:9092"/>
<entry key="group.id" value="registryConsumer"/>
<entry key="enable.auto.commit" value="true"/>
<entry key="auto.commit.interval.ms" value="1000"/>
<entry key="key.deserializer" value="org.apache.kafka.common.serialization.IntegerDeserializer"/>
<entry key="value.deserializer" value="org.apache.kafka.common.serialization.StringDeserializer"/>
</map>
</constructor-arg>
</bean> <bean id="consumerFactory" class="org.springframework.kafka.core.DefaultKafkaConsumerFactory">
<constructor-arg ref="consumerProperties"/>
</bean> <bean id="containerProperties" class="org.springframework.kafka.listener.config.ContainerProperties">
<constructor-arg name="topics" value="test"/>
<property name="messageListener" ref="registryListener"/>
</bean> <bean id="messageListenerContainer" class="org.springframework.kafka.listener.KafkaMessageListenerContainer" init-method="doStart">
<constructor-arg ref="consumerFactory"/>
<constructor-arg ref="containerProperties"/>
</bean> </beans>

  

Kafka(1)--kafka基础知识的更多相关文章

  1. Kafka消息系统基础知识索引

    一些观念的修正 从 0.9 版本开始,Kafka 的标语已经从“一个高吞吐量,分布式的消息系统”改为"一个分布式流平台". Kafka不仅仅是一个队列,而且是一个存储,有超强的堆积 ...

  2. RabbitMQ,Apache的ActiveMQ,阿里RocketMQ,Kafka,ZeroMQ,MetaMQ,Redis也可实现消息队列,RabbitMQ的应用场景以及基本原理介绍,RabbitMQ基础知识详解,RabbitMQ布曙

    消息队列及常见消息队列介绍 2017-10-10 09:35操作系统/客户端/人脸识别 一.消息队列(MQ)概述 消息队列(Message Queue),是分布式系统中重要的组件,其通用的使用场景可以 ...

  3. kafka 基础知识梳理及集群环境部署记录

    一.kafka基础介绍 Kafka是最初由Linkedin公司开发,是一个分布式.支持分区的(partition).多副本的(replica),基于zookeeper协调的分布式消息系统,它的最大的特 ...

  4. kafka 基础知识梳理-kafka是一种高吞吐量的分布式发布订阅消息系统

    一.kafka 简介 今社会各种应用系统诸如商业.社交.搜索.浏览等像信息工厂一样不断的生产出各种信息,在大数据时代,我们面临如下几个挑战: 如何收集这些巨大的信息 如何分析它 如何及时做到如上两点 ...

  5. Kafka面试你不得不知道的基础知识

    Java内存管理面试指南一 Java基础面试指南一 Java基础面试指南二 Java基础面试指南三 Java基础面试指南四 Java线程面试指南一 Java线程面试指南二 Redis面试指南一 Kaf ...

  6. kafka 基础知识梳理

    一.kafka 简介 kafka是一种高吞吐量的分布式发布订阅消息系统,它可以处理消费者规模的网站中的所有动作流数据.这种动作(网页浏览,搜索和其他用户的行动)是在现代网络上的许多社会功能的一个关键因 ...

  7. kafka 基础知识梳理(转载)

    一.kafka 简介 kafka是一种高吞吐量的分布式发布订阅消息系统,它可以处理消费者规模的网站中的所有动作流数据.这种动作(网页浏览,搜索和其他用户的行动)是在现代网络上的许多社会功能的一个关键因 ...

  8. 大数据基础知识问答----spark篇,大数据生态圈

    Spark相关知识点 1.Spark基础知识 1.Spark是什么? UCBerkeley AMPlab所开源的类HadoopMapReduce的通用的并行计算框架 dfsSpark基于mapredu ...

  9. IM开发基础知识补课(五):通俗易懂,正确理解并用好MQ消息队列

    1.引言 消息是互联网信息的一种表现形式,是人利用计算机进行信息传递的有效载体,比如即时通讯网坛友最熟悉的即时通讯消息就是其具体的表现形式之一. 消息从发送者到接收者的典型传递方式有两种: 1)一种我 ...

  10. 最全的spark基础知识解答

    原文:http://www.36dsj.com/archives/61155 一. Spark基础知识 1.Spark是什么? UCBerkeley AMPlab所开源的类HadoopMapReduc ...

随机推荐

  1. qt+opencv 构建项目时报错——no such file or directory

    构建前,记得,一定一定一定要先点击执行qmake:

  2. 对TSNU网站的初步分析

    这是一个教育网的网站,其中网站的教务子系统,html页面是用表单嵌套来格式化显示样式的,另外还有<div>.<iframe>等等 .在这个上有个form表单,提交的参数有如下几 ...

  3. PHP使用PDO操作数据库的示例

    <pre><?phpheader("Content-type:text/html;charset=utf8");//error_reporting(E_ALL^E ...

  4. 经典问题----最小生成树(prim普里姆贪心算法)

    题目简述:假如有一个无向连通图,有n个顶点,有许多(带有权值即长度)边,让你用在其中选n-1条边把这n个顶点连起来,不漏掉任何一个点,然后这n-1条边的权值总和最小,就是最小生成树了,注意,不可绕成圈 ...

  5. 使用User Primary Email作为GUID的问题

    最近发现有人使用CRM的user primary email作为GUID, 并且做了plugin来控制user primary email. 这样做法是非常有问题而且会影响同名的再次注册的用户. 假如 ...

  6. 19.1 PORT CONTROL DESCRIPTIONS

    [原文] PORT CONFIGURATION REGISTER (GPACON-GPJCON) In S3C2440A, most of the pins are multiplexed pins. ...

  7. GP中Geoprocessor.Execute(string name, IVariantArray parameters, ITrackCancel trackCancel)

    在做一个项目的过程中,发现GP运算方法 Execute(string name, IVariantArray parameters, ITrackCancel trackCancel) 与Execut ...

  8. redhat 开课啦

    今天是三八女神节. 终于开课啦,为考取RHCE准备.

  9. sql server 2005中的分区函数用法(partition by 字段)

    分组取TOP数据是T-SQL中的常用查询, 如学生信息管理系统中取出每个学科前3名的学生.这种查询在SQL Server 2005之前,写起来很繁琐,需要用到临时表关联查询才能取到.SQL Serve ...

  10. 【mark】OS是否使用svc方式分开系统空间和用户空间的优劣

    对于Cortex-M单片机,用户程序调用RTOS系统函数有两种思路: 假设创建任务的RTOS函数是xxx_task_create() 第一类:FreeRTOS.RT-Thread中采用的方法,和调用普 ...