流式圖表拒絕增刪改查之kafka核心消費(fèi)邏輯上篇
消費(fèi)邏輯
上文 流式圖表框架搭建
框架搭建好之后著手開發(fā)下kafka的核心消費(fèi)邏輯,流式圖表的核心消費(fèi)邏輯就是實(shí)現(xiàn)一個消費(fèi)鏈接池維護(hù)消費(fèi)者客戶端鏈接,將kafka client封裝成Runable任務(wù)提交到線程池里做一個常駐線程,實(shí)時(shí)消費(fèi)數(shù)據(jù),消費(fèi)到數(shù)據(jù)后存到redis中,并通過websocket推送到瀏覽器,瀏覽器刷新圖表實(shí)現(xiàn)流式圖表功能。
代碼設(shè)計(jì)
按照之前的代碼劃分,核心邏輯寫在matrix-core子模塊中,整體結(jié)構(gòu)用maven的父子模塊依賴?yán)^承的特性管理依賴。
maxtrix-core模塊只做kafka client的管理和消費(fèi)邏輯,盡量輕一點(diǎn),只需要引入redis和kafka依賴即可。
<dependency>
<groupId>org.apache.kafka</groupId>
<artifactId>kafka-clients</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>com.uptown</groupId>
<artifactId>matrix-common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
反序列化工具、線程池工具、lombok都放到matrix-common中,具體用google的包,這樣其他內(nèi)部模塊直接引用common模塊即可使用。
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
</dependency>
消費(fèi)池
首先要創(chuàng)建出一個線程池出來,由于我們的業(yè)務(wù)要實(shí)時(shí)監(jiān)聽數(shù)據(jù),所以線程池提交的線程必須是個常駐線程。所以需要重寫線程池的任務(wù)失敗策略和異常處理器。
// 自定義異常處理器,捕獲錯誤日志
@Slf4j
public class ConsumerExceptionHandler implements Thread.UncaughtExceptionHandler {
@Override
public void uncaughtException(Thread t, Throwable e) {
log.error(e.getMessage(), e);
}
}
// 任務(wù)失敗策略
@Slf4j
class ConsumerThreadPoolExecutor extends ThreadPoolExecutor {
ConsumerThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler rejectedExecutionHandler) {
super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, rejectedExecutionHandler);
}
@Override
protected void afterExecute(Runnable r, Throwable t) {
super.afterExecute(r, t);
//若線程執(zhí)行某任務(wù)失敗了,重新提交該任務(wù)
if (t != null) {
log.error("restart kafka consumer task for {}", (Object) t.getStackTrace());
}
execute(r);
}
}
剩下的創(chuàng)建出線程池即可,消費(fèi)邏輯中只需要注入到具體類中即可。
@Data
@Component
@Slf4j
public class KafkaConsumerConfig {
// 線程池維護(hù)線程的最少數(shù)量
@Value(value = "${kafka.core-pool-size:20}")
private int corePoolSize;
// 線程池維護(hù)線程的最大數(shù)量
@Value(value = "${kafka.max-pool-size:20}")
private int maxPoolSize;
// 線程池維護(hù)線程所允許的空閑時(shí)間
@Value(value = "${kafka.keep-alive-time:0}")
private int keepAliveTime;
// 線程池所使用的緩沖隊(duì)列大小
@Value(value = "${kafka.work-queue-size:0}")
private int workQueueSize;
// 統(tǒng)一存放kafka客戶端的map
@Bean
public Map<String, KafkaConsumerRunnable> globalKafkaConsumerThreadMap() {
return Maps.newConcurrentMap();
}
/**
* kafka監(jiān)聽任務(wù) 線程池
*/
@Bean(name = "defaultThreadPool")
public ThreadPoolExecutor defaultThreadPool() {
// 使用google線程工廠 線程掛掉重啟策略
ConsumerExceptionHandler exceptionHandler = new ConsumerExceptionHandler();
ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat("kafka-consumer-%d")
.setUncaughtExceptionHandler(exceptionHandler).build();
return new ConsumerThreadPoolExecutor(
corePoolSize,
maxPoolSize,
keepAliveTime,
TimeUnit.SECONDS,
new LinkedBlockingDeque<>(maxPoolSize),
threadFactory,
new ThreadPoolExecutor.CallerRunsPolicy()
);
}
}
這么搞的主要原因是防止消費(fèi)線程中出現(xiàn)消費(fèi)異常,比如反序列化異常、客戶端監(jiān)聽網(wǎng)絡(luò)異常等,為啥不在任務(wù)中try catch住異常是因?yàn)檫@樣做更優(yōu)雅點(diǎn),讓kafka client和線程的生命綁定一塊,比較好管理。
統(tǒng)一存放kafka客戶端的map算是做一個統(tǒng)計(jì),統(tǒng)計(jì)內(nèi)存中已提交的kafka監(jiān)聽線程數(shù),具體的Runable任務(wù)放在下一篇提供,畢竟上班寫文章容易翻車。
以上就是流式圖表拒絕增刪改查之kafka核心消費(fèi)邏輯上篇的詳細(xì)內(nèi)容,更多關(guān)于kafka消費(fèi)流式圖表的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Spring RestTemplate簡化HTTP通信實(shí)現(xiàn)功能探究
這篇文章主要為大家介紹了Spring框架中的RestTemplate,如果你是個Java程序員,那么你肯定知道Spring框架的重要性,在Spring的眾多工具中,RestTemplate是用來簡化HTTP通信的一個強(qiáng)大工具2024-01-01
如何使用Java調(diào)用Linux系統(tǒng)命令
這篇文章主要介紹了如何使用Java調(diào)用Linux系統(tǒng)命令,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-11-11
解決nacos項(xiàng)目啟動報(bào)錯:Connection refused: no further&
這篇文章主要介紹了解決nacos項(xiàng)目啟動報(bào)錯:Connection refused: no further informa問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-04-04
SpringMVC結(jié)合ajaxfileupload.js實(shí)現(xiàn)文件無刷新上傳
這篇文章主要介紹了SpringMVC結(jié)合ajaxfileupload.js實(shí)現(xiàn)文件無刷新上傳,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-10-10
Java用數(shù)組實(shí)現(xiàn)循環(huán)隊(duì)列的示例
下面小編就為大家?guī)硪黄狫ava用數(shù)組實(shí)現(xiàn)循環(huán)隊(duì)列的示例。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-09-09
java使用socket實(shí)現(xiàn)一個多線程web服務(wù)器的方法
今天小編就為大家分享一篇java使用socket實(shí)現(xiàn)一個多線程web服務(wù)器的方法,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-10-10
Maven?項(xiàng)目用Assembly打包可執(zhí)行jar包的方法
這篇文章主要介紹了Maven?項(xiàng)目用Assembly打包可執(zhí)行jar包的方法,該方法只可打包非spring項(xiàng)目的可執(zhí)行jar包,需要的朋友可以參考下2023-03-03

