SpringBoot整合Kafka工具類的詳細(xì)代碼
kafka是什么?
Kafka是由Apache軟件基金會開發(fā)的一個開源流處理平臺,由Scala和Java編寫。Kafka是一種高吞吐量的分布式發(fā)布訂閱消息系統(tǒng),它可以處理消費(fèi)者在網(wǎng)站中的所有動作流數(shù)據(jù)。 這種動作(網(wǎng)頁瀏覽,搜索和其他用戶的行動)是在現(xiàn)代網(wǎng)絡(luò)上的許多社會功能的一個關(guān)鍵因素。 這些數(shù)據(jù)通常是由于吞吐量的要求而通過處理日志和日志聚合來解決。 對于像Hadoop一樣的日志數(shù)據(jù)和離線分析系統(tǒng),但又要求實(shí)時處理的限制,這是一個可行的解決方案。Kafka的目的是通過Hadoop的并行加載機(jī)制來統(tǒng)一線上和離線的消息處理,也是為了通過集群來提供實(shí)時的消息。
應(yīng)用場景
- 消息系統(tǒng): Kafka 和傳統(tǒng)的消息系統(tǒng)(也稱作消息中間件)都具備系統(tǒng)解耦、冗余存儲、流量削峰、緩沖、異步通信、擴(kuò)展性、可恢復(fù)性等功能。與此同時,Kafka 還提供了大多數(shù)消息系統(tǒng)難以實(shí)現(xiàn)的消息順序性保障及回溯消費(fèi)的功能。
- 存儲系統(tǒng): Kafka 把消息持久化到磁盤,相比于其他基于內(nèi)存存儲的系統(tǒng)而言,有效地降低了數(shù)據(jù)丟失的風(fēng)險。也正是得益于 Kafka 的消息持久化功能和多副本機(jī)制,我們可以把 Kafka 作為長期的數(shù)據(jù)存儲系統(tǒng)來使用,只需要把對應(yīng)的數(shù)據(jù)保留策略設(shè)置為“永久”或啟用主題的日志壓縮功能即可。
- 流式處理平臺: Kafka 不僅為每個流行的流式處理框架提供了可靠的數(shù)據(jù)來源,還提供了一個完整的流式處理類庫,比如窗口、連接、變換和聚合等各類操作。
下面看下SpringBoot整合Kafka工具類的詳細(xì)代碼。
pom.xml
<dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.12.0</version> </dependency> <dependency> <groupId>org.apache.kafka</groupId> <artifactId>kafka-clients</artifactId> <version>2.6.3</version> </dependency> <dependency> <groupId>fastjson</groupId> <artifactId>fastjson</artifactId> <version>1.2.83</version> </dependency>
工具類
package com.bbl.demo.utils; import org.apache.commons.lang3.exception.ExceptionUtils; import org.apache.kafka.clients.admin.*; 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.ProducerRecord; import org.apache.kafka.common.KafkaFuture; import org.apache.kafka.common.errors.TopicExistsException; import org.apache.kafka.common.errors.UnknownTopicOrPartitionException; import com.alibaba.fastjson.JSONObject; import java.time.Duration; import java.util.*; import java.util.concurrent.ExecutionException; public class KafkaUtils { private static AdminClient admin; /** * 私有靜態(tài)方法,創(chuàng)建Kafka生產(chǎn)者 * @author o * @return KafkaProducer */ private static KafkaProducer<String, String> createProducer() { Properties props = new Properties(); //聲明kafka的地址 props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG,"node01:9092,node02:9092,node03:9092"); //0、1 和 all:0表示只要把消息發(fā)送出去就返回成功;1表示只要Leader收到消息就返回成功;all表示所有副本都寫入數(shù)據(jù)成功才算成功 props.put("acks", "all"); //重試次數(shù) props.put("retries", Integer.MAX_VALUE); //批處理的字節(jié)數(shù) props.put("batch.size", 16384); //批處理的延遲時間,當(dāng)批次數(shù)據(jù)未滿之時等待的時間 props.put("linger.ms", 1); //用來約束KafkaProducer能夠使用的內(nèi)存緩沖的大小的,默認(rèn)值32MB props.put("buffer.memory", 33554432); // properties.put("value.serializer", // "org.apache.kafka.common.serialization.ByteArraySerializer"); // properties.put("key.serializer", // "org.apache.kafka.common.serialization.ByteArraySerializer"); props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer"); props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer"); return new KafkaProducer<String, String>(props); } /** * 私有靜態(tài)方法,創(chuàng)建Kafka消費(fèi)者 * @author o * @return KafkaConsumer */ private static KafkaConsumer<String, String> createConsumer() { Properties props = new Properties(); //聲明kafka的地址 props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG,"node01:9092,node02:9092,node03:9092"); //每個消費(fèi)者分配獨(dú)立的消費(fèi)者組編號 props.put("group.id", "111"); //如果value合法,則自動提交偏移量 props.put("enable.auto.commit", "true"); //設(shè)置多久一次更新被消費(fèi)消息的偏移量 props.put("auto.commit.interval.ms", "1000"); //設(shè)置會話響應(yīng)的時間,超過這個時間kafka可以選擇放棄消費(fèi)或者消費(fèi)下一條消息 props.put("session.timeout.ms", "30000"); //自動重置offset props.put("auto.offset.reset","earliest"); // properties.put("value.serializer", // "org.apache.kafka.common.serialization.ByteArraySerializer"); // properties.put("key.serializer", // "org.apache.kafka.common.serialization.ByteArraySerializer"); props.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer"); props.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer"); return new KafkaConsumer<String, String>(props); } /** * 私有靜態(tài)方法,創(chuàng)建Kafka集群管理員對象 * @author o */ public static void createAdmin(String servers){ Properties props = new Properties(); props.put(AdminClientConfig.BOOTSTRAP_SERVERS_CONFIG,servers); admin = AdminClient.create(props); } /** * 私有靜態(tài)方法,創(chuàng)建Kafka集群管理員對象 * @author o * @return AdminClient */ private static void createAdmin(){ createAdmin("node01:9092,node02:9092,node03:9092"); } /** * 傳入kafka約定的topic,json格式字符串,發(fā)送給kafka集群 * @author o * @param topic * @param jsonMessage */ public static void sendMessage(String topic, String jsonMessage) { KafkaProducer<String, String> producer = createProducer(); producer.send(new ProducerRecord<String, String>(topic, jsonMessage)); producer.close(); } /** * 傳入kafka約定的topic消費(fèi)數(shù)據(jù),用于測試,數(shù)據(jù)最終會輸出到控制臺上 * @author o * @param topic */ public static void consume(String topic) { KafkaConsumer<String, String> consumer = createConsumer(); consumer.subscribe(Arrays.asList(topic)); while (true) { ConsumerRecords<String, String> records = consumer.poll(Duration.ofSeconds(100)); for (ConsumerRecord<String, String> record : records){ System.out.printf("offset = %d, key = %s, value = %s",record.offset(), record.key(), record.value()); System.out.println(); } } } /** * 傳入kafka約定的topic數(shù)組,消費(fèi)數(shù)據(jù) * @author o * @param topics */ public static void consume(String ... topics) { KafkaConsumer<String, String> consumer = createConsumer(); consumer.subscribe(Arrays.asList(topics)); while (true) { ConsumerRecords<String, String> records = consumer.poll(Duration.ofSeconds(100)); for (ConsumerRecord<String, String> record : records){ System.out.printf("offset = %d, key = %s, value = %s",record.offset(), record.key(), record.value()); System.out.println(); } } } /** * 傳入kafka約定的topic,json格式字符串?dāng)?shù)組,發(fā)送給kafka集群 * 用于批量發(fā)送消息,性能較高。 * @author o * @param topic * @param jsonMessages * @throws InterruptedException */ public static void sendMessage(String topic, String... jsonMessages) throws InterruptedException { KafkaProducer<String, String> producer = createProducer(); for (String jsonMessage : jsonMessages) { producer.send(new ProducerRecord<String, String>(topic, jsonMessage)); } producer.close(); } /** * 傳入kafka約定的topic,Map集合,內(nèi)部轉(zhuǎn)為json發(fā)送給kafka集群 <br> * 用于批量發(fā)送消息,性能較高。 * @author o * @param topic * @param mapMessageToJSONForArray */ public static void sendMessage(String topic, List<Map<Object, Object>> mapMessageToJSONForArray) { KafkaProducer<String, String> producer = createProducer(); for (Map<Object, Object> mapMessageToJSON : mapMessageToJSONForArray) { String array = JSONObject.toJSON(mapMessageToJSON).toString(); producer.send(new ProducerRecord<String, String>(topic, array)); } producer.close(); } /** * 傳入kafka約定的topic,Map,內(nèi)部轉(zhuǎn)為json發(fā)送給kafka集群 * @author o * @param topic * @param mapMessageToJSON */ public static void sendMessage(String topic, Map<Object, Object> mapMessageToJSON) { KafkaProducer<String, String> producer = createProducer(); String array = JSONObject.toJSON(mapMessageToJSON).toString(); producer.send(new ProducerRecord<String, String>(topic, array)); producer.close(); } /** * 創(chuàng)建主題 * @author o * @param name 主題的名稱 * @param numPartitions 主題的分區(qū)數(shù) * @param replicationFactor 主題的每個分區(qū)的副本因子 */ public static void createTopic(String name,int numPartitions,int replicationFactor){ if(admin == null) { createAdmin(); } Map<String, String> configs = new HashMap<>(); CreateTopicsResult result = admin.createTopics(Arrays.asList(new NewTopic(name, numPartitions, (short) replicationFactor).configs(configs))); //以下內(nèi)容用于判斷創(chuàng)建主題的結(jié)果 for (Map.Entry<String, KafkaFuture<Void>> entry : result.values().entrySet()) { try { entry.getValue().get(); System.out.println("topic "+entry.getKey()+" created"); } catch (InterruptedException | ExecutionException e) { if (ExceptionUtils.getRootCause(e) instanceof TopicExistsException) { System.out.println("topic "+entry.getKey()+" existed"); } } } } /** * 刪除主題 * @author o * @param names 主題的名稱 */ public static void deleteTopic(String name,String ... names){ if(admin == null) { createAdmin(); } Map<String, String> configs = new HashMap<>(); Collection<String> topics = Arrays.asList(names); topics.add(name); DeleteTopicsResult result = admin.deleteTopics(topics); //以下內(nèi)容用于判斷刪除主題的結(jié)果 for (Map.Entry<String, KafkaFuture<Void>> entry : result.values().entrySet()) { try { entry.getValue().get(); System.out.println("topic "+entry.getKey()+" deleted"); } catch (InterruptedException | ExecutionException e) { if (ExceptionUtils.getRootCause(e) instanceof UnknownTopicOrPartitionException) { System.out.println("topic "+entry.getKey()+" not exist"); } } } } /** * 查看主題詳情 * @author o * @param names 主題的名稱 */ public static void describeTopic(String name,String ... names){ if(admin == null) { createAdmin(); } Map<String, String> configs = new HashMap<>(); Collection<String> topics = Arrays.asList(names); topics.add(name); DescribeTopicsResult result = admin.describeTopics(topics); //以下內(nèi)容用于顯示主題詳情的結(jié)果 for (Map.Entry<String, KafkaFuture<TopicDescription>> entry : result.values().entrySet()) { try { entry.getValue().get(); System.out.println("topic "+entry.getKey()+" describe"); System.out.println("\t name: "+entry.getValue().get().name()); System.out.println("\t partitions: "); entry.getValue().get().partitions().stream().forEach(p-> { System.out.println("\t\t index: "+p.partition()); System.out.println("\t\t\t leader: "+p.leader()); System.out.println("\t\t\t replicas: "+p.replicas()); System.out.println("\t\t\t isr: "+p.isr()); }); System.out.println("\t internal: "+entry.getValue().get().isInternal()); } catch (InterruptedException | ExecutionException e) { if (ExceptionUtils.getRootCause(e) instanceof UnknownTopicOrPartitionException) { System.out.println("topic "+entry.getKey()+" not exist"); } } } } /** * 查看主題列表 * @author o * @return Set<String> TopicList */ public static Set<String> listTopic(){ if(admin == null) { createAdmin(); } ListTopicsResult result = admin.listTopics(); try { result.names().get().stream().map(x->x+"\t").forEach(System.out::print); return result.names().get(); } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); return null; } } public static void main(String[] args) { System.out.println(listTopic()); } }
到此這篇關(guān)于SpringBoot整合Kafka工具類的文章就介紹到這了,更多相關(guān)SpringBoot整合Kafka工具類內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java過濾器filter_動力節(jié)點(diǎn)Java學(xué)院整理
這篇文章主要介紹了Java過濾器filter,通過過濾器,可以對來自客戶端的請求進(jìn)行攔截,進(jìn)行預(yù)處理或者對最終響應(yīng)給客戶端的數(shù)據(jù)進(jìn)行處理后再輸出2017-07-07Java實(shí)現(xiàn)斷點(diǎn)續(xù)傳功能的示例代碼
這篇文章主要為大家詳細(xì)介紹了如何利用Java語言實(shí)現(xiàn)網(wǎng)絡(luò)資源的斷點(diǎn)續(xù)傳功能,文中的示例代碼講解詳細(xì),具有一定的學(xué)習(xí)價值,感興趣的可以了解一下2022-10-10如何將JSON字符串?dāng)?shù)組轉(zhuǎn)對象集合
這篇文章主要介紹了如何將JSON字符串?dāng)?shù)組轉(zhuǎn)對象集合,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-06-06SpringBoot使用spring.config.import多種方式導(dǎo)入配置文件
本文主要介紹了SpringBoot使用spring.config.import多種方式導(dǎo)入配置文件,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-05-05在SpringBoot中配置MySQL數(shù)據(jù)庫的詳細(xì)指南
在 Spring Boot 中配置數(shù)據(jù)庫是一個相對簡單的過程,通常涉及到以下幾個步驟:添加數(shù)據(jù)庫驅(qū)動依賴、配置數(shù)據(jù)源屬性、以及可選的配置 JPA(如果使用),下面是小編給大家編寫的一個詳細(xì)的指南,以MySQL 數(shù)據(jù)庫為例,需要的朋友可以參考下2024-12-12SpringBoot項(xiàng)目刪除Bean或者不加載Bean的問題解決
文章介紹了在Spring Boot項(xiàng)目中如何使用@ComponentScan注解和自定義過濾器實(shí)現(xiàn)不加載某些Bean的方法,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),感興趣的朋友一起看看吧2025-01-01SpringCloud OpenFeign基本介紹與實(shí)現(xiàn)示例
OpenFeign源于Netflix的Feign,是http通信的客戶端。屏蔽了網(wǎng)絡(luò)通信的細(xì)節(jié),直接面向接口的方式開發(fā),讓開發(fā)者感知不到網(wǎng)絡(luò)通信細(xì)節(jié)。所有遠(yuǎn)程調(diào)用,都像調(diào)用本地方法一樣完成2023-02-02Java實(shí)現(xiàn)的計(jì)算稀疏矩陣余弦相似度示例
這篇文章主要介紹了Java實(shí)現(xiàn)的計(jì)算稀疏矩陣余弦相似度功能,涉及java基于HashMap的數(shù)值計(jì)算相關(guān)操作技巧,需要的朋友可以參考下2018-07-07