項目代碼已上傳git
https://gitee.com/gangye/springboot_kafka
一.首先安裝zookeeper,kafka的啓動需要依賴zookeeper
1.下載安裝包
http://zookeeper.apache.org/releases.html#download
2.解壓文件進入ZooKeeper目錄,本人加壓路徑: F:\server\apache-zookeeper-3.6.1-bin\conf,將“zoo_sample.cfg”重命名爲“zoo.cfg”
3. 打開“zoo.cfg”找到並編輯dataDir=F:\server\Kafka\apache-zookeeper-3.6.1-bin\data
4.配置環境變量,在path中添加F:\server\Kafka\apache-zookeeper-3.6.1-bin\bin
5.在zoo.cfg文件中修改默認的Zookeeper端口(默認端口2181)
6.在cmd指令中輸入“zkServer”,運行Zookeeper
二.安裝Kafka
1.下載安裝包
http://kafka.apache.org/downloads
注意:下載二進制版本
2. 解壓並進入Kafka目錄,本人:F:\server\Kafka\kafka_2.12-0.11.0.0,進入config目錄找到文件server.properties並打開
3.找到並編輯配置日誌路徑:log.dirs=F:\server\Kafka\kafka_2.12-0.11.0.0\kafka-logs
4.找到並編輯zooKeeper的連接地址端口zookeeper.connect=localhost:2181
5. Kafka會按照默認,在9092端口上運行,並連接zookeeper的默認端口:2181
6.進入Kafka安裝目錄F:\server\Kafka\kafka_2.12-0.11.0.0,按下Shift+右鍵,選擇“打開命令窗口”選項,打開命令行,輸入:
.\bin\windows\kafka-server-start.bat .\config\server.properties
三.測試
1、 創建主題,進入Kafka安裝目錄F:\server\Kafka\kafka_2.12-0.11.0.0,打開命令窗口,打開命令行,輸入:
.\bin\windows\kafka-topics.bat --create --zookeeper localhost:2181 --replication-factor 1 --partitions 1 --topic test
結果:
查看主題輸入:
.\bin\windows\kafka-topics.bat --list --zookeeper localhost:2181
結果:
2.創建生產者,進入Kafka的安裝目錄F:\server\Kafka\kafka_2.12-0.11.0.0,打開命令窗口選項,打開命令行,輸入:
.\bin\windows\kafka-console-producer.bat --broker-list localhost:9092 --topic test
結果:
3.創建消費者,進入Kafka的安裝目錄F:\server\Kafka\kafka_2.12-0.11.0.0,打開命令窗口選項,打開命令行,輸入:
.\bin\windows\kafka-console-consumer.bat --bootstrap-server localhost:9092 --topic test --from-beginning
結果:
四.迴歸正題,Kafka結合SpringBoot
1.創建項目,引入pom依賴
<dependencies>
<!--spring-boot-starter-actuator(健康監控)配置和使用
在生產環境中,需要實時或定期監控服務的可用性。
Spring Boot的actuator(健康監控)功能提供了很多監控所需的接口,可以對應用系統進行配置查看、相關功能統計等。
-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka</artifactId>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.2</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
2.配置生產者的配置文件
#============== kafka ===================
# 指定kafka server的地址,集羣配多個,中間,逗號隔開
spring.kafka.bootstrap-servers=127.0.0.1:9092
#=============== provider =======================
# 寫入失敗時,重試次數。當leader節點失效,一個repli節點會替代成爲leader節點,此時可能出現寫入失敗,
# 當retris爲0時,produce不會重複。retirs重發,此時repli節點完全成爲leader節點,不會產生消息丟失。
spring.kafka.producer.retries=0
# 每次批量發送消息的數量,produce積累到一定數據,一次發送
spring.kafka.producer.batch-size=16384
# produce積累數據一次發送,緩存大小達到buffer.memory就發送數據
spring.kafka.producer.buffer-memory=33554432
#procedure要求leader在考慮完成請求之前收到的確認數,用於控制發送記錄在服務端的持久化,其值可以爲如下:
#acks = 0 如果設置爲零,則生產者將不會等待來自服務器的任何確認,該記錄將立即添加到套接字緩衝區並視爲已發送。在這種情況下,無法保證服務器已收到記錄,並且重試配置將不會生效(因爲客戶端通常不會知道任何故障),爲每條記錄返回的偏移量始終設置爲-1。
#acks = 1 這意味着leader會將記錄寫入其本地日誌,但無需等待所有副本服務器的完全確認即可做出迴應,在這種情況下,如果leader在確認記錄後立即失敗,但在將數據複製到所有的副本服務器之前,則記錄將會丟失。
#acks = all 這意味着leader將等待完整的同步副本集以確認記錄,這保證了只要至少一個同步副本服務器仍然存活,記錄就不會丟失,這是最強有力的保證,這相當於acks = -1的設置。
#可以設置的值爲:all, -1, 0, 1
spring.kafka.producer.acks=1
# 指定消息key和消息體的編解碼方式
spring.kafka.producer.key-serializer=org.apache.kafka.common.serialization.StringSerializer
spring.kafka.producer.value-serializer=org.apache.kafka.common.serialization.StringSerializer
注:
- bootstrap.servers:kafka server的地址
- acks:寫入kafka時,leader負責一個該partion讀寫,當寫入partition時,需要將記錄同步到repli節點,all是全部同步節點都返回成功,leader才返回ack。
- retris:寫入失敗時,重試次數。當leader節點失效,一個repli節點會替代成爲leader節點,此時可能出現寫入失敗,當retris爲0時,produce不會重複。retirs重發,此時repli節點完全成爲leader節點,不會產生消息丟失。
- batch.size:produce積累到一定數據,一次發送。
- buffer.memory:produce積累數據一次發送,緩存大小達到buffer.memory就發送數據。
- linger.ms:當設置了緩衝區,消息就不會即時發送,如果消息總不夠條數、或者消息不夠buffer大小就不發送了嗎?當消息超過linger時間,也會發送。
- key/value serializer:序列化類。
3.生產者香kafka發送消息
@Slf4j
@RestController
@RequestMapping(value = "kafkaProducer")
public class KafkaProducerController {
@Autowired
private KafkaTemplate<String ,Object> kafkaTemplate;
private Gson gson = new GsonBuilder().create();
@GetMapping(value = "/sendMessage")
public Response sendMessage(){
Response response = Response.newResponse();
Message message = new Message();
message.setId(System.currentTimeMillis());
message.setMessage(UUID.randomUUID().toString());
message.setSendTime(new Date());
log.info("+++++++++++++++++++++ message = {}", gson.toJson(message));
kafkaTemplate.send("testTopic",gson.toJson(message));
return response.OK();
}
}
4.在消費者項目中配置文件信息
#============== kafka ===================
# 指定kafka server的地址,集羣配多個,中間,逗號隔開
spring.kafka.bootstrap-servers=127.0.0.1:9092
#=============== consumer =======================
# 指定默認消費者group id --> 由於在kafka中,同一組中的consumer不會讀取到同一個消息,依靠groud.id設置組名
spring.kafka.consumer.group-id=testGroup
# smallest和largest纔有效,如果smallest重新0開始讀取,如果是largest從logfile的offset讀取。一般情況下我們都是設置smallest
spring.kafka.consumer.auto-offset-reset=earliest
# enable.auto.commit:true --> 設置自動提交offset
spring.kafka.consumer.enable-auto-commit=true
#如果'enable.auto.commit'爲true,則消費者偏移自動提交給Kafka的頻率(以毫秒爲單位),默認值爲5000。
spring.kafka.consumer.auto-commit-interval=100
# 指定消息key和消息體的編解碼方式
spring.kafka.consumer.key-deserializer=org.apache.kafka.common.serialization.StringDeserializer
spring.kafka.consumer.value-deserializer=org.apache.kafka.common.serialization.StringDeserializer
5.消費者監聽topic=testTopic的消息
@Slf4j
@Component
public class ConsumerListener {
@KafkaListener(topics = "testTopic")
public void consumeMessage(ConsumerRecord<?,?> record){
Optional<?> kafkaMessage = Optional.ofNullable(record.value());
if (kafkaMessage.isPresent()){
Object message = kafkaMessage.get();
log.info("----------------- record =" + record);
log.info("----------------- message =" + message);
}
}
}
6.啓動生產者和消費者項目
注:啓動項目之前,必須確保zooKeeper和kafka服務啓動成功
首先生產一個記錄,由於是get請求,直接可在瀏覽器測試
可以在生產者以及消費者的項目看到消息日誌:
生產者:
消費者: