springboot集成Kafka
1、windows安装Kafka
2、添加依赖
<!-- Kafka -->
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka</artifactId>
</dependency>
3、添加配置
在application.yml里,根据需求具体修改,都有注释
spring:
kafka:
bootstrap-servers: localhost:9092
producer:
# 发生错误后,消息重发的次数。
retries: 0
#当有多个消息需要被发送到同一个分区时,生产者会把它们放在同一个批次里。该参数指定了一个批次可以使用的内存大小,按照字节数计算。
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
4、编写Kafka工具
package org.springxxx.modules.xxx.kafka;
import java.sql.SQLException;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.springblade.modules.datatrans.service.IProtocolService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Component;
@Component
public class KafkaMountTask {
@Autowired
IProtocolService iProtocolService;
@Autowired
private KafkaTemplate<String, Object> kafkaTemplate;
// 消费监听生产方。
@KafkaListener(groupId = "group", topics = { "produce5.2" })
public void onMessageTestProduce(ConsumerRecord<?, ?> record) throws SQLException {
// 消费的哪个topic、partition的消息,打印出消息内容
System.out.println("简单消费:" + record.topic() + "-" + record.partition() + "-" + record.value());
// 调用协议中方法
iProtocolService.mountTaskProduce(record.value().toString());
}
// 发送消息给订阅方。
public void sendMessageTestOrder(String msg) {
kafkaTemplate.send("order5.2", msg);
}
}
5、测试使用
package org.springblade.modules.datatrans.controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springblade.common.constant.CustomAppConstant;
import org.springblade.core.boot.ctrl.BladeController;
import org.springblade.core.launch.constant.AppConstant;
import org.springblade.core.tool.api.R;
import org.springblade.modules.datatrans.dto.ProtocolDTO;
import org.springblade.modules.datatrans.dto.ProtocolPageDTO;
import org.springblade.modules.datatrans.entity.Protocol;
import org.springblade.modules.datatrans.service.IProtocolService;
import org.springblade.modules.datatrans.vo.CountProtocolVO;
import org.springblade.modules.datatrans.vo.ProtocolPageVO;
import org.springblade.modules.datatrans.vo.ProtocolVO;
import org.springblade.modules.system.vo.PageVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
/**
* 前端控制器
*/
@RestController
@RequestMapping("/protocol")
@Api(value = "接口", tags = "接口")
public class ProtocolController{
Logger logger = LoggerFactory.getLogger(ProtocolController.class);
private final IProtocolService protocolService;
@Autowired
public ProtocolController(IProtocolService protocolService) {
this.protocolService = protocolService;
}
@Autowired
private KafkaTemplate<String, Object> kafkaTemplate;
@GetMapping("/testSendToKafka")
@ApiOperation(value = "发送消息", notes = "发送消息")
public void testSendToKafka() {
kafkaTemplate.send("test3",
"{\"gradeCode\":\"等级维度编码\",\"spaceCode\":\"空间维度编码\",\"systemCode\":\"系统编码\",\"updateTypeCode\":\"更新方式编码\",\"dataTypeCode\":\"数据类型编码\",\"bussinessCode\":\"业务维度编码\",\"content\":{\"from\":[{\"serverCode\":\"node1\",\"serverIp\":\"127.0.0.1\",\"databases\":[{\"dbCode\":\"db1\",\"dbType\":\"postgreSQL\",\"url\":\"127.0.0.1:5432/xz_test\",\"usr\":\"xz_test\",\"password\":\"xz_test\",\"tables\":[{\"order\":\"1\",\"code\":\"dltb\",\"pks\":\"objectid\",\"filter\":\"dlbm like '21%'\"}]}]}],\"to\":[{\"serverCode\":\"node2\",\"serverIp\":\"192.168.19.111\",\"databases\":[{\"dbCode\":\"db2\",\"dbType\":\"postgreSQL\",\"url\":\"192.168.19.111:5432/xz_test\",\"usr\":\"xz_test\",\"password\":\"xz_test\"}]}]},\"version\":\"变化数据标识(通过数据发生变化的时间来标识)\",\"taskName\":\"任务名称\",\"taskCode\":\"任务编码\",\"source_db_address\":\"源端数据库连接地址\",\"priority\":\"优先级\",\"data_mapping\":\"数据表结构映射关系\",\"to_db_address\":\"订阅端数据库连接地址\"}")
.addCallback(success -> {
// 消息发送到的topic
String topic = success.getRecordMetadata().topic();
// 消息发送到的分区
int partition = success.getRecordMetadata().partition();
// 消息在分区内的offset
long offset = success.getRecordMetadata().offset();
System.out.println("发送消息成功:" + topic + "-" + partition + "-" + offset);
}, failure -> {
System.out.println("发送消息失败:" + failure.getMessage());
});
}
}