策略模式企业级实践------硬件设备监控指标数据上报
业务背景
河水水环境业务监测指标数据上报, 核心业务需求:
- 多设备指标差异化处理:各设备,指标上报参数格式、加密方式、回调协议不同
- 监测指标类型扩展:支持 水温,悬浮物,pH值,化学需氧量(COD),大肠菌群 等等30+业务指标类型
- 高并发处理:日均处理百万级事件,峰值QPS 1000
- 数据一致性:保证不同设备上报不同指标数据完整性
业务例子:比如设备A上报(该设备sn 时间 A指标 监测结果)数据,就会触发对应的URL(我们这边提供)
通过采用策略模式和事件驱动的设计,实现了对不同指标的灵活处理和扩展。
请求处理流程图
相似场景代码demo
策略容器
java
package com.shsc.wms.biz;
import com.shsc.wms.common.annotation.PlatformHandler;
import com.shsc.wms.common.enums.TaskTypeEnum;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.Map;
@Service
public class TaskEtlContext {
private final Map<TaskTypeEnum, TaskEtlTemplateService> handlerMap = new HashMap<>();
public TaskEtlContext(Map<String, TaskEtlTemplateService> map) {
map.forEach((k, v) -> {
PlatformHandler annotation = v.getClass().getAnnotation(PlatformHandler.class);
this.handlerMap.put(annotation.value(), v);
});
}
public TaskEtlTemplateService getHandler(String code) {
return handlerMap.get(code);
}
}
策略标识注解
java
package com.shsc.wms.common.annotation;
import com.shsc.wms.common.enums.TaskTypeEnum;
import org.springframework.stereotype.Component;
import java.lang.annotation.*;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface PlatformHandler {
TaskTypeEnum value();
}
策略枚举类型
java
package com.shsc.wms.common.enums;
/**
* @desc 指标对照关系
**/
public enum TaskTypeEnum {
TASK_A("WarehouseReq", "AAAA");
//入参类全路径
private String req;
//实体类全路径
private String entity;
TaskTypeEnum(String req, String entity) {
this.req = req;
this.entity = entity;
}
public String getReq() {
return req;
}
public String getEntity() {
return entity;
}
}
策略抽象模版方法
java
package com.shsc.wms.biz;
import com.shsc.wms.common.enums.EtlTaskStatusEnum;
import com.shsc.wms.entity.EtlTaskEntity;
import com.shsc.wms.mapper.etl.EtlTaskEntityMapper;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.Date;
import java.util.List;
public abstract class TaskEtlTemplateService<T> {
@Autowired
private EtlTaskEntityMapper etlTaskEntityMapper;
public final void handle(EtlTaskEntity taskEntity) {
// 1 抓取数据
List<T> items = extract(taskEntity);
// 2 保存或者更新 指标结果
saveOrUpdateResult(items);
// 3 更新 task
updateTask(taskEntity);
}
/**
* 抓取数据
*/
protected abstract List<T> extract(EtlTaskEntity taskEntity);
/**
* 保存或者更新 指标结果
*/
protected abstract void saveOrUpdateResult(List<T> items);
/**
* 更新 task
*/
public void updateTask(EtlTaskEntity taskEntity) {
taskEntity.setStatus(EtlTaskStatusEnum.FINISH.getCode());
taskEntity.setActualTime(new Date());
etlTaskEntityMapper.updateById(taskEntity);
}
}
具体策略实现Demo
java
package com.shsc.wms.service;
import com.shsc.wms.biz.TaskEtlTemplateService;
import com.shsc.wms.common.annotation.PlatformHandler;
import com.shsc.wms.common.enums.TaskTypeEnum;
import com.shsc.wms.common.model.request.StoredLocationBatchReq;
import com.shsc.wms.entity.EtlTaskEntity;
import lombok.extern.slf4j.Slf4j;
import java.util.Collections;
import java.util.List;
@PlatformHandler(value = TaskTypeEnum.TASK_A)
@Slf4j
public class TaskAService extends TaskEtlTemplateService<StoredLocationBatchReq> {
@Override
protected List<StoredLocationBatchReq> extract(EtlTaskEntity taskEntity) {
log.info("TaskAService TaskA 抓取数据");
return Collections.emptyList();
}
@Override
protected void saveOrUpdateResult(List<StoredLocationBatchReq> items) {
log.info("TaskAService TaskA 保存数据");
}
}
策略调用
java
package com.shsc.wms.biz;
import com.shsc.wms.common.constant.CommonConstant;
import com.shsc.wms.common.core.ThreadUtil;
import com.shsc.wms.common.core.UserInfoEntity;
import com.shsc.wms.entity.EtlTaskEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
@Component
@Slf4j
public class EtlTask {
@Autowired
private TaskEtlContext taskEtlContext;
@Autowired
private TransactionTemplate transactionTemplate;
@Async(value = CommonConstant.wmsEtlExecutor)
public void runTask(EtlTaskEntity taskEntity, UserInfoEntity userHolder) {
ThreadUtil.resetCurrentUserInfo(userHolder);
// 获取任务处理器
TaskEtlTemplateService handler = taskEtlContext.getHandler(taskEntity.getTaskType());
if (handler == null) {
log.error("未找到对应的任务处理器,任务类型:{}", taskEntity.getTaskType());
return;
}
// 使用编程式事务
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
try {
// 处理任务
handler.handle(taskEntity);
} catch (Exception e) {
// 发生异常时回滚事务
status.setRollbackOnly();
log.error("执行任务时发生异常,事务已回滚", e);
}
}
});
}
}