跟着官方文档学Spring Boot - 集成Kafka
这将会是一系列的文档,文章中大部分的内容都来自 SpringBoot 2.7.0的官方文档,如果需要则会提供一个最简单的环境搭建方案,每一篇文章的开头我都会列出参考的官方文档的地址,如果可以,请尽可能的阅读原文。
原文链接: Spring Boot Apache Kafka Support
一、 准备环境(如果有部署好的 kafka 请跳过)
将下面的内容保存到 docker-compose.yml 中使用 docker-compose up -d 在本地启动一个kafka
version: "2"
networks:
legacy:
services:
zookeeper:
networks:
- legacy
image: docker.io/bitnami/zookeeper:3.8
ports:
- "2181:2181"
volumes:
- "zookeeper_data:/bitnami"
environment:
- ALLOW_ANONYMOUS_LOGIN=yes
kafka:
image: docker.io/bitnami/kafka:3.2
networks:
legacy:
aliases:
- kafka-network
ports:
- "9092:9092"
volumes:
- "kafka_data:/bitnami"
environment:
- KAFKA_CFG_ZOOKEEPER_CONNECT=zookeeper:2181
- ALLOW_PLAINTEXT_LISTENER=yes
- KAFKA_CFG_LISTENERS=PLAINTEXT://:9092
- KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP=CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT
- KAFKA_CFG_ADVERTISED_LISTENERS=PLAINTEXT://127.0.0.1:9092
depends_on:
- zookeeper
volumes:
zookeeper_data:
driver: local
kafka_data:
driver: local
二、修改代码
Kafka
- 添加依赖
implementation 'org.springframework.kafka:spring-kafka'
- 在
application.properties增加配置
spring.kafka.bootstrap-servers=localhost:9092
spring.kafka.consumer.group-id=myGroup
- 发送消息
Spring 的 KafkaTemplate 是自动配置的, 你可以直接在你的bean中注入它。
@Component
@Slf4j
@RequiredArgsConstructor
public class KafkaService {
private final KafkaTemplate<String, String> kafkaTemplate;
public boolean sendMessage(String message) {
final ListenableFuture<SendResult<String, String>> sendResult = kafkaTemplate.send("test_topic", message);
try {
sendResult.get();
return true;
} catch (InterruptedException | ExecutionException e) {
log.error("kafka 消息发送失败", e);
return false;
}
}
}
- 接收消息
可以对任何一个bean标记@KafkaListener注解来创建一个监听器
@Component
@Slf4j
@RequiredArgsConstructor
public class KafkaService {
private final KafkaTemplate<String, String> kafkaTemplate;
@KafkaListener(topics = "test_topic")
public void onMessageReceived(String message) {
log.info("收到消息:{}", message);
}
}
@KafkaListener 标记的方法可以增加的参数有:
来自于
@KafkaListener源码注释
org.apache.kafka.clients.consumer.ConsumerRecordto access to the raw Kafka message
org.springframework.kafka.support.Acknowledgmentto manually ack@Payload-annotated method arguments including the support of validation
@Header-annotated method arguments to extract a specific header value, defined by KafkaHeaders
@Headers-annotated argument that must also be assignable to java.util.Map for getting access to all headers.
MessageHeaders arguments for getting access to all headers.
MessageHeaderAccessor for convenient access to all method arguments.
Kafka Streams
Spring for Apache Kafka提供了一个factory bean 来创建StreamsBuilder对象并管理流的生命周期。当类路径上有kafka-streams并且KafkaStreams由注解@EnableKafkaStreams启用时,Spring会自动配置需要的KafkaStreamsConfigurationbean
启用Kafka Streams 意味着 application id 和 bootstrap servers 必须配置。前者(application id )如果spring.kafka.streams.application-id没有配置,默认使用 spring.application.name。
使用专用属性提供了其他几个属性;可以使用spring.kafka.streams.properties命名空间设置其他任意Kafka属性。有关更多信息,请参阅Additional Kafka Properties
- 添加依赖
implementation 'org.apache.kafka:kafka-streams'
- 增加配置
spring.kafka.streams.properties.default.key.serde=org.apache.kafka.common.serialization.Serdes$IntegerSerde
spring.kafka.streams.properties.default.value.serde=org.apache.kafka.common.serialization.Serdes$StringSerde
- 增加 bean 配置
@Configuration(proxyBeanMethods = false)
@EnableKafkaStreams
@Slf4j
public class MyKafkaStreamsConfiguration {
@Bean
public KStream<Integer, String> kStream(StreamsBuilder streamsBuilder) {
KStream<Integer, String> stream = streamsBuilder.stream("ks1In");
stream.map(this::uppercaseValue).to("ks1Out", Produced.with(Serdes.Integer(),
new JsonSerde<>()));
return stream;
}
private KeyValue<Integer, String> uppercaseValue(Integer key, String value) {
return new KeyValue<>(key, value.toUpperCase());
}
}
上述代码会从 名为 ks1In topic 导入数据,之后执行 uppercaseValue 方法,将消息的内容转换为大写,之后写回到 ks1Out 这个topic
使用内嵌的Kafka测试
Spring 为 Apache Kafka 提供了一种使用嵌入式Apache Kafka broker 做测试的便捷方法。要使用此功能,请使用Spring-kafka测试模块中的@EmbeddedKafka注释测试类。
要使Spring Boot自动配置与嵌入式Apache Kafka一起工作,嵌入式Kafka broker 地址 重新映射到Apache Kafka的Spring Boot配置属性中。(官方文档提供了好几种,这里只列出一种,更详细的内容可以参考官方文档)
在测试类中增加如下代码:
static {
System.setProperty(EmbeddedKafkaBroker.BROKER_LIST_PROPERTY,
"spring.kafka.bootstrap-servers");
}
完整的测试类代码如下:
@SpringBootTest
@EmbeddedKafka
class KafkaServiceTest {
@Autowired
private KafkaService service;
static {
System.setProperty(EmbeddedKafkaBroker.BROKER_LIST_PROPERTY,
"spring.kafka.bootstrap-servers");
}
@Test
void sendMessage() {
Assert.isTrue(service.sendMessage("test_topic", "test message"), "测试消息发送");
}
}
**嵌入式的Kafka仅能在编写测试代码时使用 **