All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.jeesuite.kafka.consumer.ErrorMessageProcessor Maven / Gradle / Ivy

/**
 * 
 */
package com.jeesuite.kafka.consumer;

import java.io.Closeable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.jeesuite.common.json.JsonUtils;
import com.jeesuite.kafka.consumer.hanlder.RetryErrorMessageHandler;
import com.jeesuite.kafka.handler.MessageHandler;
import com.jeesuite.kafka.message.DefaultMessage;
import com.jeesuite.kafka.thread.StandardThreadExecutor.StandardThreadFactory;

/**
 * 消费者端处理错误消息重试处理器
 * @description 
* @author vakin * @date 2016年10月25日 */ public class ErrorMessageProcessor implements Closeable{ private static final Logger logger = LoggerFactory.getLogger(ErrorMessageProcessor.class); //重试时间间隔单元(毫秒) private long retryPeriodUnit; private int maxReties; private RetryErrorMessageHandler retryErrorHandler; private final PriorityBlockingQueue taskQueue = new PriorityBlockingQueue(1000); private ExecutorService executor; private AtomicBoolean closed = new AtomicBoolean(false); public int getRetryTaskNums(){ return taskQueue.size(); } public ErrorMessageProcessor(int poolSize,int retryPeriodSeconds,int maxReties,RetryErrorMessageHandler retryErrorHandler) { this.retryPeriodUnit = retryPeriodSeconds * 1000; this.maxReties = maxReties; this.retryErrorHandler = retryErrorHandler; executor = Executors.newFixedThreadPool(poolSize, new StandardThreadFactory("ErrorMessageProcessor")); executor.submit(new Runnable() { @Override public void run() { while(!closed.get()){ try { PriorityTask task = taskQueue.take(); //空任务跳出循环 if(task.getMessage() == null)break; if(task.nextFireTime - System.currentTimeMillis() > 0){ TimeUnit.MILLISECONDS.sleep(1000); taskQueue.put(task); continue; } task.run(); } catch (Exception e) { e.printStackTrace(); } } } }); } public void submit(final DefaultMessage message,final MessageHandler messageHandler){ int taskCount; if((taskCount = taskQueue.size()) > 1000){ logger.warn("ErrorMessageProcessor queue task count over:{}",taskCount); } taskQueue.add(new PriorityTask(message, messageHandler)); } public void close(){ closed.set(true); //taskQueue里面没有任务会一直阻塞,所以先add一个新任务保证执行 taskQueue.add(new PriorityTask(null, null)); try {Thread.sleep(1000);} catch (Exception e) {} executor.shutdown(); logger.info("ErrorMessageDefaultProcessor closed"); } class PriorityTask implements Runnable,Comparable{ final DefaultMessage message; final MessageHandler messageHandler; int retryCount = 0; long nextFireTime; public PriorityTask(DefaultMessage message, MessageHandler messageHandler) { this(message, messageHandler, System.currentTimeMillis() + retryPeriodUnit); } public PriorityTask(DefaultMessage message, MessageHandler messageHandler,long nextFireTime) { super(); this.message = message; this.messageHandler = messageHandler; this.nextFireTime = nextFireTime; } public DefaultMessage getMessage() { return message; } @Override public void run() { try { logger.debug("begin re-process message:"+message.getMsgId()); messageHandler.p2Process(message); } catch (Exception e) { retryCount++; logger.warn("retry[{}] mssageId[{}] error",retryCount,message.getMsgId()); retry(); } } private void retry(){ if(retryCount == maxReties){ if(retryErrorHandler != null){ try { retryErrorHandler.process(ConsumerContext.getInstance().getGroupId(),message.topic(), message); } catch (Exception e) { logger.warn("persistHandler error,topic["+message.topic()+"]",e); } }else{ logger.warn("retry_skip process message[{}] maxReties over {} time error!!!",JsonUtils.toJson(message),maxReties); } return; } nextFireTime = nextFireTime + retryCount * retryPeriodUnit; //重新放入任务队列 taskQueue.add(this); logger.debug("retry_resubmit mssageId[{}] task to queue,next fireTime:{}",this.message.getMsgId(),nextFireTime); } @Override public int compareTo(PriorityTask o) { return (int) (this.nextFireTime - o.nextFireTime); } @Override public String toString() { return "PriorityTask [message=" + message.getMsgId() + ", messageHandler=" + messageHandler.getClass().getSimpleName() + ", retryCount=" + retryCount + ", nextFireTime=" + nextFireTime + "]"; } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy