diff --git a/microservices-common/microservices-common-core/src/main/java/com/microservices/common/core/constant/CacheConstants.java b/microservices-common/microservices-common-core/src/main/java/com/microservices/common/core/constant/CacheConstants.java index 60c443219..22ed5c915 100644 --- a/microservices-common/microservices-common-core/src/main/java/com/microservices/common/core/constant/CacheConstants.java +++ b/microservices-common/microservices-common-core/src/main/java/com/microservices/common/core/constant/CacheConstants.java @@ -208,4 +208,15 @@ public class CacheConstants public static String getGitlinkOrgIdOpenEnterpriseKey(Long gitlinkOrgId) { return GITLINK_ORG_ID_OPEN_ENTERPRISE_KEY + gitlinkOrgId; } + + /** + * Sentinel Token缓存Key + */ + public final static String SENTINEL_TOKEN = "sentinel_token"; + + + /** + * Nacos Token缓存Key + */ + public static final String NACOS_TOKEN = "nacos_token"; } diff --git a/microservices-common/microservices-common-core/src/main/java/com/microservices/common/core/constant/TokenConstants.java b/microservices-common/microservices-common-core/src/main/java/com/microservices/common/core/constant/TokenConstants.java index a74ad6b35..e9349b3aa 100644 --- a/microservices-common/microservices-common-core/src/main/java/com/microservices/common/core/constant/TokenConstants.java +++ b/microservices-common/microservices-common-core/src/main/java/com/microservices/common/core/constant/TokenConstants.java @@ -22,6 +22,10 @@ public class TokenConstants { * Sentinel令牌标识 */ public static final String Sentinel_Token_Key = "sentinel_dashboard_cookie"; + /** + * Sentinel令牌标识 + */ + public static final String Nacos_Token_Key = "Accesstoken"; /** * Cookie中令牌标识 */ diff --git a/microservices-gateway/src/main/java/com/microservices/gateway/CustomExecutorFactory.java b/microservices-gateway/src/main/java/com/microservices/gateway/CustomExecutorFactory.java new file mode 100644 index 000000000..c18c39865 --- /dev/null +++ b/microservices-gateway/src/main/java/com/microservices/gateway/CustomExecutorFactory.java @@ -0,0 +1,35 @@ +package com.microservices.gateway; + +import com.microservices.common.core.exception.ServiceException; +import com.microservices.common.core.threadPool.ThreadPoolExecutorWrap; + +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +/** + * @author OTTO + */ +public class CustomExecutorFactory { + /** + * 创建线程池 + * 存在并发处理的情况,设置核心线程为2,设置有界队列长度为100,最大线程数为10 + * 当超出队列已满且达到最大线程数时抛出异常 + * Ncpu=CPU数量 + * Ucpu=目标CPU的使用率,0<=Ucpu<=1 + * W/C=任务等待时间与任务计算时间的比率 + * Nthreads =Ncpu*Ucpu*(1+W/C) + */ + public static ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutorWrap( + 4 + , 10 + , 10 + , TimeUnit.SECONDS + , new ArrayBlockingQueue<>(100) + , Executors.defaultThreadFactory() + , (r, executor) -> { + throw new ServiceException("目前处理的人太多了,请稍后再试"); + } + ); +} diff --git a/microservices-gateway/src/main/java/com/microservices/gateway/filter/AuthFilter.java b/microservices-gateway/src/main/java/com/microservices/gateway/filter/AuthFilter.java index 7b1483a24..ab176a9ca 100644 --- a/microservices-gateway/src/main/java/com/microservices/gateway/filter/AuthFilter.java +++ b/microservices-gateway/src/main/java/com/microservices/gateway/filter/AuthFilter.java @@ -1,5 +1,6 @@ package com.microservices.gateway.filter; +import com.alibaba.fastjson2.JSONObject; import com.microservices.common.core.constant.CacheConstants; import com.microservices.common.core.constant.HttpStatus; import com.microservices.common.core.constant.SecurityConstants; @@ -11,6 +12,7 @@ import com.microservices.common.core.utils.JwtUtils; import com.microservices.common.core.utils.ServletUtils; import com.microservices.common.core.utils.StringUtils; import com.microservices.common.redis.service.RedisService; +import com.microservices.gateway.CustomExecutorFactory; import com.microservices.gateway.config.properties.IgnoreWhiteProperties; import com.microservices.system.api.RemoteGatewayService; import com.microservices.system.api.RemoteUserService; @@ -31,15 +33,14 @@ import org.springframework.stereotype.Component; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; +import java.io.IOException; import java.io.StringWriter; import java.nio.charset.StandardCharsets; import java.util.Collection; +import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; +import java.util.concurrent.*; /** * 网关鉴权 @@ -63,7 +64,7 @@ public class AuthFilter implements GlobalFilter, Ordered { @Autowired private RemoteGatewayService remoteGatewayService; - ExecutorService executorService = Executors.newFixedThreadPool(1); + ThreadPoolExecutor threadPoolExecutor = CustomExecutorFactory.threadPoolExecutor; /** * 处理第三方工具请求 @@ -80,35 +81,64 @@ public class AuthFilter implements GlobalFilter, Ordered { if (StringUtils.isNotEmpty(CookieUtil.getCookieValue(cookie, TokenConstants.Sentinel_Token_Key))) { cookie = CookieUtil.removeCookieKey(cookie, TokenConstants.Sentinel_Token_Key); } - // 网关采用异步架构,所以此处需要通过异步请求获取Sentinel Token - Future future = executorService.submit(() -> remoteGatewayService.loginSentinel("sentinel", "sentinel")); - try { - Response response = future.get(1, TimeUnit.SECONDS); - Map> header = response.headers(); - if (header != null && header.containsKey("set-cookie")) { - String sentinelCookie = header.get("set-cookie").iterator().next(); - ServletUtils.removeHeader(mutate, TokenConstants.Cookie); - mutate.header(TokenConstants.Cookie, String.format("%s;%s;", cookie, sentinelCookie)); + String sentinelCookie = null; + if (redisService.hasKey(CacheConstants.SENTINEL_TOKEN)) { + sentinelCookie = redisService.getCacheObject(CacheConstants.SENTINEL_TOKEN); + } else { + // 网关采用异步架构,所以此处需要通过异步请求获取Sentinel Token + Future future = threadPoolExecutor.submit(() -> remoteGatewayService.loginSentinel("sentinel", "sentinel")); + try { + Response response = future.get(1, TimeUnit.SECONDS); + Map> header = response.headers(); + if (header != null && header.containsKey("set-cookie")) { + sentinelCookie = header.get("set-cookie").iterator().next(); + redisService.setCacheObject(CacheConstants.SENTINEL_TOKEN, sentinelCookie, 12L, TimeUnit.HOURS); + } + } catch (TimeoutException e) { + log.error("获取Sentinel Token超时"); + } catch (InterruptedException | ExecutionException e) { + log.error("获取Sentinel Token失败:{}", e.getMessage()); } - } catch (Exception e) { - log.error("获取Sentinel Token失败:{0}", e); + } + if (StringUtils.isNotEmpty(sentinelCookie)) { + ServletUtils.removeHeader(mutate, TokenConstants.Cookie); + mutate.header(TokenConstants.Cookie, String.format("%s;%s;", cookie, sentinelCookie)); } } // 处理Nacos请求 if (url.toLowerCase().startsWith("/nacos")) { - // 网关采用异步架构,所以此处需要通过异步请求获取Nacos Token - Future future = executorService.submit(() -> remoteGatewayService.loginNacos("nacos", "nacos")); - try { - Response res = future.get(1, TimeUnit.SECONDS); - StringWriter writer = new StringWriter(); - IOUtils.copy(res.body().asInputStream(), writer, StandardCharsets.UTF_8.name()); - String str = writer.toString(); - System.out.println(str); - } catch (Exception e) { - log.error("获取Nacos Token失败:{0}", e); + String nacosToken = null; + if (redisService.hasKey(CacheConstants.NACOS_TOKEN)) { + nacosToken = redisService.getCacheObject(CacheConstants.NACOS_TOKEN); + } else { + Map nacosMap = new HashMap<>(); + nacosMap.put("username", "nacos"); + nacosMap.put("password", "nacos"); + // 网关采用异步架构,所以此处需要通过异步请求获取Nacos Token + Future future = threadPoolExecutor.submit(() -> remoteGatewayService.loginNacos(nacosMap)); + try { + Response res = future.get(1, TimeUnit.SECONDS); + StringWriter writer = new StringWriter(); + IOUtils.copy(res.body().asInputStream(), writer, StandardCharsets.UTF_8.name()); + String str = writer.toString(); + JSONObject resJsonObject = JSONObject.parseObject(str); + nacosToken = resJsonObject.getString("accessToken"); + Long tokenTtl = resJsonObject.getLong("tokenTtl"); + if (nacosToken != null && tokenTtl != null) { + redisService.setCacheObject(CacheConstants.NACOS_TOKEN, nacosToken, tokenTtl - 10, TimeUnit.SECONDS); + } else { + throw new ServiceException("Nacos服务获取Token失败"); + } + } catch (TimeoutException e) { + log.error("获取Nacos Token超时"); + } catch (InterruptedException | ExecutionException | IOException | NullPointerException e) { + log.error("获取Nacos Token失败:{}", e.getMessage()); + } + } + if (StringUtils.isNotEmpty(nacosToken)) { + mutate.header(TokenConstants.Nacos_Token_Key, nacosToken); } } - } @Override @@ -176,7 +206,7 @@ public class AuthFilter implements GlobalFilter, Ordered { boolean hasUserIdentifyList = redisService.hasKey(redisKey); if (!hasUserIdentifyList) { // 网关采用异步架构,所以此处需要通过异步请求获取本系统Token - Future>> future = executorService.submit( + Future>> future = threadPoolExecutor.submit( () -> remoteUserService.getSysUserDeptRoleListByUserName(username, SecurityConstants.INNER)); try { List feignResult = FeignUtils.getReturnData( @@ -201,7 +231,7 @@ public class AuthFilter implements GlobalFilter, Ordered { String token = request.getHeaders().getFirst(TokenConstants.AUTHENTICATION); if (token != null) { // 网关采用异步架构,所以此处需要通过异步请求获取本系统Token - Future> future = executorService.submit( + Future> future = threadPoolExecutor.submit( () -> remoteUserService.checkGitLinkUserLogin(token, SecurityConstants.INNER)); try { Boolean feignResult = FeignUtils.getReturnData( @@ -254,7 +284,7 @@ public class AuthFilter implements GlobalFilter, Ordered { private String getGitLinkToken(String cookie) { if (StringUtils.isNotEmpty(cookie)) { // 网关采用异步架构,所以此处需要通过异步请求获取本系统Token - Future> future = executorService.submit(() -> remoteUserService + Future> future = threadPoolExecutor.submit(() -> remoteUserService .getSysUserTokenByGitLinkCookie(cookie, SecurityConstants.INNER)); R feignResult; try {