vertx网关支持唯一rpc uri, 客户端统一调用

This commit is contained in:
ztzh_xieyun 2024-05-11 14:57:45 +08:00
parent e812d6dbf8
commit 9e0ec6ed28
6 changed files with 77 additions and 32 deletions

View File

@ -3,6 +3,7 @@ package com.sf.vertx.handle;
import java.time.Duration; import java.time.Duration;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
@ -15,6 +16,7 @@ import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.TypeReference; import com.alibaba.fastjson2.TypeReference;
import com.hazelcast.config.Config; import com.hazelcast.config.Config;
import com.hazelcast.config.JoinConfig; import com.hazelcast.config.JoinConfig;
import com.hazelcast.config.ManagementCenterConfig;
import com.hazelcast.config.NetworkConfig; import com.hazelcast.config.NetworkConfig;
import com.hazelcast.config.TcpIpConfig; import com.hazelcast.config.TcpIpConfig;
import com.sf.vertx.api.pojo.ApiConfig; import com.sf.vertx.api.pojo.ApiConfig;
@ -40,9 +42,11 @@ import io.vertx.core.Future;
import io.vertx.core.Vertx; import io.vertx.core.Vertx;
import io.vertx.core.VertxOptions; import io.vertx.core.VertxOptions;
import io.vertx.core.http.HttpClient; import io.vertx.core.http.HttpClient;
import io.vertx.core.http.HttpMethod;
import io.vertx.core.http.HttpServer; import io.vertx.core.http.HttpServer;
import io.vertx.core.http.HttpServerOptions; import io.vertx.core.http.HttpServerOptions;
import io.vertx.core.spi.cluster.ClusterManager; import io.vertx.core.spi.cluster.ClusterManager;
import io.vertx.ext.web.Route;
import io.vertx.ext.web.Router; import io.vertx.ext.web.Router;
import io.vertx.ext.web.client.WebClient; import io.vertx.ext.web.client.WebClient;
import io.vertx.httpproxy.HttpProxy; import io.vertx.httpproxy.HttpProxy;
@ -62,6 +66,8 @@ import lombok.extern.slf4j.Slf4j;
public class AppConfigHandler { public class AppConfigHandler {
private static VertxConfig VERTX_CONFIG = new VertxConfig(); private static VertxConfig VERTX_CONFIG = new VertxConfig();
public static Vertx VERTX; public static Vertx VERTX;
private static SacVertxConfig sacVertxConfig;
private static RedisTemplate<String, String> redisTemplate;
public static CircuitBreaker CONNECTION_CIRCUIT_BREAKER; public static CircuitBreaker CONNECTION_CIRCUIT_BREAKER;
// global cache app config // global cache app config
private static final ConcurrentHashMap<String, AppConfig> CACHE_APP_CONFIG_MAP = new ConcurrentHashMap<>(); private static final ConcurrentHashMap<String, AppConfig> CACHE_APP_CONFIG_MAP = new ConcurrentHashMap<>();
@ -82,6 +88,14 @@ public class AppConfigHandler {
// 禁用appCode // 禁用appCode
private static ConcurrentHashSet<String> DISABLED_APPCODE = new ConcurrentHashSet<String>(); private static ConcurrentHashSet<String> DISABLED_APPCODE = new ConcurrentHashSet<String>();
public static Integer requestModel() {
return sacVertxConfig.getRequestModel();
}
public static String rpcUri() {
return sacVertxConfig.getRpcUri();
}
public static void addDisabledAppcode(String appCode) { public static void addDisabledAppcode(String appCode) {
DISABLED_APPCODE.add(appCode); DISABLED_APPCODE.add(appCode);
} }
@ -98,6 +112,11 @@ public class AppConfigHandler {
return CACHE_APP_CONFIG_MAP.get(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) { public static boolean isDataSecurity(String appCode) {
return CACHE_APP_CONFIG_MAP.get(appCode) != null && CACHE_APP_CONFIG_MAP.get(appCode).getDataSecurity() != null return CACHE_APP_CONFIG_MAP.get(appCode) != null && CACHE_APP_CONFIG_MAP.get(appCode).getDataSecurity() != null
? true ? true
@ -194,17 +213,17 @@ public class AppConfigHandler {
* *
* @throws Exception * @throws Exception
*/ */
public static void initAllAppConfig(RedisTemplate<String, String> redisTemplate) { public static void initAllAppConfig() {
Set<String> set = redisTemplate.opsForZSet().range(RedisKeyConfig.APP_CONFIG_SET_KEY, 0, -1); Set<String> set = redisTemplate.opsForZSet().range(RedisKeyConfig.APP_CONFIG_SET_KEY, 0, -1);
for (String appCode : set) { for (String appCode : set) {
AppConfigHandler.initAppConfig(redisTemplate, appCode, false); AppConfigHandler.initAppConfig(appCode, false);
} }
} }
/*** /***
* 加载vertx配置 * 加载vertx配置
*/ */
public static void initVertxConfig(RedisTemplate<String, String> redisTemplate) { public static void initVertxConfig() {
String vertxConfigKey = RedisKeyConfig.VERTX_CONFIG_STRING_KEY; String vertxConfigKey = RedisKeyConfig.VERTX_CONFIG_STRING_KEY;
String vertxConfigValue = redisTemplate.opsForValue().get(vertxConfigKey); String vertxConfigValue = redisTemplate.opsForValue().get(vertxConfigKey);
if (StringUtils.isNotBlank(vertxConfigValue)) { if (StringUtils.isNotBlank(vertxConfigValue)) {
@ -239,8 +258,7 @@ public class AppConfigHandler {
} }
} }
public static void initAppConfig(RedisTemplate<String, String> redisTemplate, String appCode, public static void initAppConfig(String appCode, boolean isDelLocalCache) {
boolean isDelLocalCache) {
// 是否需要先删除 // 是否需要先删除
if (isDelLocalCache) { if (isDelLocalCache) {
delAppConfigCache(appCode); delAppConfigCache(appCode);
@ -347,14 +365,14 @@ public class AppConfigHandler {
} }
} }
public static void createVertx(RedisTemplate<String, String> redisTemplate, SacVertxConfig sacVertxConfig) { public static void createVertx() {
// TODO 编解码线程池,后面优化协程等方式 // TODO 编解码线程池,后面优化协程等方式
VertxOptions vertxOptions = new VertxOptions(); VertxOptions vertxOptions = new VertxOptions();
loadVertxOptions(vertxOptions); loadVertxOptions(vertxOptions);
VERTX = Vertx.vertx(vertxOptions); VERTX = Vertx.vertx(vertxOptions);
initConnectionCircuitBreaker(); initConnectionCircuitBreaker();
createVertxRouter(VERTX, redisTemplate, sacVertxConfig.getPort()); createVertxRouter();
} }
private static Config hazelcastConfig(SacVertxConfig sacVertxConfig) { private static Config hazelcastConfig(SacVertxConfig sacVertxConfig) {
@ -376,16 +394,15 @@ public class AppConfigHandler {
hazelcastConfig.setNetworkConfig(networkConfig); hazelcastConfig.setNetworkConfig(networkConfig);
// TODO 还有问题,不会使用 // TODO 还有问题,不会使用
// ManagementCenterConfig managementCenterConfig = new ManagementCenterConfig(); ManagementCenterConfig managementCenterConfig = new ManagementCenterConfig();
// Set<String> interfaces = new HashSet<>(); Set<String> interfaces = new HashSet<>();
// interfaces.add("http://192.168.1.68:8080/mancenter"); interfaces.add("http://192.168.1.68:8080/mancenter");
// managementCenterConfig.setTrustedInterfaces(interfaces); managementCenterConfig.setTrustedInterfaces(interfaces);
// hazelcastConfig.setManagementCenterConfig(managementCenterConfig); hazelcastConfig.setManagementCenterConfig(managementCenterConfig);
return hazelcastConfig; return hazelcastConfig;
} }
public static Vertx createHazelcastClusterVertx(RedisTemplate<String, String> redisTemplate, public static Vertx createHazelcastClusterVertx() {
SacVertxConfig sacVertxConfig) {
Config hazelcastConfig = hazelcastConfig(sacVertxConfig); Config hazelcastConfig = hazelcastConfig(sacVertxConfig);
ClusterManager hazelcastClusterManager = new HazelcastClusterManager(hazelcastConfig); ClusterManager hazelcastClusterManager = new HazelcastClusterManager(hazelcastConfig);
// TODO 编解码线程池,后面优化协程等方式 // TODO 编解码线程池,后面优化协程等方式
@ -397,7 +414,7 @@ public class AppConfigHandler {
VERTX = res.result(); VERTX = res.result();
log.info("hazelcastClusterManager create success"); log.info("hazelcastClusterManager create success");
initConnectionCircuitBreaker(); initConnectionCircuitBreaker();
createVertxRouter(VERTX, redisTemplate, sacVertxConfig.getPort()); createVertxRouter();
// 订阅消息 // 订阅消息
VERTX.eventBus().consumer("sac_cluster_event", message -> { VERTX.eventBus().consumer("sac_cluster_event", message -> {
if (message.body() != null) { if (message.body() != null) {
@ -407,7 +424,7 @@ public class AppConfigHandler {
if (msg.getType() == 1) { if (msg.getType() == 1) {
if (msg.getOperation() == 1) { if (msg.getOperation() == 1) {
// 初始化AppConfig本地缓存 // 初始化AppConfig本地缓存
AppConfigHandler.initAppConfig(redisTemplate, msg.getAppCode(), true); AppConfigHandler.initAppConfig(msg.getAppCode(), true);
} else if (msg.getOperation() == 3) { } else if (msg.getOperation() == 3) {
// 禁用本地缓存 // 禁用本地缓存
AppConfigHandler.addDisabledAppcode(msg.getAppCode()); AppConfigHandler.addDisabledAppcode(msg.getAppCode());
@ -432,22 +449,21 @@ public class AppConfigHandler {
VERTX.eventBus().publish("sac_cluster_event", JSONObject.toJSONString(msg)); VERTX.eventBus().publish("sac_cluster_event", JSONObject.toJSONString(msg));
} }
private static void createVertxRouter(Vertx vertx, RedisTemplate<String, String> redisTemplate, private static void createVertxRouter() {
Integer serverDefaultPort) {
// consul初始化 // consul初始化
// ConsulHandler.init(vertx); // ConsulHandler.init(vertx);
// ConsulHandler.init1(vertx); // ConsulHandler.init1(vertx);
// 从redis同步app配置 // 从redis同步app配置
initAllAppConfig(redisTemplate); initAllAppConfig();
VertxConfig vertxConfig = AppConfigHandler.getVertxConfig(); VertxConfig vertxConfig = AppConfigHandler.getVertxConfig();
// 创建HTTP监听 // 创建HTTP监听
// 所有ip都能访问 // 所有ip都能访问
HttpServerOptions httpServerOptions = new HttpServerOptions().setHost("0.0.0.0"); HttpServerOptions httpServerOptions = new HttpServerOptions().setHost("0.0.0.0");
HttpServer server = vertx.createHttpServer(httpServerOptions); HttpServer server = VERTX.createHttpServer(httpServerOptions);
Router mainHttpRouter = Router.router(vertx); Router mainHttpRouter = Router.router(VERTX);
Integer serverPort = vertxConfig.getPort() == null ? serverDefaultPort : vertxConfig.getPort(); Integer serverPort = vertxConfig.getPort() == null ? sacVertxConfig.getPort() : vertxConfig.getPort();
log.info("serverPort:{}", serverPort); log.info("serverPort:{}", serverPort);
server.requestHandler(mainHttpRouter).listen(serverPort, h -> { server.requestHandler(mainHttpRouter).listen(serverPort, h -> {
if (h.succeeded()) { if (h.succeeded()) {
@ -463,7 +479,7 @@ public class AppConfigHandler {
// clientOptions.setHttp2KeepAliveTimeout(1); // clientOptions.setHttp2KeepAliveTimeout(1);
// clientOptions.setIdleTimeout(1000); // 连接空闲超时 毫秒 // clientOptions.setIdleTimeout(1000); // 连接空闲超时 毫秒
// HttpClient proxyClient = VERTX.createHttpClient(clientOptions); // HttpClient proxyClient = VERTX.createHttpClient(clientOptions);
HttpClient proxyClient = vertx.createHttpClient(); HttpClient proxyClient = VERTX.createHttpClient();
HttpProxy proxy = HttpProxy.reverseProxy(proxyClient); HttpProxy proxy = HttpProxy.reverseProxy(proxyClient);
proxy.originSelector(request -> Future.succeededFuture(ProxyTool.resolveOriginAddress(request))); proxy.originSelector(request -> Future.succeededFuture(ProxyTool.resolveOriginAddress(request)));
proxy.addInterceptor(new ProxyInterceptor() { proxy.addInterceptor(new ProxyInterceptor() {
@ -473,6 +489,16 @@ public class AppConfigHandler {
// // 会跳转到 RestfulFailureHandlerImpl // // 会跳转到 RestfulFailureHandlerImpl
// throw new HttpException(10003); // throw new HttpException(10003);
// } // }
if (AppConfigHandler.requestModel() == 2) {
String appCode = context.request().headers().get(getAppCodeHeaderKey());
String apiCode = context.request().headers().get(getApiCodeHeaderKey());
String key = appCode + ":" + apiCode;
String uri = APICODE_CONFIG_MAP.get(key).getUri();
String method = APICODE_CONFIG_MAP.get(key).getMethod();
context.request().setURI(uri).setMethod(HttpMethod.valueOf(method));
}
return context.sendRequest(); return context.sendRequest();
} }
@ -487,11 +513,17 @@ public class AppConfigHandler {
return context.sendResponse(); return context.sendResponse();
} }
}); });
WebClient mainWebClient = WebClient.create(vertx); WebClient mainWebClient = WebClient.create(VERTX);
String rateLimitModel = vertxConfig.getRateLimitModel(); String rateLimitModel = vertxConfig.getRateLimitModel();
rateLimitModel = "local"; rateLimitModel = "local";
mainHttpRouter.route().handler(ParameterCheckHandler.create()) Route route = null;
if (requestModel() == 2) {
route = mainHttpRouter.route(rpcUri());
} else {
route = mainHttpRouter.route();
}
route.handler(ParameterCheckHandler.create())
.handler(AppRateLimitHandler.create(rateLimitModel)).handler(ApiRateLimitHandler.create(rateLimitModel)) .handler(AppRateLimitHandler.create(rateLimitModel)).handler(ApiRateLimitHandler.create(rateLimitModel))
.handler(BodyHandler.create()).handler(ProxyHandler.create(mainWebClient, proxy)) .handler(BodyHandler.create()).handler(ProxyHandler.create(mainWebClient, proxy))
.failureHandler(RestfulFailureHandler.create()); .failureHandler(RestfulFailureHandler.create());

View File

@ -28,9 +28,10 @@ public class ParameterCheckHandlerImpl implements ParameterCheckHandler {
return; return;
} }
// 通过请求模式来区分
String uri = rc.request().uri(); String uri = rc.request().uri();
String httpMethod = rc.request().method().name(); String httpMethod = rc.request().method().name();
if(AppConfigHandler.isApicodeUri(key, uri, httpMethod) == false) { if(AppConfigHandler.requestModel() == 1 && AppConfigHandler.isApicodeUri(key, uri, httpMethod) == false) {
rc.fail(new HttpException(10018)); rc.fail(new HttpException(10018));
return; return;
} }

View File

@ -36,8 +36,9 @@ public class DynamicBuildServer implements ApplicationRunner {
public void run(ApplicationArguments args) throws Exception { public void run(ApplicationArguments args) throws Exception {
// 初始化redis key // 初始化redis key
redisKeyConfig.init(); redisKeyConfig.init();
AppConfigHandler.init(redisTemplate, sacVertxConfig);
// 从redis同步vertx配置 // 从redis同步vertx配置
AppConfigHandler.initVertxConfig(redisTemplate); AppConfigHandler.initVertxConfig();
// 加载vertx应用配置 // 加载vertx应用配置
startVertxService(); startVertxService();
@ -50,9 +51,9 @@ public class DynamicBuildServer implements ApplicationRunner {
*/ */
private void startVertxService() throws Exception { private void startVertxService() throws Exception {
// 单机 // 单机
//AppConfigHandler.createVertx(redisTemplate, sacVertxConfig); //AppConfigHandler.createVertx();
// 集群 // 集群
AppConfigHandler.createHazelcastClusterVertx(redisTemplate, sacVertxConfig); AppConfigHandler.createHazelcastClusterVertx();
} }
} }

View File

@ -19,6 +19,12 @@ public class SacVertxConfig {
@Value("${server.vertx.cluster.ip}") @Value("${server.vertx.cluster.ip}")
private String clusterIp; private String clusterIp;
@Value("${server.vertx.requestModel}")
private Integer requestModel;
@Value("${server.vertx.rpcUri}")
private String rpcUri;
@Value("${server.vertx.cluster.clusterName}") @Value("${server.vertx.cluster.clusterName}")
private String clusterName; private String clusterName;
} }

View File

@ -68,7 +68,7 @@ public class AppConfigServiceImpl implements AppConfigService {
public void saveVertxConfig(VertxConfig vertxConfig) { public void saveVertxConfig(VertxConfig vertxConfig) {
String vertxConfigKey = RedisKeyConfig.VERTX_CONFIG_STRING_KEY; String vertxConfigKey = RedisKeyConfig.VERTX_CONFIG_STRING_KEY;
redisTemplate.opsForValue().set(vertxConfigKey, JSONObject.toJSONString(vertxConfig)); redisTemplate.opsForValue().set(vertxConfigKey, JSONObject.toJSONString(vertxConfig));
AppConfigHandler.initVertxConfig(redisTemplate); AppConfigHandler.initVertxConfig();
} }
} }

View File

@ -1,10 +1,15 @@
# 开发环境配置 # 开发环境配置
server: server:
vertx: vertx:
requestModel: 1 # 1: 客户端传递uri. 2: uri vertx代理,不对客户端暴露uri
rpcUri: /rpc
environment: dev environment: dev
server: server:
default: default:
port: 80 port: 80
cluster:
ip: 192.168.1.68
clusterName: sac-dev
# 服务器的HTTP端口默认为8080 # 服务器的HTTP端口默认为8080
port: 5566 port: 5566
servlet: servlet: