当前位置: 首页 > news >正文

Spring Boot集成Kafka:最佳实践与详细指南

文章目录

  • 一、生产者
    • 1.引入库
    • 2.配置文件
    • 3.配置类
      • PublicConfig.java
      • MessageProducer.java
    • 4.业务处理类
  • 三、消费者
    • 1.引入库
    • 2.配置类
      • PublicConfig.java
      • MessageConsumer.java
    • 3.业务类

一、生产者

1.引入库

引入需要依赖的jar包,引入POM文件:

 <dependency><groupId>org.apache.kafka</groupId><artifactId>kafka-clients</artifactId>
</dependency>

2.配置文件

配置Kafka的相关参数(或者你项目的cacos或者yaml文件里添加)

以下是一个示例配置:application.properties

ccm.kafka.servers:192.168.1.95:9092,192.168.1.96:9092,192.168.1.97:9092
ccm.kafka.topics.xxx:xxx_content_dev

Tip:建议topic命名规则:租户简称+项目关键词+系统环境的方式,更容易区分

3.配置类

PublicConfig.java

@Data
@Configuration
@ConfigurationProperties(prefix = "ccm.kafka")
//配置信息nacos中配置
public class PublicConfig {private String servers;private String alertTopic;}

MessageProducer.java


@Slf4j
@Component
public class MessageProducer {private Producer producerKafka;@AutowiredPublicConfig publicConfig;/*** 初始化方法*/@PostConstructpublic String init() {Properties props = new Properties();props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, publicConfig.getServers());props.put(CommonClientConfigs.SECURITY_PROTOCOL_CONFIG, "PLAINTEXT");props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringSerializer");props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringSerializer");props.put(ProducerConfig.MAX_BLOCK_MS_CONFIG, String.valueOf(30 * 1000));props.put(ProducerConfig.ACKS_CONFIG, "all");producerKafka = new KafkaProducer(props);log.info("kafka message channel created successfully");return "OK";}public ResponseData send(String content, String topic) {long startTime = System.currentTimeMillis();try {String key = UUID.randomUUID().toString().replace("-", "");ProducerRecord<String, String> kafkaMessage = new ProducerRecord<>(topic, key, content);log.info("MessageProducer send key {},message{}", key, content);Future<RecordMetadata> send = producerKafka.send(kafkaMessage);send.get();log.info("MessageProducer send cost time:{}", System.currentTimeMillis() - startTime);} catch (Exception e) {log.error("MessageProducer Failed to push message:{}", e.getMessage());return ResponseData.errorWithMsg("MessageProducer Failed to push message:" + e.getMessage());}return null;}}

4.业务处理类

示例代码的业务场景:定时生成预警消息发送给下游系统调用。

//启动类注意增加定时注解的支持
@SpringBootApplication
@MapperScan(basePackages = {"com.xx.xx.mapper","com.xx.xx.crawler.mapper"})
@EnableScheduling
public class CATApp {public static void main(String[] args) {SpringApplication.run(CATApp.class,args);}}@Service
@Slf4j
public class CrawlerService {@Scheduled(cron = "${crawler.scheduled.cron:0 */1 * * * ?}") // 每5分钟执行一次//   @Scheduled(cron = "${crawler.scheduled.cron:0 0 0/1 * * ?}") // 每小时执行一次public void crawlAndSaveAlertInfos() {log.info(">>>>>>>>>>>>> crawlAndSaveAlertInfos  ");//替换成具体的业务场景 List<AlertInfo> alertInfos = fetchAlertInfoList();if (!alertInfos.isEmpty()) {for (AlertInfo alertInfo : alertInfos) {//发送预警信息到kafka供下游调用crawlerAlertSyncService.sendCrawlerAlertMsgKafka(alertInfo);}}}
/**** 预警消息通过Kafka异步同步其他应用*/
public interface CrawlerAlertSyncService {void sendCrawlerAlertMsgKafka(AlertInfo alertInfo) ;}@Slf4j
@Service
public class CrawlerAlertSyncServiceImpl implements CrawlerAlertSyncService {@Autowiredprivate MessageProducer messageProducer;@Resourceprivate PublicConfig publicConfig;@Overridepublic void sendCrawlerAlertMsgKafka(AlertInfo alertInfo) {String topic = publicConfig.getAlertTopic();String servers = publicConfig.getServers();log.info("send publish msg to kafka  ,topic:{},bizId:{}", topic, alertInfo.getAlertid());log.info("send publish msg to kafka  ,servers:{}", servers);String content = JSON.toJSONString(alertInfo);log.info("send publish msg to kafka  ,content:{}", content);if (StringUtils.isNotBlank(topic)) {messageProducer.send(content, topic);}}
}

三、消费者

1.引入库

在消费者工程pom文件中配置依赖

