Kafka系列一

1. Kafka产生的背景

什么是kafka:
Kafka 是一款分布式消息发布和订阅系统,具有高性能、高吞吐量的特点而被广泛应用与大数据传输场景。它是由 LinkedIn 公司开发,使用 Scala 语言编写,之后成为 Apache 基金会的一个顶级项目。
产生背景:
kafka 作为一个消息系统,早起设计的目的是用作 LinkedIn 的活动流(Activity Stream)和运营数据处理管道(Pipeline)。活动流数据是所有的网站对用户的使用情况做分析的时候要用到的最常规的部分,活动数据包括页面的访问量(PV)、被查看内容方面的信息以及搜索内容。这种数据通常的处理方式是先把各种活动以日志的形式写入某种文件,然后周期性的对这些文件进行统计分 析。运营数据指的是服务器的性能数据(CPU、IO 使用率、请求时间、服务日 志等)。
应用场景:
由于 kafka 具有更好的吞吐量、内置分区、冗余及容错性的优点(kafka 每秒可以处理几十万消息),让 kafka 成为了一个很好的大规模消息处理应用的解决方 案。所以在企业级应用长,主要会应用于如下几个方面 :
1》 行为跟踪:kafka 可以用于跟踪用户浏览页面、搜索及其他行为。通过发布订阅模式实时记录到对应的 topic 中,通过后端大数据平台接入处理分析,并做更进一步的实时处理和监控 。
2》 日志收集:一般都会做一 个日志统一收集平台管理 log 日志用来快速查询重要应用的问题。所以很多公司的套路都是 把应用日志几种到 kafka 上,然后分别导入到 es 和 hdfs 上,用来做实时检索分析和离线 统计数据备份等。而另一方面,kafka 本身又提供了很好的 api来集成日志并且做日志收集
在这里插入图片描述

2. kafka的架构

kafka的架构简图如下所示:
在这里插入图片描述
一个kafka集群包含:
若干个Producer,若干个Broker,若干个Consumer Group ,以及一个zookeeper集群。kafka通过zookeeper管理集群配置及服务协同;Producer使用push模式将消息发布到broker中,consumer通过监听使用pull模式从broker订阅并消费消息这是与其他mq中间件不同的点。

kafka架构包含以下组件:

1、话题(Topic):是特定类型的消息流。消息是字节的有效负载(Payload),话题是消息的分类名或种子(Feed)名;
2、生产者(Producer):是能够发布消息到话题的任何对象;
3、服务代理(Broker):已发布的消息保存在一组服务器中,它们被称为代理(Broker)或Kafka集群;
4、消费者(Consumer):可以订阅一个或多个话题,并从Broker拉数据,从而消费这些已发布的消息;
在这里插入图片描述
上图可以看出:生产者将数据发送到Broker代理,Broker代理有多个话题的topic,消息消费者从Broker获取数据。
消费端是通过pull拉取的方式

消息消费者是通过pull的方式,这是kafka与其他中间件的区别

zookeeper在kafka集群中的作用

  • 通过zookeeper来保证系统可用性
  • 借助zookeeper,kafka能够将生产者,消费者,提供者的所有组件在无状态的情况下建立生产者和消费者的订阅关系,并实现生产者与消费者的负载均衡。
    在这里插入图片描述执行流程如下:
    (1)启动zookeeper 的 server
    (2)启动kafka 的 server
    (3)Producer 如果生产了数据,会先通过 zookeeper 找到 broker,然后将数据存放到 broker
    (4)Consumer 如果要消费数据,会先通过 zookeeper 找对应的 broker,然后消费。

3. kafka安装部署及集群部署

当前机器环境如下:104,105,109 部署了kafka,110部署了zookeeper
在这里插入图片描述
kafka单机部署及启动相关步骤
0》需要修改kafka 下config server.properties中: zookeeper.connect=192.168.2.110:2181

1》启动zookeeper:
关闭防火墙:不然2181访问不到:systemctl stop iptables.service
查看端口占用情况:netstat -anp | grep 2181
zookeeper启动:[root@localhost bin]# sh zkServer.sh start …/conf/zoo.cfg

2》启动kafka:
启动:[root@localhost bin]# sh kafka-server-start.sh -daemon …/config/server.properties
创建topic:sh kafka-topics.sh --create --zookeeper 192.168.2.110:2181 --replication-factor 1 -partitions 1 --topic test
创建过程中可能报如下错误:

在这里插入图片描述
解决方案:

需要先启动:
[root@localhost bin]# sh zookeeper-server-start.sh -daemon …/config/zookeeper.properties
有的时候需要去清理日志:rm -rf /tmp/kafka-logs

创建topic完整的操作指令如下
在这里插入图片描述查看topic列表:[root@localhost bin]# sh kafka-topics.sh --list --zookeeper 192.168.2.110:2181

通过命令的方式实现消息的发布及消费
消息的发布:[root@localhost bin]# sh kafka-console-producer.sh --broker-list localhost:9092 --topic test
在这里插入图片描述
消息的消费:[root@localhost bin]# sh kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic test --from-beginning
在这里插入图片描述
集群部署:
修改 server.properties 配置

  1. 修改 server.properties.zookeeper.connect=192.168.2.110:2181
  2. 修改 server.properties. broker.id=0 / 1 /2
  3. 修改 server.properties 修改成本机 IP advertised.listeners=PLAINTEXT://192.168.2.104:9092
    当 Kafka broker 启动时,它会在 ZK 上注册自己的 IP 和端口号,客户端就通过这个 IP 和端口号来连接

