From 2c213025ea02ee272f3dec89bd9367a43864c221 Mon Sep 17 00:00:00 2001 From: cbs <18617195505@163.com> Date: Wed, 19 Mar 2025 11:26:58 +0800 Subject: [PATCH] =?UTF-8?q?=E9=99=90=E6=B5=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mqtt/api/path/PathPlanningApiImpl.java | 1 - .../api/robot/RobotGenericsStatusApiImpl.java | 4 +- .../system/api/robot/RobotStatusApiImpl.java | 16 ++-- .../config/aop/SystemRateLimiterAspect.java | 85 +++++++++++++++++++ .../config/ratelimiter/SystemRateLimiter.java | 39 +++++++++ .../src/main/resources/application-local.yaml | 1 + 6 files changed, 139 insertions(+), 7 deletions(-) create mode 100644 yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/config/aop/SystemRateLimiterAspect.java create mode 100644 yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/config/ratelimiter/SystemRateLimiter.java diff --git a/yudao-module-mqtt/yudao-module-mqtt-biz/src/main/java/cn/iododer/yudao/module/mqtt/api/path/PathPlanningApiImpl.java b/yudao-module-mqtt/yudao-module-mqtt-biz/src/main/java/cn/iododer/yudao/module/mqtt/api/path/PathPlanningApiImpl.java index a3623a47f..27d57ac77 100644 --- a/yudao-module-mqtt/yudao-module-mqtt-biz/src/main/java/cn/iododer/yudao/module/mqtt/api/path/PathPlanningApiImpl.java +++ b/yudao-module-mqtt/yudao-module-mqtt-biz/src/main/java/cn/iododer/yudao/module/mqtt/api/path/PathPlanningApiImpl.java @@ -53,7 +53,6 @@ public class PathPlanningApiImpl implements PathPlanningApi { @Override public void synchronousLineObject(Object obj, String topic) { - log.info("收到请求 :{}", JSON.toJSONString(obj)); try { mqttUtils.pub(topic, JSON.toJSONString(obj)); log.info("同步信息给PP--完成 :{}", JSON.toJSONString(obj)); diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/robot/RobotGenericsStatusApiImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/robot/RobotGenericsStatusApiImpl.java index 894927bc0..fac5b520c 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/robot/RobotGenericsStatusApiImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/robot/RobotGenericsStatusApiImpl.java @@ -4,6 +4,7 @@ import cn.hutool.core.util.ObjectUtil; import cn.hutool.json.JSONUtil; import cn.iocoder.yudao.module.system.api.robot.dto.RobotGenericsDataDTO; import cn.iocoder.yudao.module.system.api.robot.dto.RobotStatusDataPoseDTO; +import cn.iocoder.yudao.module.system.config.ratelimiter.SystemRateLimiter; import cn.iocoder.yudao.module.system.constant.robot.RobotTaskChcheConstant; import cn.iocoder.yudao.module.system.util.redis.RedisUtil; import com.alibaba.fastjson.JSON; @@ -25,10 +26,11 @@ public class RobotGenericsStatusApiImpl implements RobotGenericsStatusApi { @Resource private RedisUtil redisUtil; - @Resource@Value("${zn.robot_position_cache_time:600}") + @Resource@Value("${zn.robot_position_cache_time:10}") private Long robotPositionCacheTime; @Override + @SystemRateLimiter(time = 1, count = 20, keyArg = "updateRobotCommonStatus",message = "机器人上报车辆其他信息") public void updateRobotCommonStatus(RobotGenericsDataDTO robotStatusData) { doUpdateRobotCommonStatus(robotStatusData); } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/robot/RobotStatusApiImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/robot/RobotStatusApiImpl.java index a4a941bb1..433538879 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/robot/RobotStatusApiImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/robot/RobotStatusApiImpl.java @@ -9,6 +9,7 @@ import cn.iocoder.yudao.module.system.api.robot.dto.RobotStatusDTO; import cn.iocoder.yudao.module.system.api.robot.dto.RobotStatusDataErrorDTO; import cn.iocoder.yudao.module.system.api.robot.dto.RobotStatusDataPoseDTO; import cn.iocoder.yudao.module.system.api.robot.vo.RobotInformationVO; +import cn.iocoder.yudao.module.system.config.ratelimiter.SystemRateLimiter; import cn.iocoder.yudao.module.system.constant.path.PathPlanningTopicConstant; import cn.iocoder.yudao.module.system.constant.robot.RobotTaskChcheConstant; import cn.iocoder.yudao.module.system.dal.dataobject.robot.RobotWarnCodeMappingDO; @@ -45,7 +46,7 @@ public class RobotStatusApiImpl implements RobotStatusApi { @Autowired private RobotInformationService robotInformationService; - @Value("${zn.robot_position_cache_time:600}") + @Value("${zn.robot_position_cache_time:10}") private Long robotPositionCacheTime; @Resource @@ -64,10 +65,9 @@ public class RobotStatusApiImpl implements RobotStatusApi { * @return */ @Override + @SystemRateLimiter(time = 1, count = 150, keyArg = "robotStatusUpdate",message = "机器人上报点位超过限流") public void robotStatusUpdate(RobotPoseStatusDTO robotStatusDataDTO) { - taskExecutor.execute(()->{ - updateRobotPosed(robotStatusDataDTO); - }); + updateRobotPosed(robotStatusDataDTO); } /** @@ -92,7 +92,6 @@ public class RobotStatusApiImpl implements RobotStatusApi { } robotStatusDataPoseDTO.setRobotNo(robotNo); redisUtil.set(pose2dKey, JSON.toJSONString(robotStatusDataPoseDTO), robotPositionCacheTime); - pathPlanningApi.synchronousLineObject(robotStatusDataPoseDTO, PathPlanningTopicConstant.AGV_POSE); //机器人身上是否有货 String taskStatusKey = RobotTaskChcheConstant.ROBOT_TASK_STATUS + robotStatusDataDTO.getMac(); @@ -110,5 +109,12 @@ public class RobotStatusApiImpl implements RobotStatusApi { // 合并请求 - 这里接受到的数据都丢给 RequestProcessor - 再整合数据通过WebSocket丢给前端 processor.handleRequest(robotStatusDataPoseDTO.getFloor() + "_" + robotStatusDataPoseDTO.getArea(), robotStatusDataDTO.getMac(), JSONUtil.toJsonStr(robotInformationVO)); + sendToPP(robotStatusDataPoseDTO); + } + + private void sendToPP(RobotStatusDataPoseDTO robotStatusDataPoseDTO) { + taskExecutor.execute(()->{ + pathPlanningApi.synchronousLineObject(robotStatusDataPoseDTO, PathPlanningTopicConstant.AGV_POSE); + }); } } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/config/aop/SystemRateLimiterAspect.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/config/aop/SystemRateLimiterAspect.java new file mode 100644 index 000000000..43385c6e4 --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/config/aop/SystemRateLimiterAspect.java @@ -0,0 +1,85 @@ +package cn.iocoder.yudao.module.system.config.aop; + +import cn.hutool.core.util.ObjectUtil; +import cn.iocoder.yudao.module.system.config.ratelimiter.SystemRateLimiter; +import cn.iocoder.yudao.module.system.util.redis.RedisUtil; +import lombok.extern.slf4j.Slf4j; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Before; +import org.aspectj.lang.annotation.Pointcut; +import org.aspectj.lang.reflect.MethodSignature; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; +import java.lang.reflect.Method; + +/** + * 拦截声明了 {@link SystemRateLimiter} 注解的方法,实现限流操作 + * + * @author 芋道源码 + */ +@Aspect +@Component +@Slf4j +public class SystemRateLimiterAspect { + private static final Logger logger = LoggerFactory.getLogger(SystemRateLimiterAspect.class); + + @Resource + private RedisUtil redisUtil; + + @Value("${zn.open_rate_limiter:false}") + private Boolean openRateLimiter; + + @Pointcut("@annotation(cn.iocoder.yudao.module.system.config.ratelimiter.SystemRateLimiter)") + public void serviceLimit() { + + } + + @Around("serviceLimit()") + public Object around(ProceedingJoinPoint joinPoint) throws Throwable { + if (!openRateLimiter) { + return joinPoint.proceed(); + } + MethodSignature signature = (MethodSignature) joinPoint.getSignature(); + Method method = signature.getMethod(); + SystemRateLimiter systemRateLimiter = method.getAnnotation(SystemRateLimiter.class); + String key = systemRateLimiter.keyArg(); + int time = systemRateLimiter.time(); + // 获取redis的value + Integer maxTimes = null; + Object value = redisUtil.get(key); + if (value != null) { + maxTimes = (Integer) value; + } + + Object obj = null; + + if (maxTimes == null) { + // 如果redis中没有该ip对应的时间则表示第一次调用,保存key到redis + redisUtil.set(key, 1, time); + //这个方法用于执行原来的方法或继续原来的控制流程。 + obj = joinPoint.proceed(); + } else if (maxTimes < systemRateLimiter.count()) { + // 如果redis中的时间比注解上的时间小则表示可以允许访问,这是修改redis的value时间 + redisUtil.set(key, maxTimes + 1, time); + //这个方法用于执行原来的方法或继续原来的控制流程。 + obj = joinPoint.proceed(); + } else { + // 请求过于频繁 + logger.info("请求过于频繁 :{}", key); + } + return obj; + } + + + +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/config/ratelimiter/SystemRateLimiter.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/config/ratelimiter/SystemRateLimiter.java new file mode 100644 index 000000000..d72127958 --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/config/ratelimiter/SystemRateLimiter.java @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.module.system.config.ratelimiter; + +import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 限流注解 + * + * @author 芋道源码 + */ +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface SystemRateLimiter { + /** + * 限流的时间,默认为 1 秒 + */ + int time() default 1; + + /** + * 限流次数 + */ + int count() default 100; + + /** + * 提示信息,请求过快的提示 + * + * @see GlobalErrorCodeConstants#TOO_MANY_REQUESTS + */ + String message() default ""; // 为空时,使用 TOO_MANY_REQUESTS 错误提示 + + /** + * 使用的 Key 参数 + */ + String keyArg() default ""; +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/resources/application-local.yaml b/yudao-module-system/yudao-module-system-biz/src/main/resources/application-local.yaml index 78e87470e..9b2d8f771 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/resources/application-local.yaml +++ b/yudao-module-system/yudao-module-system-biz/src/main/resources/application-local.yaml @@ -240,4 +240,5 @@ zn: robot_config: #机器人取放货默认配置 offset_height: 0.1 #叉起货需要在原来高度基础上偏移的高度 default_tray_height: 1.1 #默认每层高度 + open_rate_limiter: true #是否开启限流