forked from Gitlink/microservices
feat(调用第三方微服务): 处理Nacos请求转发
1. 调用Nacos登录接口后将响应结果中的accessToken添加到请求头中 2. 增加Redis对Sentinel和Nacos的Token进行缓存,减少登录接口重复调用次数,加快第三方开源软件调用的响应速度 Signed-off-by: OTTO <731554297@qq.com>
This commit is contained in:
parent
62495f0f33
commit
e2138020be
|
|
@ -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";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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中令牌标识
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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("目前处理的人太多了,请稍后再试");
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
@ -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<Response> future = executorService.submit(() -> remoteGatewayService.loginSentinel("sentinel", "sentinel"));
|
||||
try {
|
||||
Response response = future.get(1, TimeUnit.SECONDS);
|
||||
Map<String, Collection<String>> 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<Response> future = threadPoolExecutor.submit(() -> remoteGatewayService.loginSentinel("sentinel", "sentinel"));
|
||||
try {
|
||||
Response response = future.get(1, TimeUnit.SECONDS);
|
||||
Map<String, Collection<String>> 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<Response> 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<String, String> nacosMap = new HashMap<>();
|
||||
nacosMap.put("username", "nacos");
|
||||
nacosMap.put("password", "nacos");
|
||||
// 网关采用异步架构,所以此处需要通过异步请求获取Nacos Token
|
||||
Future<Response> 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<R<List<SysUserDeptRole>>> future = executorService.submit(
|
||||
Future<R<List<SysUserDeptRole>>> future = threadPoolExecutor.submit(
|
||||
() -> remoteUserService.getSysUserDeptRoleListByUserName(username, SecurityConstants.INNER));
|
||||
try {
|
||||
List<SysUserDeptRole> 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<R<Boolean>> future = executorService.submit(
|
||||
Future<R<Boolean>> 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<R<String>> future = executorService.submit(() -> remoteUserService
|
||||
Future<R<String>> future = threadPoolExecutor.submit(() -> remoteUserService
|
||||
.getSysUserTokenByGitLinkCookie(cookie, SecurityConstants.INNER));
|
||||
R<String> feignResult;
|
||||
try {
|
||||
|
|
|
|||
Loading…
Reference in New Issue