流式图表拒绝增删改查之kafka核心消费逻辑上篇

 更新时间:2023年04月12日 15:07:17   作者:在下uptown  
这篇文章主要为大家介绍了流式图表拒绝增删改查之kafka核心消费逻辑详解的上篇,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

消费逻辑

上文 流式图表框架搭建

框架搭建好之后着手开发下kafka的核心消费逻辑,流式图表的核心消费逻辑就是实现一个消费链接池维护消费者客户端链接,将kafka client封装成Runable任务提交到线程池里做一个常驻线程,实时消费数据,消费到数据后存到redis中,并通过websocket推送到浏览器,浏览器刷新图表实现流式图表功能。

代码设计

按照之前的代码划分,核心逻辑写在matrix-core子模块中,整体结构用maven的父子模块依赖继承的特性管理依赖。

maxtrix-core模块只做kafka client的管理和消费逻辑,尽量轻一点,只需要引入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的包,这样其他内部模块直接引用common模块即可使用。

<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
</dependency>

消费池

首先要创建出一个线程池出来,由于我们的业务要实时监听数据,所以线程池提交的线程必须是个常驻线程。所以需要重写线程池的任务失败策略和异常处理器。

// 自定义异常处理器,捕获错误日志
@Slf4j
public class ConsumerExceptionHandler implements Thread.UncaughtExceptionHandler {
   @Override
   public void uncaughtException(Thread t, Throwable e) {
        log.error(e.getMessage(), e);
   }
}
// 任务失败策略
@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);
      //若线程执行某任务失败了,重新提交该任务
      if (t != null) {
         log.error("restart kafka consumer task for {}", (Object) t.getStackTrace());
      }
      execute(r);
   }
}

剩下的创建出线程池即可,消费逻辑中只需要注入到具体类中即可。

@Data
@Component
@Slf4j
public class KafkaConsumerConfig {
    // 线程池维护线程的最少数量
    @Value(value = "${kafka.core-pool-size:20}")
    private int corePoolSize;
    // 线程池维护线程的最大数量
    @Value(value = "${kafka.max-pool-size:20}")
    private int maxPoolSize;
    // 线程池维护线程所允许的空闲时间
    @Value(value = "${kafka.keep-alive-time:0}")
    private int keepAliveTime;
    // 线程池所使用的缓冲队列大小
    @Value(value = "${kafka.work-queue-size:0}")
    private int workQueueSize;
   // 统一存放kafka客户端的map
   @Bean
   public Map<String, KafkaConsumerRunnable> globalKafkaConsumerThreadMap() {
      return Maps.newConcurrentMap();
   }
    /**
     * kafka监听任务 线程池
     */
    @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()
      );
    }
}

这么搞的主要原因是防止消费线程中出现消费异常,比如反序列化异常、客户端监听网络异常等,为啥不在任务中try catch住异常是因为这样做更优雅点,让kafka client和线程的生命绑定一块,比较好管理。

统一存放kafka客户端的map算是做一个统计,统计内存中已提交的kafka监听线程数,具体的Runable任务放在下一篇提供,毕竟上班写文章容易翻车。

以上就是流式图表拒绝增删改查之kafka核心消费逻辑上篇的详细内容,更多关于kafka消费流式图表的资料请关注脚本之家其它相关文章!

相关文章

  • Spring RestTemplate简化HTTP通信实现功能探究

    Spring RestTemplate简化HTTP通信实现功能探究

    这篇文章主要为大家介绍了Spring框架中的RestTemplate,如果你是个Java程序员,那么你肯定知道Spring框架的重要性,在Spring的众多工具中,RestTemplate是用来简化HTTP通信的一个强大工具
    2024-01-01
  • 如何使用Java调用Linux系统命令

    如何使用Java调用Linux系统命令

    这篇文章主要介绍了如何使用Java调用Linux系统命令,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-11-11
  • 解决nacos项目启动报错:Connection refused: no further informa问题

    解决nacos项目启动报错:Connection refused: no further&

    这篇文章主要介绍了解决nacos项目启动报错:Connection refused: no further informa问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-04-04
  • Java文件与Base64之间的转化方式

    Java文件与Base64之间的转化方式

    这篇文章介绍了如何使用Java将文件(如图片、视频)转换为Base64编码,以及如何将Base64编码转换回文件,通过提供具体的工具类实现,作者希望帮助读者更好地理解和应用这一过程
    2025-02-02
  • IDEA整合jeesite4.x及安装教程

    IDEA整合jeesite4.x及安装教程

    本文给大家介绍IDEA整合jeesite4.x及安装教程,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-07-07
  • SpringMVC结合ajaxfileupload.js实现文件无刷新上传

    SpringMVC结合ajaxfileupload.js实现文件无刷新上传

    这篇文章主要介绍了SpringMVC结合ajaxfileupload.js实现文件无刷新上传,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-10-10
  • Java用数组实现循环队列的示例

    Java用数组实现循环队列的示例

    下面小编就为大家带来一篇Java用数组实现循环队列的示例。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-09-09
  • SpringBoot LiteFlow引擎框架使用原理解析

    SpringBoot LiteFlow引擎框架使用原理解析

    LiteFlow是一个轻量且强大的国产规则引擎框架,可用于复杂的组件化业务的编排领域,本文给大家介绍SpringBoot LiteFlow引擎框架的相关操作,感兴趣的朋友跟随小编一起看看吧
    2024-03-03
  • java使用socket实现一个多线程web服务器的方法

    java使用socket实现一个多线程web服务器的方法

    今天小编就为大家分享一篇java使用socket实现一个多线程web服务器的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-10-10
  • Maven 项目用Assembly打包可执行jar包的方法

    Maven 项目用Assembly打包可执行jar包的方法

    这篇文章主要介绍了Maven 项目用Assembly打包可执行jar包的方法,该方法只可打包非spring项目的可执行jar包,需要的朋友可以参考下
    2023-03-03

最新评论