zookeeper查看kafka集群部署情况:
切换到客户端:[root@localhost bin]# sh zkCli.sh
查看broker:id : [zk: localhost:2181(CONNECTED) 1] ls /brokers/ids
查看主节点信息: [zk: localhost:2181(CONNECTED) 3] get /controller
在这里插入图片描述

4. kafka的Api基本操作

(1)导入pom依赖
在这里插入图片描述
(2)Demo结构:
在这里插入图片描述
(3)消息生产者代码:

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.2.104:9092,192.168.2.105:9092,192.168.2.109:9092");
        properties.put(ProducerConfig.CLIENT_ID_CONFIG,"KafkaProducerDemo");
        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){
            String message = "message_" + num;
            System.out.println("begin send message: "+ message);
            producer.send(new ProducerRecord<>(topic,message));
            num++;
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    public static void main(String[] args) {
        new KafkaProducerDemo("test").start();
    }
}

(4)消息消费者代码:

public class KafkaConsumerDemo extends Thread{
    private final KafkaConsumer kafkaConsumer;
    public KafkaConsumerDemo(String topic){
        Properties properties = new Properties();
        properties.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG,
                "192.168.2.104:9092,192.168.2.105:9092,192.168.2.109:9092");
        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");
        //
        properties.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG,"earliest");
        kafkaConsumer = new KafkaConsumer(properties);

        kafkaConsumer.subscribe(Collections.singletonList(topic));
    }
    @Override
    public void run() {
        while (true){
            ConsumerRecords<Integer,String> consumerRecord = kafkaConsumer.poll(1000);
            for (ConsumerRecord record: consumerRecord) {
                System.out.println("message receive: "+ record.value());
            }
        }
    }
    public static void main(String[] args) {
        new KafkaConsumerDemo("test").start();
    }
}

5. kafka的Api相关配置参数详解

发送端的可选配置信息分析
(1)Acks: 表示producer发送消息到broker上以后的确认值。
有三个选项:
 - 0 : 表示producer不需要等待broker的消息确认。这个选项时延最小但风险最大(因为当server宕机时,数据将会丢失)
 - 1 : 表示producer只需要获得kafka集群中的leader节点确认即可,这个选项时延较小同时确保了leader节点确认接收成功
 - all(-1): 表示需要ISR中所有的Replica给予接收确认,速度最慢,安全性最高;但由于ISR可能会缩小到仅包含一个Replica,所以设置为all并不能一定避免数据的丢失。

(2)batch.size
生产者发送多个消息到 broker 上的同一个分区时,为了减少网络请求带来的性能开销,通过批量的方式来提交消息,可以通过这个参数来控制批量提交的字节数大小,默认大小是 16384byte,也就是 16kb,意味着当一批消息大小达到指定batch.size 的时候会统一发送
(3)linger.ms
Producer默认会把两次发送时间间隔内收集到的所有Requests进行一次聚合然后再发送,以此提高吞吐量;而linger.ms就是为每次发送到broker的请求增加一些delay,以此来聚合更多的Message请求。

	<font color = "red">batch.size 和 linger.ms 这两个参数是 kafka 性能优化的关键参数,当二者都配置的时候,只要满足其中一个要求,就会发送请求到 broker 上</font>

(4)max.request.size
设置请求的数据的最大字节数,为了防止发生较大的数据包影响到吞吐量,默认值为 1MB

接收端的可选配置信息分析
(1) group.id:

对于消息的消费:同一组内竞争,组外不影响

consumer group 是 kafka 提供的可扩展且具有容错性的消费者机制。既然是一个组,那么组内必然可以有多个消费者或消费者实例(consumer instance),它们共享一个公共的 ID,即 group ID。组内的所有消费者协调在一起来消费订阅(subscribed topics)的所有分区(partition)。

当然,每个分区只能由同一个消费组内的一个 consumer 来消费。如图1所示,分别有三个消费者,属于两个不同的 group,那么对于 firstTopic 这个 topic 来说,这两个组的消费者都能同时消费这个 topic 中的消息,对于此事的架构来说,这个 firstTopic 就类似于 ActiveMQ 中的 topic 概念。如图2所示,如果 3 个消费者都属于同一个group,那么此事 firstTopic 就是一个 Queue 的概念.

对于图一group2中只有一个消费者能够消费消息在这里插入图片描述

(2)enable.auto.commit
消费者消费消息以后自动提交,只有当消息提交以后,该消息才不会被再次接收到,还可以配合 auto.commit.interval.ms 控制自动提交的频率。当然,我们也可以通过 consumer.commitSync()的方式实现手动提交
(3)auto.offset.reset
这个参数是针对新的 groupid 中的消费者而言的,当有新 groupid 的消费者来消费指定的 topic 时,对于该参数的配置,会有不同的语义.
auto.offset.reset=latest 情况下,新的消费者将会从其他消费者最后消费的offset 处开始消费 Topic 下的消息
auto.offset.reset= earliest 情况下,新的消费者会从该 topic 最早的消息开始消费
auto.offset.reset=none 情况下,新的消费者加入以后,由于之前不存在offset,则会直接抛出异常。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值