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.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
@ -15,6 +16,7 @@ import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.TypeReference;
import com.hazelcast.config.Config;
import com.hazelcast.config.JoinConfig;
import com.hazelcast.config.ManagementCenterConfig;
import com.hazelcast.config.NetworkConfig;
import com.hazelcast.config.TcpIpConfig;
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.VertxOptions;
import io.vertx.core.http.HttpClient;
import io.vertx.core.http.HttpMethod;
import io.vertx.core.http.HttpServer;
import io.vertx.core.http.HttpServerOptions;
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.httpproxy.HttpProxy;
@ -62,6 +66,8 @@ import lombok.extern.slf4j.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;
public static CircuitBreaker CONNECTION_CIRCUIT_BREAKER;
// global cache app config
private static final ConcurrentHashMap<String, AppConfig> CACHE_APP_CONFIG_MAP = new ConcurrentHashMap<>();
@ -82,6 +88,14 @@ public class AppConfigHandler {
// 禁用appCode
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) {
DISABLED_APPCODE.add(appCode);
}
@ -98,6 +112,11 @@ public class AppConfigHandler {
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
? true
@ -194,17 +213,17 @@ public class AppConfigHandler {
*
* @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);
for (String appCode : set) {
AppConfigHandler.initAppConfig(redisTemplate, appCode, false);
AppConfigHandler.initAppConfig(appCode, false);
}
}
/***
* 加载vertx配置
*/
public static void initVertxConfig(RedisTemplate<String, String> redisTemplate) {
public static void initVertxConfig() {
String vertxConfigKey = RedisKeyConfig.VERTX_CONFIG_STRING_KEY;
String vertxConfigValue = redisTemplate.opsForValue().get(vertxConfigKey);
if (StringUtils.isNotBlank(vertxConfigValue)) {
@ -239,8 +258,7 @@ public class AppConfigHandler {
}
}
public static void initAppConfig(RedisTemplate<String, String> redisTemplate, String appCode,
boolean isDelLocalCache) {
public static void initAppConfig(String appCode, boolean isDelLocalCache) {
// 是否需要先删除
if (isDelLocalCache) {
delAppConfigCache(appCode);
@ -347,14 +365,14 @@ public class AppConfigHandler {
}
}
public static void createVertx(RedisTemplate<String, String> redisTemplate, SacVertxConfig sacVertxConfig) {
public static void createVertx() {
// TODO 编解码线程池,后面优化协程等方式
VertxOptions vertxOptions = new VertxOptions();
loadVertxOptions(vertxOptions);
VERTX = Vertx.vertx(vertxOptions);
initConnectionCircuitBreaker();
createVertxRouter(VERTX, redisTemplate, sacVertxConfig.getPort());
createVertxRouter();
}
private static Config hazelcastConfig(SacVertxConfig sacVertxConfig) {
@ -374,18 +392,17 @@ public class AppConfigHandler {
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);
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 Vertx createHazelcastClusterVertx(RedisTemplate<String, String> redisTemplate,
SacVertxConfig sacVertxConfig) {
public static Vertx createHazelcastClusterVertx() {
Config hazelcastConfig = hazelcastConfig(sacVertxConfig);
ClusterManager hazelcastClusterManager = new HazelcastClusterManager(hazelcastConfig);
// TODO 编解码线程池,后面优化协程等方式
@ -397,7 +414,7 @@ public class AppConfigHandler {
VERTX = res.result();
log.info("hazelcastClusterManager create success");
initConnectionCircuitBreaker();
createVertxRouter(VERTX, redisTemplate, sacVertxConfig.getPort());
createVertxRouter();
// 订阅消息
VERTX.eventBus().consumer("sac_cluster_event", message -> {
if (message.body() != null) {
@ -407,7 +424,7 @@ public class AppConfigHandler {
if (msg.getType() == 1) {
if (msg.getOperation() == 1) {
// 初始化AppConfig本地缓存
AppConfigHandler.initAppConfig(redisTemplate, msg.getAppCode(), true);
AppConfigHandler.initAppConfig(msg.getAppCode(), true);
} else if (msg.getOperation() == 3) {
// 禁用本地缓存
AppConfigHandler.addDisabledAppcode(msg.getAppCode());
@ -432,22 +449,21 @@ public class AppConfigHandler {
VERTX.eventBus().publish("sac_cluster_event", JSONObject.toJSONString(msg));
}
private static void createVertxRouter(Vertx vertx, RedisTemplate<String, String> redisTemplate,
Integer serverDefaultPort) {
private static void createVertxRouter() {
// consul初始化
// ConsulHandler.init(vertx);
// ConsulHandler.init1(vertx);
// 从redis同步app配置
initAllAppConfig(redisTemplate);
initAllAppConfig();
VertxConfig vertxConfig = AppConfigHandler.getVertxConfig();
// 创建HTTP监听
// 所有ip都能访问
HttpServerOptions httpServerOptions = new HttpServerOptions().setHost("0.0.0.0");
HttpServer server = vertx.createHttpServer(httpServerOptions);
Router mainHttpRouter = Router.router(vertx);
Integer serverPort = vertxConfig.getPort() == null ? serverDefaultPort : vertxConfig.getPort();
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()) {
@ -463,7 +479,7 @@ public class AppConfigHandler {
// clientOptions.setHttp2KeepAliveTimeout(1);
// clientOptions.setIdleTimeout(1000); // 连接空闲超时 毫秒
// HttpClient proxyClient = VERTX.createHttpClient(clientOptions);
HttpClient proxyClient = vertx.createHttpClient();
HttpClient proxyClient = VERTX.createHttpClient();
HttpProxy proxy = HttpProxy.reverseProxy(proxyClient);
proxy.originSelector(request -> Future.succeededFuture(ProxyTool.resolveOriginAddress(request)));
proxy.addInterceptor(new ProxyInterceptor() {
@ -473,6 +489,16 @@ public class AppConfigHandler {
// // 会跳转到 RestfulFailureHandlerImpl
// 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();
}
@ -487,11 +513,17 @@ public class AppConfigHandler {
return context.sendResponse();
}
});
WebClient mainWebClient = WebClient.create(vertx);
WebClient mainWebClient = WebClient.create(VERTX);
String rateLimitModel = vertxConfig.getRateLimitModel();
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(BodyHandler.create()).handler(ProxyHandler.create(mainWebClient, proxy))
.failureHandler(RestfulFailureHandler.create());

View File

@ -28,9 +28,10 @@ public class ParameterCheckHandlerImpl implements ParameterCheckHandler {
return;
}
// 通过请求模式来区分
String uri = rc.request().uri();
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));
return;
}

View File

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

View File

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

View File

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

View File

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