Spring boot 自定义kafkaTemplate的bean实例进行生产消息和发送消息
本文为博主原创,未经允许不得转载:
目录:
1. 自定义生产消息 kafkaTemplate 实例
2. 封装 kafka 发送消息的service 方法
3. 测试 kafka 发送消息service 的方法
4. 自定义 kafka 消费消息的工厂 bean
5. kafka 监听消费消息
1. 自定义 kafkaTemplate 实例
a : 使用 @ConditionalOnProperty 注解属性控制是否加载 kafka 相关初始化配置,因为在项目开发过程中,如kafka 或redis 等工具容易封装为
工具类,被各微服务引用并进行加载。使用 @ConditionalOnProperty 注解的 havingValue 属性可以控制服务中是否进行加载对应的配置。
该属性的值,可在 yaml 配置文件中指定: kafka.used = true 。如果为true 则加载,false则不加载
b. 使用工厂实例生成指定的 kafkaTemplate 实例
package com.example.demo.config; import org.apache.kafka.clients.producer.ProducerConfig;
import org.apache.kafka.common.serialization.StringSerializer;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.kafka.core.DefaultKafkaProducerFactory;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.kafka.core.ProducerFactory; import java.util.HashMap;
import java.util.Map; @Configuration
@ConditionalOnProperty(prefix="kafka",name = "used",havingValue = "true")
public class KafkaTemplateConfig { /**
* Producer Template 配置
*/
@Bean(name="kafkaTemplate")
public KafkaTemplate<String, String> kafkaTemplate() {
return new KafkaTemplate<>(producerFactory());
} /**
* Producer 工厂配置
*/
@Bean
public ProducerFactory<String, String> producerFactory() {
return new DefaultKafkaProducerFactory<>(producerConfigs());
} /**
* Producer 参数配置
*/
@Bean
public Map<String, Object> producerConfigs() {
Map<String, Object> props = new HashMap<>();
// 指定多个kafka集群多个地址
props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "112.125.26.68:9092"); // 重试次数,0为不启用重试机制
props.put(ProducerConfig.RETRIES_CONFIG, 0);
//同步到副本, 默认为1
// acks=0 把消息发送到kafka就认为发送成功
// acks=1 把消息发送到kafka leader分区,并且写入磁盘就认为发送成功
// acks=all 把消息发送到kafka leader分区,并且leader分区的副本follower对消息进行了同步就任务发送成功
props.put(ProducerConfig.ACKS_CONFIG, 1); // 生产者空间不足时,send()被阻塞的时间,默认60s
props.put(ProducerConfig.MAX_BLOCK_MS_CONFIG, 6000);
// 控制批处理大小,单位为字节
props.put(ProducerConfig.BATCH_SIZE_CONFIG, 4096);
// 批量发送,延迟为1毫秒,启用该功能能有效减少生产者发送消息次数,从而提高并发量
props.put(ProducerConfig.LINGER_MS_CONFIG, 1);
// 生产者可以使用的总内存字节来缓冲等待发送到服务器的记录
props.put(ProducerConfig.BUFFER_MEMORY_CONFIG, 40960);
// 消息的最大大小限制,也就是说send的消息大小不能超过这个限制, 默认1048576(1MB)
props.put(ProducerConfig.MAX_REQUEST_SIZE_CONFIG,1048576);
// 键的序列化方式
props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
// 值的序列化方式
props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
// 压缩消息,支持四种类型,分别为:none、lz4、gzip、snappy,默认为none。
// 消费者默认支持解压,所以压缩设置在生产者,消费者无需设置。
props.put(ProducerConfig.COMPRESSION_TYPE_CONFIG,"none");
return props;
} }
2. 封装 kafka 发送消息的service 方法:
package com.example.demo.service; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.concurrent.ListenableFutureCallback; import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException; @Service
public class KafkaProduceService { @Autowired
private KafkaTemplate kafkaTemplate; /**
* producer 同步方式发送数据
*
* @param topic topic名称
* @param message producer发送的数据
*/
public void sendMessageSync(String topic, String message) throws InterruptedException, ExecutionException, TimeoutException {
kafkaTemplate.send(topic, message).get(10, TimeUnit.SECONDS);
} /**
* producer 异步方式发送数据
*
* @param topic topic名称
* @param message producer发送的数据
*/
public void sendMessageAsync(String topic, String message) {
kafkaTemplate.send(topic, message).addCallback(new ListenableFutureCallback() {
@Override
public void onFailure(Throwable throwable) {
System.out.println("success");
}
@Override
public void onSuccess(Object o) {
System.out.println("failure");
}
});
} }
3. 测试 kafka 发送消息service 的方法:
package com.example.demo; import com.example.demo.service.KafkaProduceService;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException; @RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class ProduceServiceTest { @Autowired
private KafkaProduceService producerService; @Test
public void sendMessageSync() throws InterruptedException, ExecutionException, TimeoutException {
producerService.sendMessageSync("test","同步发送消息测试");
} @Test
public void sendMessageAsync() {
producerService.sendMessageAsync("test","异步发送消息测试");
} }
4. 自定义 kafka 消费消息的工厂 bean :
package com.example.demo.config; import org.apache.kafka.clients.consumer.ConsumerConfig;
import org.apache.kafka.common.serialization.StringDeserializer;
import org.springframework.context.annotation.Bean;
import org.springframework.kafka.config.ConcurrentKafkaListenerContainerFactory;
import org.springframework.kafka.config.KafkaListenerContainerFactory;
import org.springframework.kafka.core.ConsumerFactory;
import org.springframework.kafka.core.DefaultKafkaConsumerFactory;
import org.springframework.kafka.listener.ConcurrentMessageListenerContainer; import java.util.HashMap;
import java.util.Map; public class KafkaConsumerConfig {
@Bean
KafkaListenerContainerFactory<ConcurrentMessageListenerContainer<String, String>> kafkaListenerContainerFactory() {
ConcurrentKafkaListenerContainerFactory<String, String>
factory = new ConcurrentKafkaListenerContainerFactory<>();
// 设置消费者工厂
factory.setConsumerFactory(consumerFactory());
// 消费者组中线程数量
factory.setConcurrency(3);
// 拉取超时时间
factory.getContainerProperties().setPollTimeout(3000); // 当使用批量监听器时需要设置为true
factory.setBatchListener(true); return factory;
} // @Bean
public ConsumerFactory<String, String> consumerFactory() {
return new DefaultKafkaConsumerFactory<>(consumerConfigs());
} // @Bean
public Map<String, Object> consumerConfigs() {
Map<String, Object> propsMap = new HashMap<>();
// Kafka地址
propsMap.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "112.125.26.68:9092");
//配置默认分组,这里没有配置+在监听的地方没有设置groupId,多个服务会出现收到相同消息情况
propsMap.put(ConsumerConfig.GROUP_ID_CONFIG, "defaultGroup");
// 是否自动提交offset偏移量(默认true)
propsMap.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, true);
// 自动提交的频率(ms)
propsMap.put(ConsumerConfig.AUTO_COMMIT_INTERVAL_MS_CONFIG, "100");
// Session超时设置
propsMap.put(ConsumerConfig.SESSION_TIMEOUT_MS_CONFIG, "15000");
// 键的反序列化方式
propsMap.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
// 值的反序列化方式
propsMap.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
// offset偏移量规则设置:
// (1)、earliest:当各分区下有已提交的offset时,从提交的offset开始消费;无提交的offset时,从头开始消费
// (2)、latest:当各分区下有已提交的offset时,从提交的offset开始消费;无提交的offset时,消费新产生的该分区下的数据
// (3)、none:topic各分区都存在已提交的offset时,从offset后开始消费;只要有一个分区不存在已提交的offset,则抛出异常
propsMap.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest");
return propsMap;
}
}
5. kafka 监听消费消息:
package com.example.demo.service; import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.stereotype.Component; @Component
public class KafkaConsumerListener { @KafkaListener(topics = {"test"},groupId = "group1",
containerFactory="kafkaListenerContainerFactory")
public void kafkaListener(String message){
System.out.println(message);
} }
Spring boot 自定义kafkaTemplate的bean实例进行生产消息和发送消息的更多相关文章
- Spring boot 自定义 Resolver 支持 interface 类型参数
在编写 RestController 层的代码时,由于数据实体类定义了接口及实现类,本着面向接口编程的原则,我使用了接口作为 RestController 方法的入参. 代码大致如下(省略具体业务部分 ...
- 玩转Spring Boot 自定义配置、导入XML配置与外部化配置
玩转Spring Boot 自定义配置.导入XML配置与外部化配置 在这里我会全面介绍在Spring Boot里面如何自定义配置,更改Spring Boot默认的配置,以及介绍各配置的优先 ...
- Spring Boot 自定义kafka 消费者配置 ContainerFactory最佳实践
Spring Boot 自定义kafka 消费者配置 ContainerFactory最佳实践 本篇博文主要提供一个在 SpringBoot 中自定义 kafka配置的实践,想象这样一个场景:你的系统 ...
- Java 框架面试题-Spring Boot自定义配置与自动配置共存
Spring Boot 是一个快速开发框架,可以简化 Spring 应用程序的开发,其中自定义配置是其中一个非常重要的特性. 在 Spring Boot 中,自定义配置允许开发者以自己的方式来配置应用 ...
- spring boot自定义线程池以及异步处理
spring boot自定义线程池以及异步处理@Async:什么是线程池?线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务.线程池线程都是后台线程.每个线程都使 ...
- Spring Boot 2.X(四):Spring Boot 自定义 Web MVC 配置
0.准备 Spring Boot 不仅提供了相当简单使用的自动配置功能,而且开放了非常自由灵活的配置类.Spring MVC 为我们提供了 WebMvcConfigurationSupport 类和一 ...
- Spring Boot自定义Redis缓存配置,保存value格式JSON字符串
Spring Boot自定义Redis缓存,保存格式JSON字符串 部分内容转自 https://blog.csdn.net/caojidasabi/article/details/83059642 ...
- 峰哥说技术:06-手撸Spring Boot自定义启动器,解密Spring Boot自动化配置原理
Spring Boot深度课程系列 峰哥说技术—2020庚子年重磅推出.战胜病毒.我们在行动 06 峰哥说技术:手撸Spring Boot自定义启动器,解密Spring Boot自动化配置原理 Sp ...
- Spring Boot自定义starter必知必会条件
前言 在目前的Spring Boot框架中,不管是Spring Boot官方还是非官方,都提供了非常多的starter系列组件,助力开发者在企业应用中的开发,提升研发人员的工作效率,Spring Bo ...
- spring boot项目使用mybatis-plus代码生成实例
前言 mybatis-plus官方地址 https://baomidou.com mybatis-plus是mybatis的增强,不对mybatis做任何改变,涵盖了代码生成,自定义ID生成器,快速实 ...
随机推荐
- nginx下的proxy_pass使用
之前的文章说到了,return,rewrite的使用,以及它们的使用场景,今天再来说一种代理的使用,proxy_pass,它属于nginx下的ngx_http_proxy_module模块,没有显示的 ...
- apache+mysql+php环境安装及配置
一.安装mysql 1.yum安装mysql # yum -y install mysql mysql-server 2.安装mariadb,用mariadb来启动数据库,systemctl star ...
- C++ Qt开发:TableView与TreeView组件联动
Qt 是一个跨平台C++图形界面开发库,利用Qt可以快速开发跨平台窗体应用程序,在Qt中我们可以通过拖拽的方式将不同组件放到指定的位置,实现图形化开发极大的方便了开发效率,本章将重点介绍TableVi ...
- MinIO客户端之ls
MinIO提供了一个命令行程序mc用于协助用户完成日常的维护.管理类工作. 官方资料 mc ls 列出本地硬盘上的文件,命令如下: ./mc ls 控制台的输出,如下: [2023-12-14 23: ...
- Python——第二章:列表的增、删、改、查
列表的添加 .append() lst = [] # 向列表末尾添加内容 # append() 追加 lst.append("张绍刚") lst.append("赵本山& ...
- 火爆全网的Log4j 漏洞复现GetShell
目录: 一.搭建环境 1. 首先拉一个docker镜像 2. 然后启动环境 二.获取shell 首先,试验一下DNSLog 1. 准备JNDI注入工具 下载 进入目录打包成jar包 2. 利用 生成p ...
- STM32CubeMX教程8 TIM 通用定时器 - 输出比较
1.准备材料 开发板(STM32F407G-DISC1) ST-LINK/V2驱动 STM32CubeMX软件(Version 6.10.0) keil µVision5 IDE(MDK-Arm) 逻 ...
- K8s和声明式编程
转载:原文链接 认识k8s之后,他的操作模式对我来说是一种很不错的体验.他提供了更接近现实世界的面向对象接口. 什么是k8s? Kubernetes(K8s)是一种开源容器编排平台,用于自动化部署.扩 ...
- ubuntu中vim乱码以及执行shell脚本时出现乱码
vim打开文件中文出现乱码情况,可以参考如下办法: 在vim /usr/share/vim/vimrc文件末尾中加入 (这个vimrc文件是Vim 的系统级配置文件.文档.插件.语法高亮定义.颜色方案 ...
- Java 新技术:虚拟线程使用指南(二)
虚拟线程是在 Java 21 版本中实现的一种轻量级线程.它由 JVM 进行创建以及管理.虚拟线程和传统线程(我们称之为平台线程)之间的主要区别在于,我们可以轻松地在一个 Java 程序中运行大量.甚 ...