import cn.hutool.core.util.ClassUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.flinkRisk.handler.StreamHandler;
import com.flinkRisk.handler.impl.speedLimit.LimitSpeedData;
import com.flinkRisk.model.AlarmEvent;
import com.flinkRisk.model.VehiclePosInfo;
import com.flinkRisk.model.VehicleState;
import com.flinkRisk.rule.RuleParam;
import lombok.extern.slf4j.Slf4j;
import org.apache.flink.api.common.state.MapState;
import org.apache.flink.api.common.state.ValueState;
import org.apache.flink.streaming.api.functions.co.KeyedBroadcastProcessFunction;
import org.apache.flink.util.Collector;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/**
* 处理器管理类
*/
@Slf4j
public class HandlerManager {
/**
* 处理器集合
*/
private static volatile Map<String, StreamHandler> handlerMap = new HashMap<>();
/**
* 初始化需要使用的处理器集合
*
* @param config
*/
public static void initHandlers(String config) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
if (StrUtil.isEmpty(config)) {
log.info("未配置业务处理器");
return;
}
if(handlerMap.isEmpty()){
synchronized (HandlerManager.class){
if(handlerMap.isEmpty()){
String[] handlers = null;
if (config.contains(";")) {
handlers = config.split(";");
} else {
handlers = new String[]{config};
}
Set<Class<?>> classes = ClassUtil.scanPackage("com.bsj.flinkRisk.handler.impl");
for (Class<?> clazz : classes) {
String className = clazz.getName();
for (String handlerName : handlers) {
//初始化处理器
if (className.contains(handlerName)) {
Constructor<?> c = clazz.getDeclaredConstructor();
c.setAccessible(true);
handlerMap.put(handlerName, (StreamHandler) c.newInstance());
}
}
}
log.info("初始化处理器成功,处理集合大小{}",handlerMap.size());
}
}
}
}
/**
* 遍历所有处理器处理业务
* @param posInfo
* @param ctx
* @param lastState
* @param alarmState
* @param out
* @param limitSpeedDataMap
*/
public static void handler(VehiclePosInfo posInfo, RuleParam ruleParam, KeyedBroadcastProcessFunction.ReadOnlyContext ctx, ValueState<VehicleState> lastState, MapState<String, AlarmEvent> alarmState, Collector<AlarmEvent> out, Map<Long, LimitSpeedData> limitSpeedDataMap) {
VehicleState state = null;
try {
state = lastState.value();
} catch (IOException e) {
e.printStackTrace();
}
/*********************数据预处理************************/
//若中间状态没数据,表示设备第一次上线或者离线时间过长导致中间状态过期(30天),该条定位数据不进行业务分析,只进行状态记录
if (state == null) {
state = new VehicleState();
state.setLastPosInfo(posInfo);
//第一次时设置车辆为行使状态
state.setRunStopState(1);
state.setRunStopTimeBegin(posInfo.getDevTime().getTime());
//表示第一条数据
posInfo.setFirstData((byte) 1);
//设置车辆行停状态
// RedisDataUtil.runStopUpdate(posInfo, 1,posInfo.getDevTime().getTime(), ctx);
//记录定位数据,以便后来的定位数据进行比对分析
try {
lastState.update(state);
} catch (IOException e) {
log.error("中间数据更新异常",e);
}
//处理业务
handleBiz(posInfo, ruleParam, ctx, lastState, alarmState, out, limitSpeedDataMap);
//记录定位数据,以便后来的定位数据进行比对分析
try {
lastState.update(state);
} catch (IOException e) {
log.error("中间数据更新异常",e);
}
}else {
//如果当前定位数据设备时间比上一次定位数据设备时间小,丢弃掉,不进行业务处理(盲区数据,补传数据等)
if (state.getLastPosInfo().getDevTime().getTime() >= posInfo.getDevTime().getTime()) {
log.info("上次数据时间大于这次数据时间,上次时间:{},上次车牌:{},当前时间:{},当前车牌:{}",state.getLastPosInfo().getDevTime(),state.getLastPosInfo().getPlate(),posInfo.getDevTime(),posInfo.getPlate());
// log.info("上次数据接收时间大于这次数据接收时间,上次接收时间:{},上次车牌:{},当前接收时间:{},当前车牌:{}",state.getLastPosInfo().getRecvTime(),state.getLastPosInfo().getPlate(),posInfo.getRecvTime(),posInfo.getPlate());
return;
}
//处理业务
handleBiz(posInfo, ruleParam, ctx, lastState, alarmState, out,limitSpeedDataMap);
//记录定位数据,以便后来的定位数据进行比对分析
state.setLastPosInfo(posInfo);
//统一更新状态数据
try {
lastState.update(state);
} catch (IOException e) {
log.error("中间数据更新异常",e);
}
}
}
/**
* 处理业务
* @param posInfo
* @param ruleParam
* @param ctx
* @param lastState
* @param alarmState
* @param out
* @param limitSpeedDataMap
*/
public static void handleBiz(VehiclePosInfo posInfo, RuleParam ruleParam, KeyedBroadcastProcessFunction.ReadOnlyContext ctx, ValueState<VehicleState> lastState, MapState<String, AlarmEvent> alarmState, Collector<AlarmEvent> out, Map<Long, LimitSpeedData> limitSpeedDataMap){
long btime= System.currentTimeMillis();
for (Map.Entry<String, StreamHandler> entry : handlerMap.entrySet()) {
try {
long bt=System.currentTimeMillis();
entry.getValue().handleStream(posInfo, ruleParam, ctx, lastState, alarmState, out,limitSpeedDataMap);
long et = System.currentTimeMillis() - bt;
if(et>50){
log.info("{}业务处理耗时较长:{}ms",entry.getValue().getHandlerName(),et);
}
} catch (Exception e) {
log.info("异常",e);
log.error("{}数据处理异常:车辆id--{} 定位数据--{}",entry.getValue().getHandlerName(), JSON.toJSONString(posInfo),e);
}
}
long eTime=System.currentTimeMillis()-btime;
if(eTime>100){
log.info("单条数据业务处理耗时较长:{}ms",eTime);
}
}
}
HandlerManager处理器管理类
最新推荐文章于 2024-11-10 08:18:21 发布