 <dependency><groupId>org.apache.kafka</groupId><artifactId>kafka-clients</artifactId>
</dependency>

2.配置类

同样根据该项目情况编写配置类,示例代码中仍为读取naco配置

PublicConfig.java

@Data
@Configuration
@Slf4j
@ConfigurationProperties(prefix = "xman.kafka")
public class PublicConfig {private String servers;private Map<String,String> topics;public String getTopic(String appCode) {if(Objects.isNull(topics) || topics.isEmpty()){return null;}return topics.get(appCode);}private String alertTopic;private String group;
}

MessageConsumer.java

@Slf4j
@Component
public abstract class MessageConsumer {// 用于持续监听kafka消息的专用线程池private ExecutorService threadPool;// 用于持续消费kafka消息的专用线程池private ExecutorService consumerThreadPool;@Resourceprivate PublicConfig publicConfig;/*** 初始化方法*/@PostConstructpublic String init() {MessageConfigField messageConfig = MessageConfigField.builder().servers(publicConfig.getServers()).topic(publicConfig.getAlertTopic()).group(publicConfig.getGroup()).build();if (StringUtils.isBlank(messageConfig.getServers())) {//没有配置kafka信息return "OK";}initThreadPool();KafkaConsumer<String, String> instance = kafkaInstance(messageConfig.getServers(),messageConfig.getGroup(), messageConfig.getTopic(), messageConfig.getClientName(),messageConfig.getUsername(), messageConfig.getPassword());startListen(instance);log.info("ccm kafka消息订阅成功:clientId:" + messageConfig.getClientName());return "OK";}private void initThreadPool() {if (null == threadPool) {log.info("initThreadPool start");threadPool = Executors.newFixedThreadPool(1);log.info("initThreadPool done");}}private void startListen(KafkaConsumer<String, String> consumer) {threadPool.submit(() -> {TenantContext.setContextCode(CommonConstants.TENANT_CODE);while (true) {try {ConsumerRecords<String, String> records = consumer.poll(Duration.ofSeconds(10));if (records == null || records.isEmpty()) {continue;}for (ConsumerRecord<String, String> record : records) {Optional<String> kafkaMessage = Optional.ofNullable(record.value());if (kafkaMessage.isPresent()) {String msg = kafkaMessage.get();if (StringUtils.isNotBlank(msg)) {log.info("msgJson:" + msg);consumeMsg(msg);}}}} catch (Exception e) {TimeUnit.SECONDS.sleep(1);log.error("consume error", e);}}});}public static KafkaConsumer<String, String> kafkaInstance(String servers, String group,String topic, String clientId, String username, String password) {Properties props = new Properties();props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, servers);if (StringUtils.isNotBlank(group)) {props.put(ConsumerConfig.GROUP_ID_CONFIG, group);}props.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, "true");props.put(ConsumerConfig.AUTO_COMMIT_INTERVAL_MS_CONFIG, "1000");props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest");props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG,"org.apache.kafka.common.serialization.StringDeserializer");props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG,"org.apache.kafka.common.serialization.StringDeserializer");KafkaConsumer<String, String> consumer = new KafkaConsumer<>(props);List<String> subscribedTopics = new ArrayList<>();subscribedTopics.add(topic);consumer.subscribe(subscribedTopics);return consumer;}/*** 核心逻辑,由子类继承实现** @param msgData msg*/public abstract void consumeMsg(String msgData) throws Exception;}

3.业务类

@Slf4j
@Service
@RefreshScope
public class CmsInfoConsumer extends MessageConsumer {@Resourceprivate InfoService infoService;@Overridepublic void consumeMsg(String msgData) throws Exception {log.info("CmsWeatherConsumer收到mq消息message:{}", msgData);CcmAlertInfoDTO alertInfoDTO = JSONObject.parseObject(msgData, CcmAlertInfoDTO.class);try {//to_do 处理消费内容infoService.saveInfoContent(alertInfoDTO);} catch (Exception e) {e.printStackTrace();log.info("同步用户消息失败:" + e);}}
}

至此,一个简单的通过kafka同步预警消息的应用就开发完了。

相关文章:

Spring Boot集成Kafka:最佳实践与详细指南

文章目录 一、生产者1.引入库2.配置文件3.配置类PublicConfig.javaMessageProducer.java 4.业务处理类 三、消费者1.引入库2.配置类PublicConfig.javaMessageConsumer.java 3.业务类 一、生产者 1.引入库 引入需要依赖的jar包&#xff0c;引入POM文件&#xff1a; <depend…...

基于Qwen2-VL模型针对LaTeX OCR任务进行微调训练 - 多图推理

基于Qwen2-VL模型针对LaTeX OCR任务进行微调训练 - 多图推理 flyfish 基于Qwen2-VL模型针对LaTeX_OCR任务进行微调训练_-_LoRA配置如何写 基于Qwen2-VL模型针对LaTeX_OCR任务进行微调训练_-_单图推理 基于Qwen2-VL模型针对LaTeX_OCR任务进行微调训练_-_原模型_单图推理 基于Q…...

详解下c语言下的多维数组和指针数组

在实际c语言编程中&#xff0c;三维及以上数组我们使用的很少&#xff0c;二维数组我们使用得较多。说到数组&#xff0c;又不得关联到指针&#xff0c;因为他们两者的联系太紧密了。今天我们就详细介绍下c语言下的多维数组(主要是介绍二维数组)和指针。 一、二维数组 1.1&am…...

免费送源码:Java+ssm+MySQL 基于微服务架构的餐饮系统的设计与实现 计算机毕业设计原创定制

摘 要 近年来,我国经济和社会发展迅速,人们物质生活水平日渐提高,餐饮行业更是发展迅速,人们对于餐饮行业的认识和要求也越来越高。传统形式的餐饮行业都是以人为本,管理起来需要很多人力、物力、财力,既不方便管理者的管理,也不方便顾客实时了解餐厅动态,给传统餐饮行业的经…...

LeetCode hot100-69-N

https://leetcode.cn/problems/valid-parentheses/description/?envTypestudy-plan-v2&envIdtop-100-liked 20. 有效的括号 已解答 简单 相关标签 相关企业 提示 给定一个只包括 (&#xff0c;)&#xff0c;{&#xff0c;}&#xff0c;[&#xff0c;] 的字符串 s &#x…...

【橘子容器】如何构建一个docker镜像

你肯定打过docker镜像是吧&#xff0c;作为一个开发这很正常&#xff0c;那么你用的什么打包方式呢&#xff0c;这里我们来梳理几种常用的docker镜像构建方式。 ps&#xff1a;这里不是太讲原理&#xff0c;更多的是一种科普和操作。因为讲原理的东西网上已经够多了。 一、Dock…...

EFAK kafka可视化管理工具部署使用

简介&#xff1a;EFAK是开源的可视化和管理软件。它允许您查询、可视化、提醒和探索您的指标&#xff0c;无论它们存储在何处。简单来说&#xff0c;它为您提供了将 Kafka 集群数据转换为漂亮的图形和可视化效果的工具。 环境&#xff1a;①操作系统&#xff1a;CentOS7.6&…...

Spring Boot 工程分层实战(五个分层维度)

1、分层思想 计算机领域有一句话&#xff1a;计算机中任何问题都可通过增加一个虚拟层解决。这句体现了分层思想重要性&#xff0c;分层思想同样适用于Java工程架构。 分层优点是每层只专注本层工作&#xff0c;可以类比设计模式单一职责原则&#xff0c;或者经济学比较优势原…...

vscode IntelliSense Configurations

IntelliSense 是一个强大的代码补全和代码分析功能&#xff0c;它可以帮助开发者提高编程效率。图中显示的是 VSCode 的 IntelliSense 配置界面&#xff0c;具体配置如下&#xff1a; Compiler path&#xff08;编译器路径&#xff09;: 这里指定了用于构建项目的编译器的完整路…...

hbase读写操作后hdfs内存占用太大的问题

hbase读写操作后hdfs内存占用太大的问题 查看内存信息hbase读写操作 查看内存信息 查看本地磁盘的内存信息 df -h查看hdfs上根目录下各个文件的内存大小 hdfs dfs -du -h /查看hdfs上/hbase目录下各个文件的内存大小 hdfs dfs -du -h /hbase查看hdfs上/hbase/oldWALs目录下…...

C++----入门篇

引言 C是在C的基础之上&#xff0c;容纳进去了面向对象编程思想&#xff0c;并增加了许多有用的库&#xff0c;以及编程范式等。熟悉C语言之后&#xff0c;对C学习有一定的帮助&#xff0c;本章节主要目标&#xff1a; 1. 补充C语言语法的不足&#xff0c;以及C是如何对C语言…...

C语言程序设计P5-5【应用函数进行程序设计 | 第五节】—知识要点:变量的作用域和生存期

知识要点&#xff1a;变量的作用域和生存期 视频&#xff1a; 目录 一、任务分析 二、必备知识与理论 三、任务实施 一、任务分析 有一个一维数组&#xff0c;内放 10 个学生成绩&#xff0c;写一个函数&#xff0c;求出平均分、最高分和最低分。 任务要求用一个函数来完…...

用 Sass 模块化系统取代全局导入,消除 1.80.0 引入的 @import 弃用警告

目录 前言 问题 import 的缺陷 命名冲突 重复导入 模块系统 use 规则 forward 规则 实际修改 前言 最初&#xff0c;Sass 使用 import 规则通过单个全局命名空间加载其他文件&#xff0c;所有内置函数也可全局使用。由于模块系统&#xff08;use 和 forward 规则&…...

安卓低功耗蓝牙BLE官方开发例程(JAVA)翻译注释版

官方原文链接 https://developer.android.com/develop/connectivity/bluetooth/ble/ble-overview?hlzh-cn 目录 低功耗蓝牙 基础知识 关键术语和概念 角色和职责 查找 BLE 设备 连接到 GATT 服务器 设置绑定服务 设置 BluetoothAdapter 连接到设备 声明 GATT 回…...

搭建fastapi项目

环境准备 # 创建项目目录 mkdir my_fastapi_project cd my_fastapi_project# 创建和激活虚拟环境 python -m venv venv .\venv\Scripts\activate安装必要的包 pip install fastapi uvicorn python-dotenv创建项目基本结构 my_fastapi_project/ │ .env # …...

Maven学习(Maven项目模块化。模块间“继承“机制。父(工程),子项目(模块)间聚合)

目录 一、Maven项目模块化&#xff1f; &#xff08;1&#xff09;基本介绍。 &#xff08;2&#xff09;汽车模块化生产再聚合组装。 &#xff08;3&#xff09;Maven项目模块化图解。 1、maven_parent。 2、maven_pojo。 3、maven_dao。 4、maven_service。 5、maven_web。 6…...

华为云云原生中间件DCS DMS 通过中国信通院与全球IPv6测试中心双重能力检测

近日&#xff0c;中国信息通信研究院&#xff08;以下简称“中国信通院”&#xff09;与全球IPv6测试中心相继宣布&#xff0c;华为云的分布式缓存服务&#xff08;Distributed Cache Service&#xff0c;简称DCS&#xff09;和分布式消息服务&#xff08;Distributed Message …...

PostgreSQL中事件触发器Event Trigger

在PostgreSQL中&#xff0c;事件触发器&#xff08;Event Trigger&#xff09;是一种特殊的触发器类型&#xff0c;它允许你在特定的数据库系统事件发生时执行特定的操作。与普通的触发器不同&#xff0c;事件触发器并不与特定的表或视图相关联&#xff0c;而是与数据库级别的全…...

uni.request流式(Stream)请求,实现打印机效果

最近使用扣子 - 开发指南 (coze.cn)和智谱AI开放平台开发小程序AI导诊和用药对话指南。 开发的过程中也是走了不少坑,下面就来聊聊走了哪些坑。 坑1 :coze试了v2和v3的接口,两个接口请求还是有点差别的,v2拿到了botId和accessToken可以直接请求不需要做任何处理,v3还需要…...

canvas保存图片

需求&#xff1a;上面有几个按钮&#xff0c;其中有一个切换是图片 用v-if会导致图片加载慢 实现方法&#xff1a; 一进来就加载&#xff0c;通过监听元素显示&#xff0c;用于控制canvas的宽高&#xff0c;从而达到隐藏的效果 组件dowolad.vue <template><view …...

UE5 学习系列(二)用户操作界面及介绍

这篇博客是 UE5 学习系列博客的第二篇&#xff0c;在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下&#xff1a; 【Note】&#xff1a;如果你已经完成安装等操作&#xff0c;可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作&#xff0c;重…...

Linux 文件类型,目录与路径,文件与目录管理

文件类型 后面的字符表示文件类型标志 普通文件&#xff1a;-&#xff08;纯文本文件&#xff0c;二进制文件&#xff0c;数据格式文件&#xff09; 如文本文件、图片、程序文件等。 目录文件&#xff1a;d&#xff08;directory&#xff09; 用来存放其他文件或子目录。 设备…...

Appium+python自动化(十六)- ADB命令

简介 Android 调试桥(adb)是多种用途的工具&#xff0c;该工具可以帮助你你管理设备或模拟器 的状态。 adb ( Android Debug Bridge)是一个通用命令行工具&#xff0c;其允许您与模拟器实例或连接的 Android 设备进行通信。它可为各种设备操作提供便利&#xff0c;如安装和调试…...

解锁数据库简洁之道:FastAPI与SQLModel实战指南

在构建现代Web应用程序时&#xff0c;与数据库的交互无疑是核心环节。虽然传统的数据库操作方式&#xff08;如直接编写SQL语句与psycopg2交互&#xff09;赋予了我们精细的控制权&#xff0c;但在面对日益复杂的业务逻辑和快速迭代的需求时&#xff0c;这种方式的开发效率和可…...

【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 初始化服务器)

服务端执行命令请求的过程 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 初始化服务器1. 初始化服务器状态结构初始化RedisServer变量 2. 加载相关系统配置和用户配置参数定制化配置参数案…...

【大模型RAG】Docker 一键部署 Milvus 完整攻略

本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装&#xff1b;只需暴露 19530&#xff08;gRPC&#xff09;与 9091&#xff08;HTTP/WebUI&#xff09;两个端口&#xff0c;即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...

2.Vue编写一个app

1.src中重要的组成 1.1main.ts // 引入createApp用于创建应用 import { createApp } from "vue"; // 引用App根组件 import App from ./App.vue;createApp(App).mount(#app)1.2 App.vue 其中要写三种标签 <template> <!--html--> </template>…...

c++ 面试题(1)-----深度优先搜索(DFS)实现

操作系统&#xff1a;ubuntu22.04 IDE:Visual Studio Code 编程语言&#xff1a;C11 题目描述 地上有一个 m 行 n 列的方格&#xff0c;从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子&#xff0c;但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...

C# 类和继承(抽象类)

抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...

现有的 Redis 分布式锁库(如 Redisson)提供了哪些便利?

现有的 Redis 分布式锁库&#xff08;如 Redisson&#xff09;相比于开发者自己基于 Redis 命令&#xff08;如 SETNX, EXPIRE, DEL&#xff09;手动实现分布式锁&#xff0c;提供了巨大的便利性和健壮性。主要体现在以下几个方面&#xff1a; 原子性保证 (Atomicity)&#xff…...