package com.nuzar.fcms.framework.bizevent.dto;
import org.apache.commons.lang3.time.DateUtils;
import java.time.Clock;
import java.util.concurrent.atomic.AtomicInteger;
/**
* 事件分发统计
*/
public class BizEventDistStat {
private AtomicInteger remainingDistTotal;
private Long eventId;
private long beginTime;
public BizEventDistStat(Long eventId, int expectTotal){
this.eventId = eventId;
this.remainingDistTotal = new AtomicInteger(expectTotal);
this.beginTime = Clock.systemUTC().millis();
}
public Long getEventId(){
return this.eventId;
}
/**
* 完成一次处理,剩余数量扣减一次
*/
public void completeOnce() {
this.remainingDistTotal.decrementAndGet();
}
/**
* 所有分发都完成了 true
* @return
*/
public boolean hasAllCompleted(){
return this.remainingDistTotal.get() <= 0;
}
/**
* 经过了多少时间
* @return
*/
public long elapsedMillisTime(){
return Clock.systemUTC().millis() - this.beginTime;
}
@Override public String toString() {
return "BizEventDistStat{remainingDistTotal=" + remainingDistTotal + ", eventId=" + eventId
+ ", beginTime=" + beginTime + '}';
}
}
package com.nuzar.fcms.framework.bizevent.service;
import com.nuzar.fcms.framework.bizevent.config.BizEventProperties;
import com.nuzar.fcms.framework.bizevent.constant.BizFlowEventRecordStatusEnum;
import com.nuzar.fcms.framework.bizevent.dto.BizEventDistStat;
import com.nuzar.fcms.framework.bizevent.model.BizFlowEventRecord;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import javax.annotation.Resource;
import java.util.List;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.LockSupport;
/**
* 客户端事件分发管道处理器,各个客户端对事件进行选择构建分发事件
*/
@Slf4j
public class AppClientEventDistPipelineProcessor implements InitializingBean {
@Resource IBizFlowEventRecordService bizFlowEventRecordService;
@Resource ClientEventProcessManager clientEventProcessManager;
@Resource BizEventProperties bizEventProperties;
// 统计事件分发情况,根据分发情况进行事件状态的更新
private LinkedBlockingQueue<BizEventDistStat> bizEventDistStatQueue;
public void handle(BizFlowEventRecord event) throws InterruptedException {
// 根据eventType获取当前关注该事件的所有客户端处理列表
List<ClientEventProcessor> processors = clientEventProcessManager.getProcessorsByEventType(event.getEventType());
BizEventDistStat eventDistStat = new BizEventDistStat(event.getId(), processors.size());
bizEventDistStatQueue.put(eventDistStat);
processors.forEach(proc ->{
proc.offerEvent(event, eventDistStat);
});
}
@Override public void afterPropertiesSet() throws Exception {
this.bizEventDistStatQueue = new LinkedBlockingQueue<>(this.bizEventProperties.getBizEventDistStatQueueCapacity());
Thread distStatThread = new Thread(() -> {
for(;;){
try {
BizEventDistStat stat = bizEventDistStatQueue.take(); // when empty then wait next event
if(stat.hasAllCompleted()){
//在什么条件下才更新完成? 当订阅当前事件的处理器数量与分发消息完成数一致时(剩余分发总数为0),则认为分发完成
bizFlowEventRecordService.updateEventStatus(bizFlowEventRecordService.getById(stat.getEventId()),
BizFlowEventRecordStatusEnum.COMPLETED);
}else if(stat.elapsedMillisTime() < bizEventProperties.getDistStatLimitElapsedMillis()){
// 没有完成,在监控有效时间内,继续监控
bizEventDistStatQueue.put(stat);
}else{
// 事件为处理中状态,需要排查,不再监控
log.error("监控到超时分发的事件记录:{}", stat);
}
}catch(Throwable e){
log.error("事件分发监控处理异常:", e);
}
LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(8));
}
});
distStatThread.setName("AppClientEventDistPipelineProcessor-DistStatThread");
distStatThread.setDaemon(true);
distStatThread.start();
log.info(">>>>>>BizEvent dist queue monitor thread init done. Thread:{}", distStatThread.getName());
}
}