解决接口响应超时
This commit is contained in:
parent
4abfc570a0
commit
4a6cca7373
|
@ -3,6 +3,8 @@ package com.greenorange.promotion;
|
|||
import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.scheduling.annotation.EnableAsync;
|
||||
|
||||
@SpringBootApplication
|
||||
@MapperScan("com.greenorange.promotion.mapper")
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
package com.greenorange.promotion.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target(ElementType.METHOD) // 只用于方法
|
||||
@Retention(RetentionPolicy.RUNTIME) // 运行时可用
|
||||
public @interface Timeout {
|
||||
long value(); // 超时时间,单位:毫秒
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
package com.greenorange.promotion.aop;
|
||||
|
||||
import com.greenorange.promotion.annotation.Timeout;
|
||||
import com.greenorange.promotion.common.ErrorCode;
|
||||
import com.greenorange.promotion.exception.BusinessException;
|
||||
import com.greenorange.promotion.exception.ThrowUtils;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.aspectj.lang.annotation.Before;
|
||||
import org.aspectj.lang.annotation.Pointcut;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.concurrent.*;
|
||||
|
||||
@Aspect
|
||||
@Component
|
||||
public class TimeoutAspect {
|
||||
|
||||
|
||||
private final ExecutorService executorService;
|
||||
|
||||
// 构造器注入线程池
|
||||
@Autowired
|
||||
public TimeoutAspect(ExecutorService executorService) {
|
||||
this.executorService = executorService;
|
||||
}
|
||||
|
||||
@Around("@annotation(timeout)")
|
||||
public Object handleTimeout(ProceedingJoinPoint joinPoint, Timeout timeout) throws Throwable {
|
||||
long timeoutMillis = timeout.value(); // 获取超时时间
|
||||
|
||||
// 创建一个线程池来执行任务
|
||||
Callable<Object> task = () -> {
|
||||
try {
|
||||
// 执行目标方法
|
||||
return joinPoint.proceed();
|
||||
} catch (Throwable e) {
|
||||
throw new BusinessException(ErrorCode.OPERATION_ERROR, e.getMessage());
|
||||
}
|
||||
};
|
||||
|
||||
Future<Object> future = executorService.submit(task); // 提交任务
|
||||
|
||||
try {
|
||||
// 在规定时间内等待任务完成
|
||||
return future.get(timeoutMillis, TimeUnit.MILLISECONDS);
|
||||
} catch (TimeoutException e) {
|
||||
// 超时后抛出自定义异常
|
||||
throw new BusinessException(ErrorCode.TIMEOUT_ERROR, "请求超时,超过最大允许时间 " + timeoutMillis + " 毫秒");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -14,7 +14,8 @@ public enum ErrorCode {
|
|||
SYSTEM_ERROR(50000,"系统内部异常"),
|
||||
OPERATION_ERROR(50001,"操作失败"),
|
||||
DATABASE_ERROR(50002, "数据库内部异常"),
|
||||
LOGIN_ERROR(40110,"登陆状态变更");
|
||||
LOGIN_ERROR(40110,"登陆状态变更"),
|
||||
TIMEOUT_ERROR(40800, "请求超时");
|
||||
|
||||
/**
|
||||
* 状态码
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
package com.greenorange.promotion.config;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
|
||||
@Data
|
||||
@Configuration
|
||||
@ConfigurationProperties(prefix = "threadpool")
|
||||
public class ThreadPoolConfig {
|
||||
|
||||
// 从配置文件中读取线程池的配置参数
|
||||
private int corePoolSize; // 核心线程数
|
||||
|
||||
private int maxPoolSize; // 最大线程数
|
||||
|
||||
private int queueCapacity; // 队列容量
|
||||
|
||||
private long keepAliveTime; // 线程空闲时间,单位秒
|
||||
|
||||
/**
|
||||
* 配置线程池
|
||||
* @return 线程池实例
|
||||
*/
|
||||
@Bean
|
||||
public ExecutorService threadPoolExecutor() {
|
||||
return new ThreadPoolExecutor(
|
||||
corePoolSize, // 核心线程数
|
||||
maxPoolSize, // 最大线程数
|
||||
keepAliveTime, // 空闲线程存活时间
|
||||
TimeUnit.SECONDS, // 空闲时间单位
|
||||
new LinkedBlockingQueue<>(queueCapacity), // 任务队列,设置队列大小
|
||||
new ThreadPoolExecutor.CallerRunsPolicy() // 拒绝策略:调用者运行
|
||||
);
|
||||
}
|
||||
}
|
|
@ -6,10 +6,10 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
|||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.greenorange.promotion.annotation.RequiresPermission;
|
||||
import com.greenorange.promotion.annotation.SysLog;
|
||||
import com.greenorange.promotion.annotation.Timeout;
|
||||
import com.greenorange.promotion.common.BaseResponse;
|
||||
import com.greenorange.promotion.common.ErrorCode;
|
||||
import com.greenorange.promotion.common.ResultUtils;
|
||||
import com.greenorange.promotion.constant.SystemConstant;
|
||||
import com.greenorange.promotion.constant.UserConstant;
|
||||
import com.greenorange.promotion.exception.ThrowUtils;
|
||||
import com.greenorange.promotion.model.dto.CommonBatchRequest;
|
||||
|
@ -24,14 +24,11 @@ import com.greenorange.promotion.service.common.CommonService;
|
|||
import com.greenorange.promotion.service.user.UserInfoService;
|
||||
import com.greenorange.promotion.service.user.UserMainInfoService;
|
||||
import com.greenorange.promotion.utils.JWTUtils;
|
||||
import com.greenorange.promotion.utils.RegexUtils;
|
||||
import com.greenorange.promotion.utils.SendSmsUtil;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.validation.Valid;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
@ -408,4 +405,16 @@ public class UserInfoController {
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@PostMapping("/test")
|
||||
@Timeout(5000) // 设置超时时间为 3000 毫秒(3秒)
|
||||
public String testMethod() throws InterruptedException {
|
||||
// 模拟长时间的任务,超过 3 秒会抛出超时异常
|
||||
Thread.sleep(10000); // 模拟 5 秒的耗时操作
|
||||
return "任务完成";
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -246,6 +246,9 @@ public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo>
|
|||
redisTemplate.opsForValue().set(SystemConstant.VERIFICATION_CODE + ":" + verificationCode, verificationCode, 5, TimeUnit.MINUTES);
|
||||
return verificationCode;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -30,6 +30,12 @@ spring:
|
|||
springdoc:
|
||||
default-flat-param-object: true
|
||||
|
||||
#线程池配置
|
||||
threadpool:
|
||||
corePoolSize: 10
|
||||
maxPoolSize: 50
|
||||
queueCapacity: 1024
|
||||
keepAliveTime: 60
|
||||
|
||||
|
||||
server:
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.greenorange.promotion.timeout;
|
||||
|
||||
import org.junit.jupiter.api.Timeout;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
|
Loading…
Reference in New Issue
Block a user