主要的消息管理者对象:
package com.rynk.mugua.trading.biz.service.impl;
import java.util.concurrent.DelayQueue;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.rynk.commons.entity.QueueMessage;
import com.rynk.mugua.trading.biz.commons.RedisKeyResolver;
import com.rynk.mugua.trading.biz.commons.lock.DistributedLockHandler;
import com.rynk.mugua.trading.biz.eth.DelayedTack;
import lombok.extern.slf4j.Slf4j;
/**
* 延时消息管理员
* @author ZHANGYUKUNUP
*
*/
@Component
@Slf4j
public class QueueManger {
MessagePersistent messagePersistent;
/**
* 延时消息队列
*/
private DelayQueue dQueue = new DelayQueue<>();
/**
* 消息任务处理线程
*/
private Thread taskThread;
@Autowired
DistributedLockHandler lock;
public QueueManger() {
taskThread = new TaskThread();
taskThread.start();
}
/**
* 任务线程
* @author ZHANGYUKUNUP
*
*/
class TaskThread extends Thread{
@Override
public void run() {
while (true) {
try {
DelayedTack delayedTack = dQueue.take();
QueueMessage queueMessage = delayedTack.getQueueMessage();
if( queueMessage == null ) {
return ;
}
//简单的加个锁保证消息不被重复消费(需要保证解锁前 数据被提交到数据库,否者会出同步问题 ,也就是说不能有更加大的 事务范围 包裹当前方法 )
if( lock.tryLock( RedisKeyResolver.getMsgrKey( queueMessage.getId() ) ) ) {
//如果这个消息被正常消费,那么久标记消费成功,如果异常消费,那么久重试这个消息
try {
if( QueueManger.this.messageDispense(delayedTack.getQueueMessage()) ) {
messagePersistent.succeed( queueMessage );
}else {
QueueManger.this.reTry( queueMessage );
}
}catch (Exception e) {
e.printStackTrace();
QueueManger.this.reTry(queueMessage);
}finally {
lock.unLock( RedisKeyResolver.getMsgrKey( queueMessage.getId() ) );
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
/**
* 重试
* @param queueMessage
*/
protected void reTry(QueueMessage queueMessage) {
messagePersistent.reTry(queueMessage);
}
/**
* 分发消息
* @param queueMessage
*/