kafka重试实例-生产端重试,消费端重试

消费端异常重试

通过listenter中errorhandler监听异常进行重试。

 @KafkaListener(errorHandler = "consumerAwareListenerErrorHandler")
package cn.gov.chinatax.gt4.szc.sj.sjszzh.listenter;

import cn.gov.chinatax.gt4.szc.sj.sjszzh.common.elasticsearch.ElasticsearchService;
import cn.gov.chinatax.gt4.szc.sj.sjszzh.common.elasticsearch.model.SsRzSsjl;
import cn.gov.chinatax.gt4.szc.sj.sjszzh.pojo.dto.SsContextDTO;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.CollectionType;
import lombok.extern.slf4j.Slf4j;
import org.apache.kafka.clients.consumer.Consumer;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.kafka.listener.ConsumerAwareListenerErrorHandler;
import org.springframework.kafka.listener.ErrorHandler;
import org.springframework.kafka.listener.ListenerExecutionFailedException;
import org.springframework.messaging.Message;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

/**
 * kafka消费时异常重试
 */
@Component
@Slf4j
public class KafkaConsumerListenter{

    public final String ES_INDEX_SS_RZ_KAFKA_FAIL = "ss_rz_kafkasend_fail";
    @Resource
    @Qualifier("kafkaSjSsTemplate")
    private KafkaTemplate kafkaSsTemplate;

    @Resource
    protected ElasticsearchService esService;

    @Bean
    public ConsumerAwareListenerErrorHandler consumerAwareListenerErrorHandler(){
        return new ConsumerAwareListenerErrorHandler() {
            @Override
            public Object handleError(Message<?> message, ListenerExecutionFailedException e, Consumer<?, ?> consumer) {
                if(!ObjectUtil.isEmpty(e)){
                    ObjectMapper objectMapper = new ObjectMapper();
                    List<ConsumerRecord<String, String>> consumerRecords = new ArrayList<>();
                    try {
                        consumerRecords = (List<ConsumerRecord<String, String>>) message.getPayload();
                        for(ConsumerRecord<String, String> t : consumerRecords){
                            SsContextDTO ssContextDTO = objectMapper.readValue(JSONUtil.toJsonStr(t.value()),SsContextDTO.class);
                            ssContextDTO.setKafkasendnum(ssContextDTO.getKafkasendnum()+1);
                            if(ssContextDTO.getKafkasendnum()<3){
                                log.info("topic{},consumer num{}",t.topic(),ssContextDTO.getKafkasendnum());
                                kafkaSsTemplate.send(t.topic(),t.key(),JSONUtil.toJsonStr(ssContextDTO));
                            }else {
                                SsRzSsjl rzSsjl = new SsRzSsjl();
                                rzSsjl.setXwlsh(ssContextDTO.getRowkey());
                                rzSsjl.setRzmx(Arrays.asList(JSONUtil.toJsonStr(ssContextDTO)));
                                esService.saveSsRzSsjl(rzSsjl,ES_INDEX_SS_RZ_KAFKA_FAIL);
                            }
                        }
                    } catch (JsonProcessingException ex) {
                        log.info("consumer message fail");
                        throw new RuntimeException(ex);
                    }

                }else {
                    log.info("consumer message fail");
                }
                return null;
            }
        };
    }
}

生产端异常重试

通过ProducerListener 中onerror进行处理。

package cn.gov.chinatax.gt4.szc.sj.sjszzh.listenter;

import cn.gov.chinatax.gt4.szc.sj.sjszzh.common.elasticsearch.ElasticsearchService;
import cn.gov.chinatax.gt4.szc.sj.sjszzh.common.elasticsearch.model.SsRzSsjl;
import cn.gov.chinatax.gt4.szc.sj.sjszzh.common.utils.SsToolUtils;
import cn.gov.chinatax.gt4.szc.sj.sjszzh.pojo.dto.SsContextDTO;
import cn.hutool.json.JSONUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.kafka.clients.producer.ProducerRecord;
import org.apache.kafka.clients.producer.RecordMetadata;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.kafka.support.ProducerListener;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Arrays;

/**
 * kafka发送时异常重试
 */
@Component
@Slf4j
public class KafkaProducerListenter implements ProducerListener {

    public final String ES_INDEX_SS_RZ_KAFKA_FAIL = "ss_rz_kafkasend_fail";
    @Resource
    @Qualifier("kafkaSjSsTemplate")
    private KafkaTemplate kafkaSsTemplate;

    @Resource
    protected ElasticsearchService esService;

    @Override
    public void onSuccess(ProducerRecord producerRecord, RecordMetadata recordMetadata) {
        log.info("message send sucess:topic:{}",producerRecord.topic());
    }

    @Override
    public void onError(ProducerRecord producerRecord, Exception exception) {
        ObjectMapper objectMapper = new ObjectMapper();
        SsContextDTO ssContextDTO = new SsContextDTO();
        try {
            ssContextDTO = objectMapper.readValue(JSONUtil.toJsonStr(producerRecord.value()), SsContextDTO.class);
        } catch (JsonProcessingException e) {
            log.info("message retry exception"+ SsToolUtils.getExcepitonInfo(e));
            throw new RuntimeException(e);
        }
        ssContextDTO.setKafkasendnum(ssContextDTO.getKafkasendnum()+1);
        if(ssContextDTO.getKafkasendnum()<3){
            log.info("topic{},consumer num{}",producerRecord.topic(),ssContextDTO.getKafkasendnum());
            kafkaSsTemplate.send(producerRecord.topic(),producerRecord.key(),JSONUtil.toJsonStr(ssContextDTO));
        }else {
            SsRzSsjl rzSsjl = new SsRzSsjl();
            rzSsjl.setXwlsh(ssContextDTO.getRowkey());
            rzSsjl.setRzmx(Arrays.asList(JSONUtil.toJsonStr(ssContextDTO)));
            esService.saveSsRzSsjl(rzSsjl,ES_INDEX_SS_RZ_KAFKA_FAIL);
        }
    }
}

监听操作

kafkaSsTemplate.setProducerListener(kafkaProducerListenter);
kafkaSsTemplate.send(yhsjgywxl,  gfdjxh + xfdjxh, CssJsonUtils.toJson(ssContextDTO));

https://blog.csdn.net/yangshangwei/article/details/113846000
https://www.jianshu.com/p/9bf9809b7491

  • 8
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
多线程分区消费Kafka是一种通过多个线程同时消费Kafka消息的方式。在Kafka中,一个主题可以被分成多个分区,每个分区可以由一个或多个消费者线程来消费。以下是一种实现多线程分区消费Kafka的方式: 1. 创建一个Kafka消费实例:使用适当的配置参数创建一个Kafka消费实例,指定要消费的主题和消费者组ID。 2. 获取主题的分区列表:通过调用`consumer.partitionsFor(topic)`方法,获取指定主题的所有分区。 3. 创建消费者线程:根据分区列表创建相应数量的消费者线程。每个线程负责消费一个或多个分区。 4. 启动消费者线程:启动所有的消费者线程,使它们开始消费消息。 5. 消费消息:每个消费者线程在一个无限循环中执行以下操作: - 通过`consumer.poll()`方法获取一批待消费的消息。 - 遍历消息列表,处理每条消息。 - 提交偏移量:在消息处理完成后,通过`consumer.commitSync()`方法提交消费偏移量,确保下次启动时可以继续从上次的位置消费。 6. 处理异常情况:在消费过程中可能会出现异常,如网络故障或处理消息时的错误。你可以根据需要添加异常处理逻辑,比如重新连接Kafka重试消息处理等。 需要注意的是,多线程消费Kafka消息时,需要确保线程之间的同步和并发访问控制,以避免数据竞争和重复消费的问题。可以使用线程安全的数据结构和同步机制来实现这一点。 此外,还可以通过调整消费者线程数量和分区分配策略等参数来优化消费性能。例如,可以根据主题的分区数和消费者线程数来进行分区分配,以实现负载均衡和最大化吞吐量。 希望以上信息对你有所帮助!如果你还有其他问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值