1. 引依赖包
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka</artifactId>
</dependency>
2. 配置类
/**
* @author :yepk
* @version :1.0
* @apiNote :kafka配置
* @date :2020-03-13-10:34
*/
@Configuration
@EnableKafka
@PropertySource("classpath:application.properties")
public class KafkaConfiguration {
@Value("${spring.kafka.bootstrap-servers}")
private String bootstrapServers;
@Value("${spring.kafka.consumer.enable-auto-commit}")
private Boolean autoCommit;
@Value("${spring.kafka.consumer.auto-commit-interval}")
private Integer autoCommitInterval;
@Value("${spring.kafka.consumer.group-id}")
private String groupId;
@Value("${spring.kafka.consumer.max-poll-records}")
private Integer maxPollRecords;
@Value("${spring.kafka.consumer.auto-offset-reset}")
private String autoOffsetReset;
@Value("${spring.kafka.producer.retries}")
private Integer retries;
@Value("${spring.kafka.producer.batch-size}")
private Integer batchSize;
@Value("${spring.kafka.producer.buffer-memory}")
private Integer bufferMemory;
/**
* 生产者配置信息
*/
@Bean
public Map<String, Object> producerConfigs() {
Map<String, Object> props = Maps.newHashMap();
props.put(ProducerConfig.ACKS_CONFIG, "0");
props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServers);
props.put(ProducerConfig.RETRIES_CONFIG, retries);
props.put(ProducerConfig.BATCH_SIZE_CONFIG, batchSize);
props.put(ProducerConfig.LINGER_MS_CONFIG, 1);
props.put(ProducerConfig.BUFFER_MEMORY_CONFIG, bufferMemory);
props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
return props;
}
/**
* 生产者工厂
*/
@Bean
public ProducerFactory<String, String> producerFactory() {
return new DefaultKafkaProducerFactory<>(producerConfigs());
}
/**
* 生产者模板
*/
@Bean
public KafkaTemplate<String, String> kafkaTemplate() {
return new KafkaTemplate<>(producerFactory());
}
/**
* 消费者配置信息
*/
@Bean
public Map<String, Object> consumerConfigs() {
Map<String, Object> props = Maps.newHashMap();
props.put(ConsumerConfig.GROUP_ID_CONFIG, groupId);
props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, autoOffsetReset);
props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServers);
props.put(ConsumerConfig.MAX_POLL_RECORDS_CONFIG, maxPollRecords);
props.put(ConsumerConfig.SESSION_TIMEOUT_MS_CONFIG, 120000);
props.put(ConsumerConfig.REQUEST_TIMEOUT_MS_CONFIG, 180000);
props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
return props;
}
/**
* 消费者批量工程
*/
@Bean
public KafkaListenerContainerFactory<?> batchFactory() {
ConcurrentKafkaListenerContainerFactory<Integer, String> factory = new ConcurrentKafkaListenerContainerFactory<>();
factory.setConsumerFactory(new DefaultKafkaConsumerFactory<>(consumerConfigs()));
//设置为批量消费,每个批次数量在Kafka配置参数中设置ConsumerConfig.MAX_POLL_RECORDS_CONFIG
factory.setBatchListener(true);
return factory;
}
}
3. 生产者自定义类
/**
* @author :yepk
* @version :1.0
* @apiNote :生产者
* @date :2020-03-13-10:38
*/
@Component
public class KafkaProducer {
private final KafkaTemplate<String, String> kafkaTemplate;
public KafkaProducer(KafkaTemplate<String, String> kafkaTemplate) {
this.kafkaTemplate = kafkaTemplate;
}
/**
* 向topic中发送消息
*/
public void send (String topic, String msg) {
kafkaTemplate.send(topic, msg);
}
/**
* 向topic中发送消息
*/
public void send (String topic, List<String> msgs) {
msgs.forEach(msg -> kafkaTemplate.send(topic, msg));
}
}
4. 消费者基类
/**
* @author :yepk
* @version :1.0
* @apiNote :消费者
* @date :2020-03-13-11:02
*/
public abstract class BaseKafkaConsumer {
/***
* @apiNote 消费类
* topics 在配置文件配置 例:spring.kafka.consumer.topic=topic1,topic2
* @author yepk
* @date 2020/3/13 11:06
* @param consumerRecord 消费的消息
*/
@KafkaListener(topics = "#{'${spring.kafka.consumer.topic}'.split(',')}")
public void consumer(ConsumerRecord<String,Object> consumerRecord){
String topic = consumerRecord.topic();
Optional<Object> kafkaMassage = Optional.ofNullable(consumerRecord.value());
if(kafkaMassage.isPresent()){
String msg = (String) kafkaMassage.get();
consume(topic,msg);
}
}
/***
* 继承基础消费类则继承此方法
* @apiNote 消费方法
* @author yepk
* @date 2020/3/13 11:08
* @param topic 主题
* @param msg 消费消息
*/
protected abstract void consume(String topic, String msg);
}
5. 消费子类(具体消费逻辑)
/**
* @author :yepk
* @version :1.0
* @apiNote :消费了
* @date :2020-03-13-11:11
*/
@Service
@Slf4j
public class LogKafkaConsumer extends BaseKafkaConsumer {
@Override
protected void consume(String topic, String msg) {
// 消费逻辑
}
6. 配置文件
### kafka配置
spring.kafka.bootstrap-servers=xxxx:9092
spring.kafka.producer.retries=1
spring.kafka.producer.batch-size=16384
spring.kafka.producer.buffer-memory=33554432
spring.kafka.consumer.group-id=etl
spring.kafka.consumer.auto-offset-reset=earliest
spring.kafka.consumer.max-poll-records=1000
spring.kafka.consumer.auto-commit-interval=1000
spring.kafka.consumer.enable-auto-commit=true
## 消费者消费消息 “,”号分割
spring.kafka.consumer.topic=TOPIC1,TOPIC2,TOPIC3