Kafka消息隊列學習筆記(2020.3.20)
前言:
1. 什麼是 Kafka
Kafka 用於構建實時數據管道和流應用。它具有水平可伸縮性,容錯性,快速快速性。
1.1 Kafka
核心功能
- 發佈 / 訂閱 - 發佈 / 訂閱類似於一個消息系統,讀寫流式的數據
- 流處理 - 編寫可擴展的流處理應用,用於實時事件響應
- 存儲 - 將流式數據存儲在一個分佈式、有副本的集羣中
1.2 Kafka
的特性
Kafka 有什麼優點, 爲什麼使用Kafka而不使用其他消息隊列中間件呢? Kafka 具有如下特性:
- 伸縮性 - 隨着數據量增長,可以通過對 Broker 集羣水平擴展來提高系統性能。
- 高性能 - 通過橫向擴展生產者、消費者(通過消費者羣組實現)和 Broker(通過擴展實現系統伸縮性)可以輕鬆處理巨大的消息流。
- 消息持久化 - Kafka 將所有的消息存儲到磁盤,並在結構中對它們進行排序,以便利用順序磁盤讀取,所以消息不會丟失。
1.3 Kafka
具有四個核心API
- 該 Producer API (生產者) - 允許一個應用程序發佈的流式數據至一個或多個 Kafka的主題(
topics
)。 - 該 Consumer API (消費者) - 允許一個應用程序訂閱一個或多個 Kafka Topic(主題),並且對發佈給他們的流式數據進行處理。
- 該 Streams API (流處理器) -允許一個應用程序作爲一個流處理器,從一個或多個主題消耗的輸入流,併產生一個輸出流到一個或多個 Kafka Topic(主題),在輸入輸出流中進行有效的轉換。
- Connector API (連接器) - 允許構建並運行可重用的生產者或者消費者連接Kafka Topic(主題),將 Kafka Topic 連接到已存在的應用程序或數據庫。例如,連接到一個關係型數據庫,捕捉表的所有變更內容。
其他詳細介紹在官網介紹有!
2. 快速入門開始 (kafka版本是2.4.1)
2.1 下載Kafka代碼 (在Windows下安裝使用Kafka)
Kafka控制腳本在Unix和Windows平臺有所不同,在Windows平臺,請使用
bin\windows\
而不是bin/
, 並將腳本擴展名改爲.bat
.
2.2 啓動服務器(windows版)
Kafka 使用 ZooKeeper 如果你還沒有ZooKeeper服務器,你需要先啓動一個ZooKeeper服務器。 您可以通過與kafka打包在一起的便捷腳本來快速簡單地創建一個單節點ZooKeeper實例。
2.3 windows系統上啓動kafka
打包一起的 ZooKeeper
,
進到
kafka_2.11-2.4.1\bin\windows
目錄下,運行cmd
窗口。備註:
..\..\config\zookeeper.properties
: 代表zookeeper
配置文件在此目錄下
D:\Mykafka\kafka_2.11-2.4.1\bin\windows>zookeeper-server-start.bat ..\..\config\zookeeper.properties
[2020-03-20 15:01:37,495] INFO Reading configuration from: config/zookeeper.properties (org.apache.zookeeper.server.quorum.QuorumPeerConfig)
.................
2.4 啓動kafka
依舊在目錄下打開cmd,執行命令
kafka-server-start.bat ..\..\config\server.properties
D:\Mykafka\kafka_2.11-2.4.1\bin\windows>kafka-server-start.bat ..\..\config\server.properties
[2020-03-20 15:01:47,028] INFO Verifying properties (kafka.utils.VerifiableProperties)
[2020-03-20 15:01:47,051] INFO Property socket.send.buffer.bytes is overridden to 1048576 (kafka.utils.VerifiableProperties)
.....
如果遇到命令語法不正確
,需要修改config
文件夾下的zookeeper.properties中dataDir=
與server.properties
中的log.dirs=
。 注意盤符命令使用\\
例如:
dataDir=D:\\Mykafka\\kafka_2.11-2.4.1\\tmp\\zookeeper
log.dirs=D:\\Mykafka\\kafka_2.11-2.4.1\\tmp\\kafka-logs
到此就啓動成功了!
2.5 創建kafka的topic(主題)
創建一個名爲
“mykafkaDemo”
的topic,它有一個分區和一個副本:依舊在\bin\windows目錄下打開
cmd
windows>kafka-topics.bat --create --zookeeper localhost:2181 --replication-factor 1 --partitions 1 --topic mykafkaDemo
Created topic mykafkaDemo. #創建成功後輸出
zookeeper localhost:2181
是指定zookeeper
地址和端口這條命令會創建一個名爲
mykafkaDemo
的topic,有1個分區,每個分區需分配1個副本。或者,您也可將代理配置爲:在發佈的topic不存在時,自動創建topic,而不是手動創建。
現在我們可以運行list(列表)命令來查看這個topic:
windows>kafka-topics.bat --list --zookeeper localhost:2181
mykafkaDemo #成功後輸出
2.6 發送一些消息
Kafka自帶一個命令行客戶端,它從文件或標準輸入中獲取輸入,並將其作爲message(消息)發送到Kafka集羣。默認情況下,每行將作爲單獨的message發送。
運行
producer.bat
,然後在控制檯輸入一些消息以發送到服務器。
windows>kafka-console-producer.bat --broker-list localhost:9092 --topic mykafkaDemo
This is a message
This is another message
如果生產者進程報錯:
[2020-03-20 16:33:47,934] WARN Bootstrap broker 127.0.0.1:9092 disconnected (org.apache.kafka.clients.NetworkClient)
參考: Leader Not Available Kafka in Console Producer
在
config/server.properties
添加以下行:listeners=PLAINTEXT://localhost:9092
- 無需更改advertised.listeners,因爲它從std偵聽器屬性中獲取了值。
2.7 啓動一個consumer
Kafka 還有一個命令行consumer(消費者),將消息轉儲到標準輸出。
windows>kafka-console-consumer.bat --bootstrap-server localhost:9092 --topic mykafkaDemo --from-beginning
3. java
原態方式操作kafka
並沒使用到spring封裝操作的kafka
3.1 依賴:
<dependency>
<groupId>org.apache.kafka</groupId>
<artifactId>kafka-clients</artifactId>
<version>2.4.1</version>
</dependency>
3.2 發送消息
生產者的配置
// 指定生產者的配置
Properties properties = new Properties();
properties.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092");
properties.put(ProducerConfig.ACKS_CONFIG, "all");
properties.put(ProducerConfig.RETRIES_CONFIG, 0);
properties.put(ProducerConfig.BATCH_SIZE_CONFIG, 16384);
properties.put(ProducerConfig.LINGER_MS_CONFIG, 1);
properties.put(ProducerConfig.BUFFER_MEMORY_CONFIG, 33554432);
properties.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG,
"org.apache.kafka.common.serialization.StringSerializer");
properties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG,
"org.apache.kafka.common.serialization.StringSerializer");
//使用配置初始化 Kafka 生產者
Producer<String,String> producer = new KafkaProducer<>(properties);
發送並忽略返回
ProducerRecord<String,String> record = null;
try {
for (int i = 0; i < 100; i++) {
record = new ProducerRecord<>("mykafkaDemo","message"+i,message+i);
producer.send(record);
}
} catch (Exception e) {
e.printStackTrace();
}finally {
producer.close();
}
同步發送和上面例子區別在於多了一個
get
方法,會一直阻塞等待Broker
返回結果。
ProducerRecord<String,String> record = null;
try {
for (int i = 0; i < 100; i++) {
record = new ProducerRecord<>("mykafkaDemo","message"+i,message+i);
producer.send(record).get();
}
} catch (Exception e) {
e.printStackTrace();
}finally {
producer.close();
}
異步發送,相對於其他方式,異步發送在異步返回時可以執行一些操作,如記錄錯誤或者成功日誌
ProducerRecord<String,String> record = null;
try {
for (int i = 0; i < 100; i++) {
record = new ProducerRecord<>("mykafkaDemo","message"+i,message+i);
//使用 send 方法發送異步消息
producer.send(record, new Callback() {
@Override
public void onCompletion(RecordMetadata metadata, Exception exception) {
System.out.println(metadata.toString());
System.out.println(exception.getMessage());
}
});
}
} catch (Exception e) {
e.printStackTrace();
}finally {
producer.close();
}
到此發送消息結束。
3.3 消費消息
消費流程:
- 創建消費者。
- 訂閱主題。除了訂閱主題方式外還有使用指定分組的模式,但是常用方式都是訂閱主題方式。
- 輪詢(監聽)消息。通過 poll 方法輪詢。
- 關閉消費者。在不用消費者之後,會執行 close 操作。close 操作會關閉 socket,並觸發當前消費者羣組的再均衡。
/**
* 創建並獲取消費者
*
* @return KafkaConsumer
* @author: zhihao
* @date: 2020/3/20
*/
public KafkaConsumer<String, String> getConsumer(){
Properties properties = new Properties();
properties.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG,"localhost:9092");
properties.put(ConsumerConfig.GROUP_ID_CONFIG,"test");
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.StringDeserializer");
properties.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG,"org.apache.kafka.common.serialization.StringDeserializer");
//創建kafka消費者
KafkaConsumer<String,String> consumer = new KafkaConsumer<>(properties);
//訂閱主題方式
consumer.subscribe(Arrays.asList("mykafkaDemo"));
return consumer;
}
/**
* 訂閱主題方式 -消費消息
*
* @author: zhihao
* @date: 2020/3/20
*/
@Test
public void consumeMessage(){
//訂閱主題方式
KafkaConsumer<String, String> consumer= this.getConsumer();
consumer.subscribe(Arrays.asList("mykafkaDemo"));
try {
while (true) {
// 接受消息
ConsumerRecords<String, String> records = consumer.poll(Duration.ofMillis(100));
for (ConsumerRecord<String, String> record : records)
System.out.printf("offset = %d, key = %s, value = %s%n", record.offset(), record.key(), record.value());
}
} catch (Exception e) {
e.printStackTrace();
}finally {
//關閉消息
consumer.close();
}
}
消費消息方式
分爲訂閱主題和指定分組兩種方式:
- 消費者分組模式。通過訂閱主題方式時,消費者必須加入到消費者羣組中,即消費者必須有一個自己的分組;
- 獨立消費者模式。這種模式就是消費者是獨立的不屬於任何消費者分組,自己指定消費那些
Partition
。
1、訂閱主題方式, 上面的例子。
consumer.subscribe(Arrays.asList(topic));
2、獨立消費者模式
通過 consumer 的
assign(Collection partitions)
方法來爲消費者指定分區。
/**
* 獨立消費消息
*
* @author: zhihao
* @date: 2020/3/20
*/
@Test
public void consumeMessageS(){
// 1.構建KafkaCustomer
KafkaConsumer<String, String> consumer = this.getConsumer();
// 2.指定分區
// 2.1獲取可用分區
List<PartitionInfo> partitionInfoList = consumer.partitionsFor("mykafkaDemo");
// 2.2指定分區,這裏是指定了所有分區,也可以指定個別的分區
if(null != partitionInfoList){
List<TopicPartition> partitions = new ArrayList();
for(PartitionInfo partitionInfo : partitionInfoList){
partitions.add(new TopicPartition(partitionInfo.topic(),partitionInfo.partition()));
}
consumer.assign(partitions);
}
try {
while (true) {
// 接受消息
ConsumerRecords<String, String> records = consumer.poll(Duration.ofMillis(100));
for (ConsumerRecord<String, String> record : records)
System.out.printf("offset = %d, key = %s, value = %s%n", record.offset(), record.key(), record.value());
// 異步提交
consumer.commitAsync();
}
} catch (Exception e) {
e.printStackTrace();
}finally {
//關閉消息
consumer.close();
}
}
到此叫學習結束了,一般我們都不會使用原生態的操作方式。
1