sac/sf-vertx/src/main/java/com/sf/vertx/handle/AppConfigHandler.java
ztzh_xieyun 6fac2783bf 保留了ReverseProxy反向代理区分body请求,这块代码可以去掉
ReverseProxy 源码部分仅使用了连接超时
request.setTimeout(AppConfigHandler.getApicodeConfigTimeOut(key));

vertx有一个使用问题,一定要注意, 异常情况可能不会抛出, 导致后台一直不返回.
很可能是业务代码逻辑问题, 比如空异常等等
2024-06-03 14:02:35 +08:00

642 lines
25 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package com.sf.vertx.handle;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.TypeReference;
import com.hazelcast.config.Config;
import com.hazelcast.config.JoinConfig;
import com.hazelcast.config.NetworkConfig;
import com.hazelcast.config.TcpIpConfig;
import com.sf.vertx.api.pojo.ApiConfig;
import com.sf.vertx.api.pojo.AppConfig;
import com.sf.vertx.api.pojo.DataSecurity;
import com.sf.vertx.api.pojo.Node;
import com.sf.vertx.api.pojo.RouteContent;
import com.sf.vertx.api.pojo.SacService;
import com.sf.vertx.api.pojo.Strategy;
import com.sf.vertx.api.pojo.VertxConfig;
import com.sf.vertx.arithmetic.roundRobin.SacLoadBalancing;
import com.sf.vertx.constans.RedisKeyConfig;
import com.sf.vertx.enums.GatewayServiceType;
import com.sf.vertx.httpproxy.HttpProxy;
import com.sf.vertx.init.SacVertxConfig;
import com.sf.vertx.pojo.ClusterEventMsg;
import com.sf.vertx.pojo.SacCircuitBreaker;
import com.sf.vertx.pojo.SacCurrentLimiting;
import com.sf.vertx.security.MainSecurity;
import com.sf.vertx.utils.ProxyTool;
import cn.hutool.core.collection.ConcurrentHashSet;
import io.github.resilience4j.ratelimiter.RateLimiterConfig;
import io.github.resilience4j.ratelimiter.RateLimiterRegistry;
import io.vertx.circuitbreaker.CircuitBreaker;
import io.vertx.circuitbreaker.CircuitBreakerOptions;
import io.vertx.core.Future;
import io.vertx.core.Vertx;
import io.vertx.core.VertxOptions;
import io.vertx.core.http.HttpClient;
import io.vertx.core.http.HttpServer;
import io.vertx.core.http.HttpServerOptions;
import io.vertx.core.net.JksOptions;
import io.vertx.core.spi.cluster.ClusterManager;
import io.vertx.ext.web.Route;
import io.vertx.ext.web.Router;
import io.vertx.ext.web.client.WebClient;
import io.vertx.ext.web.handler.CorsHandler;
import io.vertx.ext.web.handler.HttpException;
import io.vertx.httpproxy.ProxyContext;
import io.vertx.httpproxy.ProxyInterceptor;
import io.vertx.httpproxy.ProxyResponse;
import io.vertx.spi.cluster.hazelcast.HazelcastClusterManager;
import lombok.extern.slf4j.Slf4j;
/***
* vertx配置维护
*
* @author xy
*
*/
@Slf4j
public class AppConfigHandler {
private static VertxConfig VERTX_CONFIG = new VertxConfig();
public static Vertx VERTX;
private static SacVertxConfig sacVertxConfig;
private static RedisTemplate<String, String> redisTemplate;
private static final ConcurrentHashMap<String, AppConfig> CACHE_APP_CONFIG_MAP = new ConcurrentHashMap<>();
// global api config appCode - RateLimiterRegistry
private static final ConcurrentHashMap<String, SacCurrentLimiting> GLOBAL_API_CURRENT_LIMITING_MAP = new ConcurrentHashMap<>();
// global app config appCode - Strategy
private static final ConcurrentHashMap<String, SacCurrentLimiting> GLOBAL_APP_CURRENT_LIMITING_MAP = new ConcurrentHashMap<>();
// appCode:apiCode:SacLoadBalancing
private static ConcurrentHashMap<String, SacLoadBalancing> LOADBALANCING_MAP = new ConcurrentHashMap<>();
// appCode:apiCode - ApiConfig
private static ConcurrentHashMap<String, ApiConfig> APICODE_CONFIG_MAP = new ConcurrentHashMap<>();
// apiCode限流配置 appCode:apiCode - RateLimiterRegistry
private static ConcurrentHashMap<String, SacCurrentLimiting> APICODE_CONFIG_CURRENT_LIMITING_MAP = new ConcurrentHashMap<>();
// 服务类型, apiCode限流配置 appCode:apiCode - 服务类型SAC=SAC规范服务OPEN=开放服务
private static ConcurrentHashMap<String, String> APICODE_CONFIG_SERVICE_TYPE_MAP = new ConcurrentHashMap<>();
// 负载均衡路由类型 appCode:apiCode - routerType
// 执行流程 routerType= <br/>
// 1、serviceNodel="NORMAL", serviceNodel="ROUTE" and RouteType = "WEIGHT_ROUTE"
// <br/>
// return LOADBALANCING_MAP
// 2、serviceNodel="ROUTE", RouteType = "HEADER_ROUTE" <br/>
// return APICODE_CONFIG_ROUTERCONENT_MAP
private static ConcurrentHashMap<String, Integer> APICODE_CONFIG_ROUTERTYPE_MAP = new ConcurrentHashMap<>();
private static ConcurrentHashMap<String, List<RouteContent>> APICODE_CONFIG_HEADER_ROUTERCONENT_MAP = new ConcurrentHashMap<>();
// apiCode熔断配置 appCode:apiCode - CircuitBreaker
private static ConcurrentHashMap<String, SacCircuitBreaker> APICODE_CONFIG_CIRCUIT_BREAKER_MAP = new ConcurrentHashMap<>();
// apicode uri = * - appConfig
private static ConcurrentHashMap<String, AppConfig> APICODE_APPCONFIG_MAP = new ConcurrentHashMap<>();
// 禁用appCode
private static ConcurrentHashSet<String> DISABLED_APPCODE = new ConcurrentHashSet<String>();
public static AppConfig getAppConfigByDomain(String domain) {
return APICODE_APPCONFIG_MAP.get(domain);
}
public static Integer routerType(String key) {
return APICODE_CONFIG_ROUTERTYPE_MAP.get(key) != null ? APICODE_CONFIG_ROUTERTYPE_MAP.get(key) : 1;
}
public static List<RouteContent> routerHeaderConentList(String key) {
return APICODE_CONFIG_HEADER_ROUTERCONENT_MAP.get(key);
}
public static Boolean isServiceTypeOpen(String key) {
return APICODE_CONFIG_SERVICE_TYPE_MAP.get(key) != null
&& StringUtils.equals(APICODE_CONFIG_SERVICE_TYPE_MAP.get(key), GatewayServiceType.OPEN.getCode());
}
public static Boolean isServiceTypeSac(String key) {
return APICODE_CONFIG_SERVICE_TYPE_MAP.get(key) != null
&& StringUtils.equals(APICODE_CONFIG_SERVICE_TYPE_MAP.get(key), GatewayServiceType.SAC.getCode());
}
public static String getServiceType(String key) {
return APICODE_CONFIG_SERVICE_TYPE_MAP.get(key);
}
public static String sacResponseHeaderKey() {
return sacVertxConfig.getSacResponseHeaderKey();
}
public static String rpcUri() {
return sacVertxConfig.getRpcUri();
}
public static void removeDisabledAppcode(String appCode) {
DISABLED_APPCODE.remove(appCode);
}
public static void addDisabledAppcode(String appCode) {
DISABLED_APPCODE.add(appCode);
}
public static boolean isDisabledAppcode(String appCode) {
return DISABLED_APPCODE.contains(appCode);
}
public static SacCurrentLimiting getGlobalAppCurrentLimitingConfig(String appCode) {
return GLOBAL_APP_CURRENT_LIMITING_MAP.get(appCode);
}
public static AppConfig getAppConfig(String appCode) {
return CACHE_APP_CONFIG_MAP.get(appCode);
}
public static void init(RedisTemplate<String, String> _redisTemplate, SacVertxConfig _sacVertxConfig) {
redisTemplate = _redisTemplate;
sacVertxConfig = _sacVertxConfig;
}
public static boolean isDataSecurity(String appCode) {
return CACHE_APP_CONFIG_MAP.get(appCode) != null && CACHE_APP_CONFIG_MAP.get(appCode).getDataSecurity() != null;
}
public static boolean isApiCodeCircuitBreaker(String key) {
return APICODE_CONFIG_CIRCUIT_BREAKER_MAP.get(key) != null;
}
public static SacCircuitBreaker getApiCodeCircuitBreaker(String key) {
return APICODE_CONFIG_CIRCUIT_BREAKER_MAP.get(key);
}
/***
* 优先apicode配置限流、无法找到匹配全局限流
*
* @param appCode
* @param apiCode
* @return
*/
public static SacCurrentLimiting getApiCurrentLimiting(String appCode, String apiCode) {
String key = appCode + ":" + apiCode;
SacCurrentLimiting sacCurrentLimiting = APICODE_CONFIG_CURRENT_LIMITING_MAP.get(key) != null
? APICODE_CONFIG_CURRENT_LIMITING_MAP.get(key)
: null;
sacCurrentLimiting = sacCurrentLimiting != null ? sacCurrentLimiting
: (GLOBAL_API_CURRENT_LIMITING_MAP.get(appCode) != null ? GLOBAL_API_CURRENT_LIMITING_MAP.get(appCode)
: null);
return sacCurrentLimiting;
}
public static VertxConfig getVertxConfig() {
return VERTX_CONFIG;
}
public static String getAppCodeHeaderKey() {
return VERTX_CONFIG.getAppCodeHeaderKey();
}
public static String getApiCodeHeaderKey() {
return VERTX_CONFIG.getApiCodeHeaderKey();
}
public static SacLoadBalancing getLoadBalancing(String key) {
return LOADBALANCING_MAP.get(key);
}
public static ApiConfig getApicodeConfig(String key) {
return APICODE_CONFIG_MAP.get(key);
}
public static Long getApicodeConfigTimeOut(String key) {
return APICODE_CONFIG_MAP.get(key) != null ? APICODE_CONFIG_MAP.get(key).getTimeout() : 3000L;
}
private static RateLimiterRegistry createRateLimiter(Strategy strategy) {
RateLimiterConfig config = RateLimiterConfig.custom()
.limitRefreshPeriod(Duration.ofSeconds(strategy.getTimeWindow()))
.limitForPeriod(strategy.getThreshold()).timeoutDuration(Duration.ofMillis(0)).build();
RateLimiterRegistry registry = RateLimiterRegistry.of(config);
return registry;
}
private static void initRateLimiter(String appCode, Strategy strategy,
ConcurrentHashMap<String, SacCurrentLimiting> map) {
RateLimiterRegistry registry = createRateLimiter(strategy);
SacCurrentLimiting sacCurrentLimiting = new SacCurrentLimiting();
sacCurrentLimiting.setStrategy(strategy);
sacCurrentLimiting.setRegistry(registry);
map.put(appCode, sacCurrentLimiting);
}
/***
* 从redis加载数据
*
* @throws Exception
*/
public static void initAllAppConfig() {
Set<String> set = redisTemplate.opsForZSet().range(RedisKeyConfig.APP_CONFIG_SET_KEY, 0, -1);
for (String appCode : set) {
AppConfigHandler.initAppConfig(appCode, false);
}
}
/***
* 加载vertx配置
*/
public static void initVertxConfig() {
String vertxConfigKey = RedisKeyConfig.VERTX_CONFIG_STRING_KEY;
String vertxConfigValue = redisTemplate.opsForValue().get(vertxConfigKey);
if (StringUtils.isNotBlank(vertxConfigValue)) {
VERTX_CONFIG = JSONObject.parseObject(vertxConfigValue, VertxConfig.class);
}
}
private static void delAppConfigCache(String appCode) {
AppConfig appConfig = CACHE_APP_CONFIG_MAP.get(appCode);
if (appConfig != null) {
// app、api默认限流
GLOBAL_API_CURRENT_LIMITING_MAP.remove(appCode);
GLOBAL_APP_CURRENT_LIMITING_MAP.remove(appCode);
for (SacService sacService : appConfig.getService()) {
if (sacService.getApiConfig() != null && sacService.getApiConfig().size() > 0) {
for (ApiConfig apiConfig : sacService.getApiConfig()) {
String key = appCode + ":" + apiConfig.getApiCode();
APICODE_CONFIG_MAP.remove(key);
LOADBALANCING_MAP.remove(key);
APICODE_CONFIG_SERVICE_TYPE_MAP.remove(key);
APICODE_CONFIG_CURRENT_LIMITING_MAP.remove(key);
APICODE_APPCONFIG_MAP.remove(apiConfig.getApiCode());
String keyCircuitBreaker = key + ":" + "CIRCUIT_BREAKER";
SacCircuitBreaker sacCircuitBreaker = APICODE_CONFIG_CIRCUIT_BREAKER_MAP.get(key);
if (sacCircuitBreaker != null) {
if(sacCircuitBreaker.getCircuitBreaker() != null) {
sacCircuitBreaker.getCircuitBreaker().close();
}
APICODE_CONFIG_CIRCUIT_BREAKER_MAP.remove(keyCircuitBreaker);
}
}
}
}
// 应用配置
CACHE_APP_CONFIG_MAP.remove(appCode);
}
}
public static void initAppConfig(String appCode, boolean isDelLocalCache) {
// 是否需要先删除
if (isDelLocalCache) {
delAppConfigCache(appCode);
}
String appCodeKey = RedisKeyConfig.APP_CONFIG_PREFIX_KEY + ":" + appCode;
String appCodeValue = redisTemplate.opsForValue().get(appCodeKey);
if (StringUtils.isNotBlank(appCodeValue)) {
AppConfig appConfig = JSON.parseObject(appCodeValue, new TypeReference<AppConfig>() {
});
CACHE_APP_CONFIG_MAP.put(appCode, appConfig);
// app、api默认限流
if (appConfig.getApiCurrentLimitingConfig() != null) {
initRateLimiter(appCode, appConfig.getApiCurrentLimitingConfig(), GLOBAL_API_CURRENT_LIMITING_MAP);
}
if (appConfig.getAppCurrentLimitingConfig() != null) {
initRateLimiter(appCode, appConfig.getAppCurrentLimitingConfig(), GLOBAL_APP_CURRENT_LIMITING_MAP);
}
// app router负载均衡
List<RouteContent> routeContentList = null;
for (SacService sacService : appConfig.getService()) {
int routerType = 1;
List<Node> nodeList = new ArrayList<>();
// 获取service模式
if (StringUtils.equals(sacService.getServiceModel(), "NORMAL")) {
Node node = new Node();
node.setIp(sacService.getServerAddress().getHost());
node.setPort(sacService.getServerAddress().getPort());
node.setWeight(0);
node.setProtocol(sacService.getServerAddress().getProtocol());
nodeList.add(node);
} else if (StringUtils.equals(sacService.getServiceModel(), "ROUTE")) {
if (sacService.getRouteConfig() != null
&& StringUtils.equals(sacService.getRouteConfig().getRouteType(), "WEIGHT_ROUTE")) {
for (RouteContent routeContent : sacService.getRouteConfig().getRouteContent()) {
Node node = new Node();
node.setIp(routeContent.getServerAddress().getHost());
node.setPort(routeContent.getServerAddress().getPort());
node.setWeight(routeContent.getWeight() != null && routeContent.getWeight() > 0
? routeContent.getWeight()
: 1);
node.setProtocol(routeContent.getServerAddress().getProtocol());
nodeList.add(node);
}
} else if (sacService.getRouteConfig() != null
&& StringUtils.equals(sacService.getRouteConfig().getRouteType(), "HEADER_ROUTE")) {
routerType = 2;
routeContentList = sacService.getRouteConfig().getRouteContent();
}
}
// 初始化apiConfig
if (sacService.getApiConfig() != null && sacService.getApiConfig().size() > 0) {
for (ApiConfig apiConfig : sacService.getApiConfig()) {
String key = appCode + ":" + apiConfig.getApiCode();
APICODE_CONFIG_MAP.put(key, apiConfig);
if (sacService.getServiceType() != null) {
APICODE_CONFIG_SERVICE_TYPE_MAP.put(key, sacService.getServiceType());
}
// OPEN模式, 域名映射
if (isServiceTypeOpen(key)) {
APICODE_APPCONFIG_MAP.put(apiConfig.getApiCode(), appConfig);
}
// 负载均衡模式
APICODE_CONFIG_ROUTERTYPE_MAP.put(key, routerType);
switch (routerType) {
case 1:
if (nodeList.size() > 0) {
// 初始化负载均衡算法
SacLoadBalancing sacLoadBalancing = ProxyTool.roundRobin(nodeList);
LOADBALANCING_MAP.put(key, sacLoadBalancing);
}
break;
case 2:
APICODE_CONFIG_HEADER_ROUTERCONENT_MAP.put(key, routeContentList);
default:
break;
}
if (apiConfig.getStrategy() != null && apiConfig.getStrategy().size() > 0) {
for (Strategy strategy : apiConfig.getStrategy()) {
if (StringUtils.equals(strategy.getType(), "CURRENT_LIMITING")) {
RateLimiterRegistry registry = createRateLimiter(strategy);
SacCurrentLimiting sacCurrentLimiting = new SacCurrentLimiting();
sacCurrentLimiting.setStrategy(strategy);
sacCurrentLimiting.setRegistry(registry);
APICODE_CONFIG_CURRENT_LIMITING_MAP.put(key, sacCurrentLimiting);
} else if (StringUtils.equals(strategy.getType(), "CIRCUIT_BREAKER")) {
String keyCircuitBreaker = key + ":" + "CIRCUIT_BREAKER";
// interfaceBreaker = CircuitBreaker.create("interfaceBreaker", VERTX,
// new CircuitBreakerOptions().setMaxFailures(3).setMaxRetries(5).setTimeout(2000)
// .setFallbackOnFailure(true)
// ).openHandler(v -> {
// log.info("Circuit opened");
// }).closeHandler(v -> {
// log.info("Circuit closed");
// });//.retryPolicy(retryCount -> retryCount * 100L);
// apiCode熔断
CircuitBreaker circuitBreaker = CircuitBreaker
.create(keyCircuitBreaker + "-circuit-breaker", VERTX,
new CircuitBreakerOptions().setMaxFailures(strategy.getThreshold()) // 最大失败数
.setFailuresRollingWindow(strategy.getTimeWindow() * 1000) // 毫秒
// .setTimeout(apiConfig.getTimeout()) // 超时时间,不要开启,
// 配置会设置接口超时, 这个参数有bug,半开超时会卡死
.setFallbackOnFailure(true) // 失败后是否调用回退函数fallback
.setResetTimeout(strategy.getRecovery_interval() * 1000) // 在开启状态下,尝试重试之前所需时间
).openHandler(v -> {
log.info(keyCircuitBreaker + " Circuit open");
}).halfOpenHandler(v -> {
log.info(keyCircuitBreaker + " Circuit halfOpen");
}).closeHandler(v -> {
log.info(keyCircuitBreaker + " Circuit close");
});
SacCircuitBreaker sacCircuitBreaker = new SacCircuitBreaker();
sacCircuitBreaker.setCircuitBreaker(circuitBreaker);
sacCircuitBreaker.setStrategy(strategy);
APICODE_CONFIG_CIRCUIT_BREAKER_MAP.put(key, sacCircuitBreaker);
}
}
}
}
}
}
}
}
public static void createVertx() {
// TODO 编解码线程池,后面优化协程等方式
VertxOptions vertxOptions = new VertxOptions();
loadVertxOptions(vertxOptions);
VERTX = Vertx.vertx(vertxOptions);
createVertxRouter();
consumerClusterEventMsg();
}
private static Config hazelcastConfig(SacVertxConfig sacVertxConfig) {
// 集群
Config hazelcastConfig = new Config();
hazelcastConfig.setClusterName(sacVertxConfig.getClusterName()); // 集群名字
NetworkConfig networkConfig = new NetworkConfig();
networkConfig.setPort(sacVertxConfig.getNetworkPort());
networkConfig.setPortAutoIncrement(sacVertxConfig.isPortAutoIncrement());
JoinConfig join = new JoinConfig();
TcpIpConfig tcpIpConfig = new TcpIpConfig();
tcpIpConfig.setEnabled(true);
String[] clusterIps = sacVertxConfig.getClusterIp().split(",");
List<String> members = Arrays.asList(clusterIps);
tcpIpConfig.setMembers(members);
join.setTcpIpConfig(tcpIpConfig);
networkConfig.setJoin(join);
hazelcastConfig.setNetworkConfig(networkConfig);
// TODO 还有问题,不会使用
// ManagementCenterConfig managementCenterConfig = new ManagementCenterConfig();
// Set<String> interfaces = new HashSet<>();
// interfaces.add("http://192.168.1.68:8080/mancenter");
// managementCenterConfig.setTrustedInterfaces(interfaces);
// hazelcastConfig.setManagementCenterConfig(managementCenterConfig);
return hazelcastConfig;
}
public static void createHazelcastClusterVertx() {
Config hazelcastConfig = hazelcastConfig(sacVertxConfig);
ClusterManager hazelcastClusterManager = new HazelcastClusterManager(hazelcastConfig);
// TODO 编解码线程池,后面优化协程等方式
VertxOptions vertxOptions = new VertxOptions();
loadVertxOptions(vertxOptions);
vertxOptions.setClusterManager(hazelcastClusterManager);
Vertx.clusteredVertx(vertxOptions, res -> {
if (res.succeeded()) {
VERTX = res.result();
log.info("hazelcastClusterManager create success");
createVertxRouter();
consumerClusterEventMsg();
} else {
res.cause().printStackTrace();
log.info("hazelcastClusterManager create failure");
}
});
}
private static void consumerClusterEventMsg() {
// 订阅消息
VERTX.eventBus().consumer("sac_cluster_event", message -> {
if (message.body() != null) {
ClusterEventMsg msg = JSONObject.parseObject(message.body().toString(), ClusterEventMsg.class);
log.info("Received message: {}", msg);
// message.reply("我是返回数据===" + message.body());
if (msg.getType() == 1) {
if (msg.getOperation() == 1) {
// 初始化AppConfig本地缓存
AppConfigHandler.initAppConfig(msg.getAppCode(), true);
} else if (msg.getOperation() == 3) {
// 删除本地缓存
delAppConfigCache(msg.getAppCode());
} else if (msg.getOperation() == 4) {
// 禁用app
addDisabledAppcode(msg.getAppCode());
} else if (msg.getOperation() == 5) {
// 启用app
removeDisabledAppcode(msg.getAppCode());
}
}
}
});
}
/***
* 发布消息,订阅消息
*
* @param msg
*/
public static void publishClusterEventMsg(ClusterEventMsg msg) {
VERTX.eventBus().publish("sac_cluster_event", JSONObject.toJSONString(msg));
}
private static void createVertxRouter() {
// consul初始化
// ConsulHandler.init(vertx);
// 从redis同步app配置
initAllAppConfig();
VertxConfig vertxConfig = AppConfigHandler.getVertxConfig();
// 创建HTTP监听
// 所有ip都能访问
HttpServerOptions httpServerOptions = new HttpServerOptions().setHost("0.0.0.0");
if (sacVertxConfig.isSSLs()) {
httpServerOptions.setSsl(true)
.setKeyStoreOptions(new JksOptions().setPassword("changeit").setPath("keystore.jks"));
}
HttpServer server = VERTX.createHttpServer(httpServerOptions);
Router mainHttpRouter = Router.router(VERTX);
Integer serverPort = vertxConfig.getPort() == null ? sacVertxConfig.getPort() : vertxConfig.getPort();
log.info("serverPort:{}", serverPort);
server.requestHandler(mainHttpRouter).listen(serverPort, h -> {
if (h.succeeded()) {
log.info("HTTP端口监听成功:{}", serverPort);
} else {
log.error("HTTP端口监听失败:{}", serverPort);
}
});
HttpClient proxyClient = VERTX.createHttpClient();
HttpProxy proxy = HttpProxy.reverseProxy(proxyClient);
proxy.originSelector(request -> Future.succeededFuture(ProxyTool.resolveOriginAddress(request)));
proxy.addInterceptor(new ProxyInterceptor() {
@Override
public Future<ProxyResponse> handleProxyRequest(ProxyContext context) {
// if(StringUtils.equals(sacAppHeaderKey, "dsafdsfadafhappC")) {
// // 会跳转到 RestfulFailureHandlerImpl
// throw new HttpException(10003);
// }
return context.sendRequest();
}
@Override
public Future<Void> handleProxyResponse(ProxyContext context) {
// 调试代码,获取reponse body
// Filter filter = new Filter();
// ProxyResponse proxyResponse = context.response();
// Body body = proxyResponse.getBody();
// proxyResponse.setBody(Body.body(filter.init(context.request().getURI(), body.stream(), false)));
// 继续拦截链
return context.sendResponse();
}
});
WebClient mainWebClient = WebClient.create(VERTX);
String rateLimitModel = vertxConfig.getRateLimitModel();
Route routeSac = mainHttpRouter.post(rpcUri());
routeSac.handler(CorsHandler.create().addRelativeOrigin(".*"))
.handler(ParameterCheckHandler.create(GatewayServiceType.SAC))
.handler(AppRateLimitHandler.create(rateLimitModel))
.handler(ApiRateLimitHandler.create(rateLimitModel))
.handler(BodyPreCheckHandler.create())
.handler(BodyHandler.create().setHandleFileUploads(false))
.handler(BodyPostAnalysisHandler.create())
.handler(BodyPostCheckHandler.create())
.handler(SacRouteRequestHandler.create(mainWebClient))
.handler(ProxyHandler.create(mainWebClient, proxy))
.failureHandler(RestfulFailureHandler.create());
Route routeOpen = mainHttpRouter.route();
routeOpen.handler(CorsHandler.create().addRelativeOrigin(".*"))
.handler(ParameterCheckHandler.create(GatewayServiceType.OPEN))
.handler(AppRateLimitHandler.create(rateLimitModel))
.handler(ApiRateLimitHandler.create(rateLimitModel))
.handler(BodyPreCheckHandler.create())
.handler(BodyHandler.create().setHandleFileUploads(false))
.handler(BodyPostCheckHandler.create())
.handler(SacRouteRequestHandler.create(mainWebClient))
.handler(ProxyHandler.create(mainWebClient, proxy))
.failureHandler(RestfulFailureHandler.create());
}
private static void loadVertxOptions(VertxOptions vertxOptions) {
long blockedThreadCheckInterval = VERTX_CONFIG.getVertxOptionsConfig() == null ? -1
: VERTX_CONFIG.getVertxOptionsConfig().getBlockedThreadCheckInterval();
int workerPoolSize = VERTX_CONFIG == null || VERTX_CONFIG.getVertxOptionsConfig() == null ? -1
: VERTX_CONFIG.getVertxOptionsConfig().getWorkerPoolSize();
if (workerPoolSize != -1) {
vertxOptions.setWorkerPoolSize(workerPoolSize);
}
// TODO
// blockedThreadCheckInterval = 1000000L;
if (blockedThreadCheckInterval != -1) {
vertxOptions.setBlockedThreadCheckInterval(blockedThreadCheckInterval); // 不打印Thread blocked 阻塞日志
}
}
public static String bodyEncrypt(String body, String appCode) {
DataSecurity dataSecurity = getAppConfig(appCode).getDataSecurity();
switch (dataSecurity.getAlgorithm()) {
case "AES":
return MainSecurity.aesEncrypt(body, dataSecurity.getPrivateKey());
case "RSA":
return MainSecurity.rsaEncrypt(body, dataSecurity.getPublicKey());
default:
break;
}
log.info(" appCode:{}, encrypt key config is error.", appCode);
throw new HttpException(10011);
}
public static String bodyDecrypt(String body, String appCode) {
DataSecurity dataSecurity = getAppConfig(appCode).getDataSecurity();
switch (dataSecurity.getAlgorithm()) {
case "AES":
return MainSecurity.aesDecrypt(body, dataSecurity.getPrivateKey());
case "RSA":
return MainSecurity.rsaDecrypt(body, dataSecurity.getPrivateKey());
default:
break;
}
log.info(" appCode:{}, decrypt key config is error.", appCode);
throw new HttpException(10011);
}
}