1.引入pom坐标
<dependency> <groupId>org.springframework.kafka</groupId> <artifactId>spring-kafka</artifactId> </dependency>
2.在application.yml中新增配置
spring:
kafka: bootstrap-servers: 120.48.21.139:9092 producer: # 发生错误后,消息重发的次数。 retries: 5 #当有多个消息需要被发送到同一个分区时,生产者会把它们放在同一个批次里。该参数指定了一个批次可以使用的内存大小,按照字节数计算。 batch-size: 16384 # 设置生产者内存缓冲区的大小。 buffer-memory: 33554432 # 键的序列化方式 key-serializer: org.apache.kafka.common.serialization.StringSerializer # 值的序列化方式 value-serializer: org.apache.kafka.common.serialization.StringSerializer # acks=0 : 生产者在成功写入消息之前不会等待任何来自服务器的响应。 # acks=1 : 只要集群的首领节点收到消息,生产者就会收到一个来自服务器成功响应。 # acks=all :只有当所有参与复制的节点全部收到消息时,生产者才会收到一个来自服务器的成功响应。 acks: 1 consumer: # 自动提交的时间间隔 在spring boot 2.X 版本中这里采用的是值的类型为Duration 需要符合特定的格式,如1S,1M,2H,5D auto-commit-interval: 1S # 该属性指定了消费者在读取一个没有偏移量的分区或者偏移量无效的情况下该作何处理: # latest(默认值)在偏移量无效的情况下,消费者将从最新的记录开始读取数据(在消费者启动之后生成的记录) # earliest :在偏移量无效的情况下,消费者将从起始位置读取分区的记录 auto-offset-reset: earliest # 是否自动提交偏移量,默认值是true,为了避免出现重复数据和数据丢失,可以把它设置为false,然后手动提交偏移量 enable-auto-commit: false # 键的反序列化方式 key-deserializer: org.apache.kafka.common.serialization.StringDeserializer # 值的反序列化方式 value-deserializer: org.apache.kafka.common.serialization.StringDeserializer listener: # 在侦听器容器中运行的线程数。 concurrency: 5 #listner负责ack,每调用一次,就立即commit ack-mode: manual_immediate missing-topics-fatal: false
3.新增KafkaController
package com.fast.kafka; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.kafka.annotation.KafkaListener; import org.springframework.kafka.core.KafkaTemplate; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @Api(tags = "kafka接口管理") @RestController @RequestMapping @Slf4j public class KafkaController { private static final String topic = "ceshi"; @Autowired private KafkaTemplate kafkaTemplate; @ApiOperation("kafka发送消息") @GetMapping("/send/{input}") public String sendToKafka(@PathVariable String input) { kafkaTemplate.send(topic, input); return "发送成功!" + input; } @KafkaListener(id = "myContainer1", topics = topic, groupId = "group.demo") public void listener(String input) { log.info("接收到的消息为:" + input); } }
4.使用事务两种方式:声明式和注解
声明式事务:默认支持
@ApiOperation("kafka2发送消息") @GetMapping("/send2/{input}") public String sendToKafka2(@PathVariable String input) { kafkaTemplate.executeInTransaction(operations -> { kafkaTemplate.send(topic, "第一条消息:" + input); if ("1".equals(input)) { throw new RuntimeException("消息发送失败!"); } kafkaTemplate.send(topic, "第二条消息:" + input); return "发送成功!" + input; }); return "发送成功!" + input; }
注解式事务:手动开启
kafka:
bootstrap-servers: 120.48.21.139:9092
producer:
# 发生错误后,消息重发的次数。
retries: 5
#当有多个消息需要被发送到同一个分区时,生产者会把它们放在同一个批次里。该参数指定了一个批次可以使用的内存大小,按照字节数计算。
batch-size: 16384
# 设置生产者内存缓冲区的大小。
buffer-memory: 33554432
# 键的序列化方式
key-serializer: org.apache.kafka.common.serialization.StringSerializer
# 值的序列化方式
value-serializer: org.apache.kafka.common.serialization.StringSerializer
# acks=0 : 生产者在成功写入消息之前不会等待任何来自服务器的响应。
# acks=1 : 只要集群的首领节点收到消息,生产者就会收到一个来自服务器成功响应。
# acks=all :只有当所有参与复制的节点全部收到消息时,生产者才会收到一个来自服务器的成功响应。
acks: all
#事务支持
transaction-id-prefix: tx_
@ApiOperation("kafka1发送消息") @GetMapping("/send/{input}") @Transactional(rollbackFor = Exception.class) public String sendToKafka(@PathVariable String input) { kafkaTemplate.send(topic, "第一条消息:" + input); if ("1".equals(input)) { throw new RuntimeException("消息发送失败!"); } kafkaTemplate.send(topic, "第二条消息:" + input); return "发送成功!" + input; }
5.回调函数addCallback
@ApiOperation("kafka1发送消息") @GetMapping("/send/{input}") @Transactional(rollbackFor = Exception.class) public String sendToKafka(@PathVariable String input) { kafkaTemplate.send(topic, "第一条消息:" + input).addCallback(successFlow->{ System.out.println("发送成功调用!"); },failFlow->{ System.out.println("发送失败调用!"); }); if ("1".equals(input)) { throw new RuntimeException("消息发送失败!"); } kafkaTemplate.send(topic, "第二条消息:" + input); return "发送成功!" + input; }