-
+
@@ -111,6 +111,7 @@ Starting from v1.3.0, the frontend and backend of the management backend are mer
| v2.3.2 | v2.3.2 |
| v2.3.3 | v2.3.3 |
| v2.4.0 | v2.4.0 |
+| v2.4.1 | v2.4.1 |
Please download the corresponding management backend version according to the version of the community version
diff --git a/README.md b/README.md
index cf9ed5a..4d51e91 100644
--- a/README.md
+++ b/README.md
@@ -3,7 +3,7 @@
-
+
@@ -113,6 +113,7 @@ API地址:http://demo.fizzgate.com/proxy/[服务名]/[API_Path]
| v2.3.2 | v2.3.2 |
| v2.3.3 | v2.3.3 |
| v2.4.0 | v2.4.0 |
+| v2.4.1 | v2.4.1 |
请根据社区版的版本下载对应的管理后台版本
diff --git a/fizz-bootstrap/pom.xml b/fizz-bootstrap/pom.xml
index 559d934..dedc737 100644
--- a/fizz-bootstrap/pom.xml
+++ b/fizz-bootstrap/pom.xml
@@ -16,13 +16,13 @@
1.8
- 5.2.18.RELEASE
+ 5.2.19.RELEASEDragonfruit-SR3Dysprosium-SR255.3.7.RELEASE
- 4.1.70.Final
- 4.4.14
- 2.14.1
+ 4.1.72.Final
+ 4.4.15
+ 2.17.01.7.323.12.01.18.22
@@ -37,6 +37,7 @@
2.0.46.Final2.2.9.RELEASE1.7.1
+ 1.30
@@ -99,6 +100,12 @@
resilience4j-reactor${resilience4j.version}
+
+
+ io.netty
+ netty-tcnative-classes
+ ${netty-tcnative.version}
+
diff --git a/fizz-bootstrap/src/main/java/we/FizzBootstrapApplication.java b/fizz-bootstrap/src/main/java/we/FizzBootstrapApplication.java
index ef0e335..e54ab0c 100644
--- a/fizz-bootstrap/src/main/java/we/FizzBootstrapApplication.java
+++ b/fizz-bootstrap/src/main/java/we/FizzBootstrapApplication.java
@@ -186,7 +186,8 @@ public class FizzBootstrapApplication {
private static final Logger LOGGER = LoggerFactory.getLogger(FizzBootstrapApplication.class);
public static void main(String[] args) {
- System.setProperty("log4j2.contextSelector", "org.apache.logging.log4j.core.async.AsyncLoggerContextSelector");
+ System.setProperty("log4j2.contextSelector", "org.apache.logging.log4j.core.async.AsyncLoggerContextSelector");
+ System.setProperty("log4j2.formatMsgNoLookups", "true");
SpringApplication springApplication = new SpringApplication(FizzBootstrapApplication.class);
springApplication.setApplicationContextClass(CustomReactiveWebServerApplicationContext.class);
diff --git a/fizz-bootstrap/src/main/resources/application.yml b/fizz-bootstrap/src/main/resources/application.yml
index d461f2e..1b2886f 100644
--- a/fizz-bootstrap/src/main/resources/application.yml
+++ b/fizz-bootstrap/src/main/resources/application.yml
@@ -20,7 +20,7 @@ eureka:
enabled: false #use Eureka? (default:false)
serviceUrl:
# need replace
- defaultZone: http://localhost:6600/eureka/ #please input the eureka client serviceUrl defaultZone (default:http://localhost:6600/eureka/)
+ defaultZone: http://6.6.6.6:6600/eureka/ #please input the eureka client serviceUrl defaultZone (default:http://localhost:6600/eureka/)
instance:
prefer-ip-address: true
################################################### Eureka config end ###################################################
@@ -52,7 +52,7 @@ spring:
aggregate:
redis:
# need replace
- host: 6.6.6.6 #please input the redis host (default:localhost)
+ host: 1.1.1.1 #please input the redis host (default:localhost)
# need replace
port: 6379 #please input the redis port (default:6379)
# need replace
@@ -127,15 +127,22 @@ fizz:
retry-count: 0 # default no retry
retry-interval: 0 # default no retry interval
crypto: true # if true, client will encrypt request body and decrypt response body
-# service-registration:
-# type: eureka # service registration type, can be eureka or nacos
-# application: ax # register the name of this application to server
-# port: 8601 # the port to be registered
-# service-url: http://6.6.6.6:6600/eureka/ # server address
-# type: nacos
-# application: ax
-# port: 8601
-# service-url: 6.6.6.6:8848
+ service-registration:
+# eureka:
+# server-port: 8601
+# client:
+# enabled: true
+# serviceUrl:
+# defaultZone: http://3.3.3.3:6600/eureka
+# instance:
+# appname: fizz-dedicated-line
+# prefer-ip-address: true
+# nacos:
+# discovery:
+# enabled: true
+# service: fizz-dedicated-line
+# port: 8601
+# server-addr: 2.2.2.2:8848
fizz-trace-id:
header: X-Trace-Id
diff --git a/fizz-bootstrap/src/main/resources/log4j2-spring.xml b/fizz-bootstrap/src/main/resources/log4j2-spring.xml
index fdd5dce..b948186 100644
--- a/fizz-bootstrap/src/main/resources/log4j2-spring.xml
+++ b/fizz-bootstrap/src/main/resources/log4j2-spring.xml
@@ -7,10 +7,10 @@
-
+
-
+
diff --git a/fizz-common/src/main/java/we/util/Consts.java b/fizz-common/src/main/java/we/util/Consts.java
index b6e05f0..e9a1852 100644
--- a/fizz-common/src/main/java/we/util/Consts.java
+++ b/fizz-common/src/main/java/we/util/Consts.java
@@ -27,6 +27,7 @@ public final class Consts {
}
public static final class S {
+ public static final String DEFAULT = "default";
public static final String TRUE = "true";
public static final String FALSE = "false";
public static final String TRUE1 = "1";
diff --git a/fizz-common/src/main/java/we/util/FileUtils.java b/fizz-common/src/main/java/we/util/FileUtils.java
new file mode 100644
index 0000000..9a31fa1
--- /dev/null
+++ b/fizz-common/src/main/java/we/util/FileUtils.java
@@ -0,0 +1,34 @@
+package we.util;
+
+import java.io.File;
+import java.util.Objects;
+
+/**
+ * @author hongqiaowei
+ */
+
+public abstract class FileUtils {
+
+ private FileUtils() {
+ }
+
+ public static String getAppRootDir() {
+ return new File(Consts.S.EMPTY).getAbsolutePath();
+ }
+
+ public static String getAbsoluteDir(Class> cls) {
+ return new File(Objects.requireNonNull(cls.getResource(Consts.S.EMPTY)).getPath()).getAbsolutePath();
+ }
+
+ public static String getAbsolutePath(Class> cls) {
+ String absoluteDir = getAbsoluteDir(cls);
+ return absoluteDir + File.separatorChar + cls.getSimpleName() + ".class";
+ }
+
+ /**
+ * @param file relative to src or resource dir, eg: we/util/FileUtils.class and application.yml
+ */
+ public static String getAbsolutePath(String file) {
+ return new File(Objects.requireNonNull(FileUtils.class.getClassLoader().getResource(file)).getPath()).getAbsolutePath();
+ }
+}
diff --git a/fizz-common/src/main/java/we/util/PropertiesUtils.java b/fizz-common/src/main/java/we/util/PropertiesUtils.java
new file mode 100644
index 0000000..6510412
--- /dev/null
+++ b/fizz-common/src/main/java/we/util/PropertiesUtils.java
@@ -0,0 +1,70 @@
+package we.util;
+
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.BeanWrapperImpl;
+import org.springframework.beans.PropertyAccessor;
+
+import java.util.Map;
+import java.util.Properties;
+
+/**
+ * @author hongqiaowei
+ */
+
+public abstract class PropertiesUtils {
+
+ private PropertiesUtils() {
+ }
+
+ public static String normalize(String propertyName) {
+ char[] chars = propertyName.toCharArray();
+ StringBuilder b = new StringBuilder(chars.length);
+ for (int i = 0; i < chars.length; i++) {
+ char c = chars[i];
+ if (c == Consts.S.DASH) {
+ b.append(Character.toUpperCase(chars[++i]));
+ } else {
+ b.append(c);
+ }
+ }
+ return b.toString();
+ }
+
+ public static Properties remove(Properties properties, String prefix) {
+ Properties result = new Properties();
+ properties.forEach(
+ (k, v) -> {
+ String s = k.toString();
+ int idx = s.indexOf(prefix);
+ if (idx > -1) {
+ s = s.substring(prefix.length() + 1);
+ }
+ result.setProperty(s, v.toString());
+ }
+ );
+ return result;
+ }
+
+ public static void setBeanPropertyValue(Object bean, Properties properties) {
+ setBeanPropertyValue(bean, properties, null);
+ }
+
+ public static void setBeanPropertyValue(Object bean, Properties properties, Map> propertyTypeHint) {
+ BeanWrapperImpl beanWrapper = new BeanWrapperImpl(bean);
+ for (String propertyName : properties.stringPropertyNames()) {
+ if (beanWrapper.isWritableProperty(propertyName)) {
+ beanWrapper.setPropertyValue(propertyName, properties.get(propertyName));
+ } else if (propertyTypeHint != null) {
+ int dotPos = propertyName.lastIndexOf(Consts.S.DOT);
+ if (dotPos > -1) {
+ String prefix = propertyName.substring(0, dotPos);
+ Class> aClass = propertyTypeHint.get(prefix);
+ if (aClass != null && Map.class.isAssignableFrom(aClass)) {
+ String newPropertyName = prefix + PropertyAccessor.PROPERTY_KEY_PREFIX_CHAR + propertyName.substring(dotPos + 1) + PropertyAccessor.PROPERTY_KEY_SUFFIX_CHAR;
+ beanWrapper.setPropertyValue(newPropertyName, properties.get(propertyName));
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/fizz-common/src/main/java/we/util/YmlUtils.java b/fizz-common/src/main/java/we/util/YmlUtils.java
new file mode 100644
index 0000000..91112f8
--- /dev/null
+++ b/fizz-common/src/main/java/we/util/YmlUtils.java
@@ -0,0 +1,34 @@
+package we.util;
+
+import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
+import org.springframework.core.io.ByteArrayResource;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.core.io.Resource;
+
+import java.util.Properties;
+
+/**
+ * @author hongqiaowei
+ */
+
+public abstract class YmlUtils {
+
+ private YmlUtils() {
+ }
+
+ public static Properties file2properties(String file) {
+ Resource resource = new ClassPathResource(file);
+ return getProperties(resource);
+ }
+
+ public static Properties string2properties(String config) {
+ Resource resource = new ByteArrayResource(config.getBytes());
+ return getProperties(resource);
+ }
+
+ private static Properties getProperties(Resource resource) {
+ YamlPropertiesFactoryBean yamlPropertiesFactoryBean = new YamlPropertiesFactoryBean();
+ yamlPropertiesFactoryBean.setResources(resource);
+ return yamlPropertiesFactoryBean.getObject();
+ }
+}
diff --git a/fizz-core/pom.xml b/fizz-core/pom.xml
index 053c530..ead62d6 100644
--- a/fizz-core/pom.xml
+++ b/fizz-core/pom.xml
@@ -329,6 +329,10 @@
io.nettynetty-tcnative-boringssl-static
+
+ io.netty
+ netty-tcnative-classes
+
diff --git a/fizz-core/src/main/java/we/dedicated_line/DedicatedLineServiceRegistration.java b/fizz-core/src/main/java/we/dedicated_line/DedicatedLineServiceRegistration.java
index a474b6b..4869c0a 100644
--- a/fizz-core/src/main/java/we/dedicated_line/DedicatedLineServiceRegistration.java
+++ b/fizz-core/src/main/java/we/dedicated_line/DedicatedLineServiceRegistration.java
@@ -19,27 +19,25 @@ package we.dedicated_line;
import com.alibaba.cloud.nacos.discovery.NacosDiscoveryAutoConfiguration;
import lombok.SneakyThrows;
-import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.boot.env.OriginTrackedMapPropertySource;
import org.springframework.boot.web.reactive.context.ReactiveWebServerApplicationContext;
import org.springframework.cloud.client.ConditionalOnDiscoveryEnabled;
-import org.springframework.cloud.client.serviceregistry.Registration;
-import org.springframework.cloud.client.serviceregistry.ServiceRegistry;
-import org.springframework.cloud.commons.util.InetUtils;
import org.springframework.cloud.netflix.eureka.EurekaClientAutoConfiguration;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.ConfigurableEnvironment;
+import org.springframework.core.env.PropertySource;
import we.config.SystemConfig;
+import we.service_registry.FizzServiceRegistration;
import we.service_registry.eureka.FizzEurekaHelper;
-import we.service_registry.eureka.FizzEurekaProperties;
-import we.service_registry.eureka.FizzEurekaServiceRegistration;
import we.service_registry.nacos.FizzNacosHelper;
-import we.service_registry.nacos.FizzNacosProperties;
-import we.service_registry.nacos.FizzNacosServiceRegistration;
import javax.annotation.PreDestroy;
+import java.util.Properties;
/**
* @author hongqiaowei
@@ -51,9 +49,9 @@ import javax.annotation.PreDestroy;
@AutoConfigureAfter({EurekaClientAutoConfiguration.class, NacosDiscoveryAutoConfiguration.class})
public class DedicatedLineServiceRegistration implements ApplicationListener {
- private ServiceRegistry serviceRegistry;
+ private static final Logger log = LoggerFactory.getLogger(DedicatedLineServiceRegistration.class);
- private Registration registration;
+ private FizzServiceRegistration fizzServiceRegistration;
@SneakyThrows
@Override
@@ -62,70 +60,75 @@ public class DedicatedLineServiceRegistration implements ApplicationListener propertySource : env.getPropertySources()) {
+ if (propertySource instanceof OriginTrackedMapPropertySource) {
+ OriginTrackedMapPropertySource originTrackedMapPropertySource = (OriginTrackedMapPropertySource) propertySource;
+ String[] propertyNames = originTrackedMapPropertySource.getPropertyNames();
+ for (String propertyName : propertyNames) {
+ if (propertyName.length() > 55) {
+ int eurekaPos = propertyName.indexOf("eureka");
+ if (eurekaPos > -1) {
+ eurekaProperties.setProperty(propertyName.substring(eurekaPos), originTrackedMapPropertySource.getProperty(propertyName).toString());
+ find = true;
+ }
+ }
+ }
+ if (find) {
+ break;
+ }
+ }
+ }
+ if (!find) {
+ log.error("no eureka config");
+ return;
+ }
+ fizzServiceRegistration = FizzEurekaHelper.getServiceRegistration(applicationContext, eurekaProperties);
}
- if ("nacos".equals(type)) {
- String application = env.getProperty(prefix + ".application");
- String ipAddress = env.getProperty(prefix + ".ip-address");
- String port = env.getProperty(prefix + ".port");
- String serviceUrl = env.getProperty(prefix + ".service-url");
- String namespace = env.getProperty(prefix + ".namespace", "");
- String group = env.getProperty(prefix + ".group", "DEFAULT_GROUP");
- String clusterName = env.getProperty(prefix + ".clusterName", "DEFAULT");
-
- FizzNacosProperties fizzNacosProperties = new FizzNacosProperties();
- fizzNacosProperties.setApplicationContext(applicationContext);
- fizzNacosProperties.setId(application + ':' + serviceUrl);
- fizzNacosProperties.setService(application);
- fizzNacosProperties.setIp(ipAddress == null ? applicationContext.getBean(InetUtils.class).findFirstNonLoopbackAddress().getHostAddress() : ipAddress);
- fizzNacosProperties.setPort(Integer.parseInt(port));
- fizzNacosProperties.setNamespace(namespace.equals("") ? null : namespace);
- fizzNacosProperties.setGroup(group);
- fizzNacosProperties.setClusterName(clusterName);
- fizzNacosProperties.setNamespace("");
- fizzNacosProperties.setSecretKey("");
- fizzNacosProperties.setAccessKey("");
- fizzNacosProperties.setUsername("");
- fizzNacosProperties.setPassword("");
- fizzNacosProperties.setEndpoint("");
- fizzNacosProperties.setLogName("");
- fizzNacosProperties.setNamingLoadCacheAtStart("false");
- fizzNacosProperties.setServerAddr(serviceUrl);
-
- FizzNacosServiceRegistration fizzNacosServiceRegistration = FizzNacosHelper.getServiceRegistration(fizzNacosProperties);
- serviceRegistry = fizzNacosServiceRegistration.serviceRegistry;
- registration = fizzNacosServiceRegistration.registration;
+ if (nacos) {
+ Properties nacosProperties = new Properties();
+ boolean find = false;
+ for (PropertySource> propertySource : env.getPropertySources()) {
+ if (propertySource instanceof OriginTrackedMapPropertySource) {
+ OriginTrackedMapPropertySource originTrackedMapPropertySource = (OriginTrackedMapPropertySource) propertySource;
+ String[] propertyNames = originTrackedMapPropertySource.getPropertyNames();
+ for (String propertyName : propertyNames) {
+ if (propertyName.length() > 64) {
+ int naocsPos = propertyName.indexOf("nacos");
+ if (naocsPos > -1) {
+ nacosProperties.setProperty(propertyName.substring(naocsPos), originTrackedMapPropertySource.getProperty(propertyName).toString());
+ find = true;
+ }
+ }
+ }
+ if (find) {
+ break;
+ }
+ }
+ }
+ if (!find) {
+ log.error("no nacos config");
+ return;
+ }
+ fizzServiceRegistration = FizzNacosHelper.getServiceRegistration(applicationContext, nacosProperties);
}
- serviceRegistry.register(registration);
+ fizzServiceRegistration.register();
}
}
@PreDestroy
public void stop() {
- if (serviceRegistry != null) {
- serviceRegistry.deregister(registration);
+ if (fizzServiceRegistration != null) {
+ fizzServiceRegistration.deregister();
}
}
}
diff --git a/fizz-core/src/main/java/we/filter/CallbackFilter.java b/fizz-core/src/main/java/we/filter/CallbackFilter.java
index 57fa36b..8ee27da 100644
--- a/fizz-core/src/main/java/we/filter/CallbackFilter.java
+++ b/fizz-core/src/main/java/we/filter/CallbackFilter.java
@@ -43,6 +43,7 @@ import we.plugin.auth.Receiver;
import we.proxy.CallbackService;
import we.proxy.DiscoveryClientUriSelector;
import we.proxy.ServiceInstance;
+import we.service_registry.RegistryCenterService;
import we.util.Consts;
import we.util.NettyDataBufferUtils;
import we.util.ThreadContext;
@@ -75,6 +76,9 @@ public class CallbackFilter extends FizzWebFilter {
@Resource
private CallbackFilterProperties callbackFilterProperties;
+ @Resource
+ private RegistryCenterService registryCenterService;
+
@Resource(name = AggregateRedisConfig.AGGREGATE_REACTIVE_REDIS_TEMPLATE)
private ReactiveStringRedisTemplate rt;
@@ -142,7 +146,14 @@ public class CallbackFilter extends FizzWebFilter {
List receivers = ac.callbackConfig.receivers;
for (Receiver r : receivers) {
if (r.type == ApiConfig.Type.SERVICE_DISCOVERY) {
- ServiceInstance inst = discoveryClientSelector.getNextInstance(r.service);
+ ServiceInstance inst = null;
+ if (r.registryCenter == null) {
+ inst = discoveryClientSelector.getNextInstance(r.service);
+ } else {
+ String instance = registryCenterService.getInstance(r.registryCenter, r.service);
+ String[] ipAndPort = StringUtils.split(instance, Consts.S.COLON);
+ inst = new ServiceInstance(ipAndPort[0], Integer.parseInt(ipAndPort[1]));
+ }
service2instMap.put(r.service, inst);
}
}
diff --git a/fizz-core/src/main/java/we/filter/RouteFilter.java b/fizz-core/src/main/java/we/filter/RouteFilter.java
index 93d4f0f..45f2f99 100644
--- a/fizz-core/src/main/java/we/filter/RouteFilter.java
+++ b/fizz-core/src/main/java/we/filter/RouteFilter.java
@@ -115,7 +115,11 @@ public class RouteFilter extends FizzWebFilter {
} else if (route.type == ApiConfig.Type.SERVICE_DISCOVERY) {
String pathQuery = getBackendPathQuery(req, route);
- return fizzWebClient.send2service(traceId, route.method, route.backendService, pathQuery, hdrs, req.getBody(), route.timeout, route.retryCount, route.retryInterval)
+ String svc = route.backendService;
+ if (route.registryCenter != null) {
+ svc = route.registryCenter + Consts.S.COMMA + route.backendService;
+ }
+ return fizzWebClient.send2service(traceId, route.method, svc, pathQuery, hdrs, req.getBody(), route.timeout, route.retryCount, route.retryInterval)
.flatMap(genServerResponse(exchange));
} else if (route.type == ApiConfig.Type.REVERSE_PROXY) {
diff --git a/fizz-core/src/main/java/we/plugin/auth/ApiConfig.java b/fizz-core/src/main/java/we/plugin/auth/ApiConfig.java
index e992875..b12fd84 100644
--- a/fizz-core/src/main/java/we/plugin/auth/ApiConfig.java
+++ b/fizz-core/src/main/java/we/plugin/auth/ApiConfig.java
@@ -25,6 +25,7 @@ import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.web.server.ServerWebExchange;
import we.plugin.PluginConfig;
import we.proxy.Route;
+import we.util.Consts;
import we.util.JacksonUtils;
import we.util.UrlTransformUtils;
@@ -71,6 +72,8 @@ public class ApiConfig {
public String service;
+ public String registryCenter;
+
public String backendService;
public Object fizzMethod = ALL_METHOD;
@@ -141,6 +144,17 @@ public class ApiConfig {
firstGatewayGroup = gatewayGroups.iterator().next();
}
+ @JsonProperty("registryName")
+ public void setRegistryCenter(String rc) {
+ if (StringUtils.isNotBlank(rc)) {
+ if (rc.equals(Consts.S.DEFAULT)) {
+ registryCenter = Consts.S.DEFAULT;
+ } else {
+ registryCenter = rc;
+ }
+ }
+ }
+
public void setPath(String p) {
if (StringUtils.isNotBlank(p)) {
if ("/".equals(p)) {
@@ -209,18 +223,19 @@ public class ApiConfig {
public Route getRoute(ServerWebExchange exchange, @Nullable List gatewayGroupPluginConfigs) {
ServerHttpRequest request = exchange.getRequest();
- Route r = new Route().dedicatedLine( this.dedicatedLine)
- .type( this.type)
- .method( request.getMethod())
- .backendService(this.backendService)
- .backendPath( this.backendPath)
- .rpcMethod( this.rpcMethod)
- .rpcParamTypes( this.rpcParamTypes)
- .rpcGroup( this.rpcGroup)
- .rpcVersion( this.rpcVersion)
- .timeout( this.timeout)
- .retryCount( this.retryCount)
- .retryInterval( this.retryInterval);
+ Route r = new Route().dedicatedLine( this.dedicatedLine)
+ .type( this.type)
+ .method( request.getMethod())
+ .registryCenter( this.registryCenter)
+ .backendService( this.backendService)
+ .backendPath( this.backendPath)
+ .rpcMethod( this.rpcMethod)
+ .rpcParamTypes( this.rpcParamTypes)
+ .rpcGroup( this.rpcGroup)
+ .rpcVersion( this.rpcVersion)
+ .timeout( this.timeout)
+ .retryCount( this.retryCount)
+ .retryInterval( this.retryInterval);
if (gatewayGroupPluginConfigs == null || gatewayGroupPluginConfigs.isEmpty()) {
r.pluginConfigs = this.pluginConfigs;
diff --git a/fizz-core/src/main/java/we/plugin/auth/Receiver.java b/fizz-core/src/main/java/we/plugin/auth/Receiver.java
index f3347c0..43e165a 100644
--- a/fizz-core/src/main/java/we/plugin/auth/Receiver.java
+++ b/fizz-core/src/main/java/we/plugin/auth/Receiver.java
@@ -17,6 +17,9 @@
package we.plugin.auth;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import org.apache.commons.lang3.StringUtils;
+import we.util.Consts;
import we.util.JacksonUtils;
/**
@@ -27,10 +30,23 @@ public class Receiver {
public String service;
- public int type;
+ public String registryCenter;
+
+ public int type;
public String path;
+ @JsonProperty("registryName")
+ public void setRegistryCenter(String rc) {
+ if (StringUtils.isNotBlank(rc)) {
+ if (rc.equals(Consts.S.DEFAULT)) {
+ registryCenter = Consts.S.DEFAULT;
+ } else {
+ registryCenter = rc;
+ }
+ }
+ }
+
@Override
public String toString() {
return JacksonUtils.writeValueAsString(this);
diff --git a/fizz-core/src/main/java/we/proxy/CallbackService.java b/fizz-core/src/main/java/we/proxy/CallbackService.java
index 3b0f6f7..ec0468a 100644
--- a/fizz-core/src/main/java/we/proxy/CallbackService.java
+++ b/fizz-core/src/main/java/we/proxy/CallbackService.java
@@ -242,7 +242,13 @@ public class CallbackService {
for (ServiceTypePath stp : req.assignServices) {
if (stp.type == ApiConfig.Type.SERVICE_DISCOVERY) {
- send = fizzWebClient.send2service(req.id, req.method, stp.service, stp.path, req.headers, req.body)
+ String svc = null;
+ if (stp.registryCenter == null) {
+ svc = stp.service;
+ } else {
+ svc = stp.registryCenter + Consts.S.COMMA + stp.service;
+ }
+ send = fizzWebClient.send2service(req.id, req.method, svc, stp.path, req.headers, req.body)
.onErrorResume( crError(req, stp.service, stp.path) );
} else {
String traceId = CommonConstants.TRACE_ID_PREFIX + req.id;
diff --git a/fizz-core/src/main/java/we/proxy/FizzWebClient.java b/fizz-core/src/main/java/we/proxy/FizzWebClient.java
index f310ec1..4fb6807 100644
--- a/fizz-core/src/main/java/we/proxy/FizzWebClient.java
+++ b/fizz-core/src/main/java/we/proxy/FizzWebClient.java
@@ -17,12 +17,6 @@
package we.proxy;
-import java.time.Duration;
-import java.util.Collections;
-import java.util.List;
-
-import javax.annotation.Resource;
-
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -35,7 +29,6 @@ import org.springframework.web.reactive.function.BodyInserter;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.client.ClientResponse;
import org.springframework.web.reactive.function.client.WebClient;
-
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.util.retry.Retry;
@@ -44,10 +37,16 @@ import we.config.SystemConfig;
import we.exception.ExternalService4xxException;
import we.fizz.exception.FizzRuntimeException;
import we.flume.clients.log4j2appender.LogService;
+import we.service_registry.RegistryCenterService;
import we.util.Consts;
import we.util.ThreadContext;
import we.util.WebUtils;
+import javax.annotation.Resource;
+import java.time.Duration;
+import java.util.Collections;
+import java.util.List;
+
/**
* @author hongqiaowei
*/
@@ -67,6 +66,9 @@ public class FizzWebClient {
@Resource
private DiscoveryClientUriSelector discoveryClientUriSelector;
+ @Resource
+ private RegistryCenterService registryCenterService;
+
@Resource(name = ProxyWebClientConfig.proxyWebClient)
private WebClient webClient;
@@ -83,13 +85,22 @@ public class FizzWebClient {
String s = extractServiceOrAddress(uriOrSvc);
Mono cr = Mono.just(Consts.S.EMPTY).flatMap(dummy -> {
- if (isService(s)) {
- String path = uriOrSvc.substring(uriOrSvc.indexOf(Consts.S.FORWARD_SLASH, 10));
- String uri = discoveryClientUriSelector.getNextUri(s, path);
- return send2uri(traceId, method, uri, headers, body, timeout);
- } else {
- return send2uri(traceId, method, uriOrSvc, headers, body, timeout);
- }
+ if (isService(s)) {
+ String path = uriOrSvc.substring(uriOrSvc.indexOf(Consts.S.FORWARD_SLASH, 10));
+ String uri = null;
+ int commaPos = s.indexOf(Consts.S.COMMA);
+ if (commaPos > -1) {
+ String rc = s.substring(0, commaPos);
+ String svc = s.substring(commaPos + 1);
+ String instance = registryCenterService.getInstance(rc, svc);
+ uri = ThreadContext.getStringBuilder().append(Consts.S.HTTP_PROTOCOL_PREFIX).append(instance).append(path).toString();
+ } else {
+ uri = discoveryClientUriSelector.getNextUri(s, path);
+ }
+ return send2uri(traceId, method, uri, headers, body, timeout);
+ } else {
+ return send2uri(traceId, method, uriOrSvc, headers, body, timeout);
+ }
});
if (numRetries > 0) {
@@ -123,7 +134,16 @@ public class FizzWebClient {
long timeout, long numRetries, long retryInterval) {
Mono cr = Mono.just(Consts.S.EMPTY).flatMap(dummy -> {
- String uri = discoveryClientUriSelector.getNextUri(service, relativeUri);
+ String uri = null;
+ int commaPos = service.indexOf(Consts.S.COMMA);
+ if (commaPos > -1) {
+ String rc = service.substring(0, commaPos);
+ String s = service.substring(commaPos + 1);
+ String instance = registryCenterService.getInstance(rc, s);
+ uri = ThreadContext.getStringBuilder().append(Consts.S.HTTP_PROTOCOL_PREFIX).append(instance).append(relativeUri).toString();
+ } else {
+ uri = discoveryClientUriSelector.getNextUri(service, relativeUri);
+ }
return send2uri(traceId, method, uri, headers, body, timeout);
});
if (numRetries > 0) {
diff --git a/fizz-core/src/main/java/we/proxy/Route.java b/fizz-core/src/main/java/we/proxy/Route.java
index 5dbb7fb..269e339 100644
--- a/fizz-core/src/main/java/we/proxy/Route.java
+++ b/fizz-core/src/main/java/we/proxy/Route.java
@@ -36,6 +36,8 @@ public class Route {
public HttpMethod method;
+ public String registryCenter;
+
public String backendService;
public String backendPath;
@@ -81,6 +83,11 @@ public class Route {
return this;
}
+ public Route registryCenter(String rc) {
+ registryCenter = rc;
+ return this;
+ }
+
public Route backendService(String bs) {
backendService = bs;
return this;
diff --git a/fizz-core/src/main/java/we/proxy/ServiceInstance.java b/fizz-core/src/main/java/we/proxy/ServiceInstance.java
index b30b460..278dd13 100644
--- a/fizz-core/src/main/java/we/proxy/ServiceInstance.java
+++ b/fizz-core/src/main/java/we/proxy/ServiceInstance.java
@@ -27,13 +27,13 @@ public class ServiceInstance {
public String ip;
- public int port;
+ public int port;
public ServiceInstance() {
}
public ServiceInstance(String ip, int port) {
- this.ip = ip;
+ this.ip = ip;
this.port = port;
}
diff --git a/fizz-core/src/main/java/we/proxy/ServiceTypePath.java b/fizz-core/src/main/java/we/proxy/ServiceTypePath.java
index 44b79c8..9f4af80 100644
--- a/fizz-core/src/main/java/we/proxy/ServiceTypePath.java
+++ b/fizz-core/src/main/java/we/proxy/ServiceTypePath.java
@@ -17,6 +17,9 @@
package we.proxy;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import org.apache.commons.lang3.StringUtils;
+import we.util.Consts;
import we.util.JacksonUtils;
/**
@@ -25,11 +28,24 @@ import we.util.JacksonUtils;
public class ServiceTypePath {
+ public String registryCenter;
+
public String service;
public String path;
- public int type;
+ public int type;
+
+ @JsonProperty("registryName")
+ public void setRegistryCenter(String rc) {
+ if (StringUtils.isNotBlank(rc)) {
+ if (rc.equals(Consts.S.DEFAULT)) {
+ registryCenter = Consts.S.DEFAULT;
+ } else {
+ registryCenter = rc;
+ }
+ }
+ }
@Override
public String toString() {
diff --git a/fizz-core/src/main/java/we/service_registry/FizzServiceRegistration.java b/fizz-core/src/main/java/we/service_registry/FizzServiceRegistration.java
new file mode 100644
index 0000000..113cc9a
--- /dev/null
+++ b/fizz-core/src/main/java/we/service_registry/FizzServiceRegistration.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2020 the original author or authors.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package we.service_registry;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.cloud.client.serviceregistry.Registration;
+import org.springframework.cloud.client.serviceregistry.ServiceRegistry;
+
+/**
+ * @author hongqiaowei
+ */
+
+public abstract class FizzServiceRegistration {
+
+ protected static final Logger log = LoggerFactory.getLogger(FizzServiceRegistration.class);
+
+ protected String id;
+
+ private Registration registration;
+
+ private ServiceRegistry serviceRegistry;
+
+ public FizzServiceRegistration(String id, Registration registration, ServiceRegistry serviceRegistry) {
+ this.id = id;
+ this.registration = registration;
+ this.serviceRegistry = serviceRegistry;
+ }
+
+ public void register() {
+ serviceRegistry.register(registration);
+ }
+
+ public void deregister() {
+ serviceRegistry.deregister(registration);
+ }
+
+ public abstract RegistryCenter.Status getRegistryCenterStatus();
+
+ public abstract String getInstance(String service);
+}
diff --git a/fizz-core/src/main/java/we/service_registry/RegistryCenter.java b/fizz-core/src/main/java/we/service_registry/RegistryCenter.java
new file mode 100644
index 0000000..1bc2878
--- /dev/null
+++ b/fizz-core/src/main/java/we/service_registry/RegistryCenter.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2020 the original author or authors.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package we.service_registry;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import org.springframework.core.io.ByteArrayResource;
+import org.springframework.core.io.Resource;
+import org.springframework.core.io.support.PropertiesLoaderUtils;
+import we.Fizz;
+import we.service_registry.eureka.FizzEurekaHelper;
+import we.service_registry.nacos.FizzNacosHelper;
+import we.util.JacksonUtils;
+import we.util.YmlUtils;
+
+import java.io.IOException;
+import java.util.Properties;
+
+/**
+ * @author hongqiaowei
+ */
+
+public class RegistryCenter {
+
+ public enum Status {
+ UP,
+ DOWN,
+ STARTING,
+ OUT_OF_SERVICE,
+ UNKNOWN;
+ }
+
+ public static final int EUREKA = 1;
+ public static final int NACOS = 2;
+
+ public static final int YML = 1;
+ public static final int PROPERTIES = 2;
+
+ @JsonProperty(
+ access = JsonProperty.Access.WRITE_ONLY
+ )
+ public boolean isDeleted = false;
+ public long id;
+ public String name;
+ public int type;
+ public int clientConfigFormat;
+ public String clientConfig;
+
+ private FizzServiceRegistration fizzServiceRegistration;
+
+ @JsonCreator
+ public RegistryCenter(
+ @JsonProperty("isDeleted") int isDeleted,
+ @JsonProperty("id") long id,
+ @JsonProperty("name") String name,
+ @JsonProperty("type") int type,
+ @JsonProperty("format") int clientConfigFormat,
+ @JsonProperty("content") String clientConfig
+ ) {
+
+ if (isDeleted == 1) {
+ this.isDeleted = true;
+ }
+ this.id = id;
+ this.name = name;
+ this.type = type;
+ this.clientConfigFormat = clientConfigFormat;
+ this.clientConfig = clientConfig;
+ }
+
+ @JsonIgnore
+ public FizzServiceRegistration getFizzServiceRegistration() {
+ if (fizzServiceRegistration == null) {
+ Properties properties;
+ if (this.clientConfigFormat == YML) {
+ properties = YmlUtils.string2properties(clientConfig);
+ } else {
+ Resource resource = new ByteArrayResource(clientConfig.getBytes());
+ try {
+ properties = PropertiesLoaderUtils.loadProperties(resource);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ if (type == EUREKA) {
+ fizzServiceRegistration = FizzEurekaHelper.getServiceRegistration(Fizz.context, properties);
+ } else {
+ fizzServiceRegistration = FizzNacosHelper.getServiceRegistration(Fizz.context, properties);
+ }
+ }
+ return fizzServiceRegistration;
+ }
+
+ @JsonIgnore
+ public String getInstance(String service) {
+ return fizzServiceRegistration.getInstance(service);
+ }
+
+ @Override
+ public String toString() {
+ return JacksonUtils.writeValueAsString(this);
+ }
+}
diff --git a/fizz-core/src/main/java/we/service_registry/RegistryCenterService.java b/fizz-core/src/main/java/we/service_registry/RegistryCenterService.java
new file mode 100644
index 0000000..b7d1a4d
--- /dev/null
+++ b/fizz-core/src/main/java/we/service_registry/RegistryCenterService.java
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2020 the original author or authors.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package we.service_registry;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.data.redis.core.ReactiveStringRedisTemplate;
+import org.springframework.stereotype.Service;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+import we.config.AggregateRedisConfig;
+import we.util.JacksonUtils;
+import we.util.Result;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.Resource;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author hongqiaowei
+ */
+
+@Service
+public class RegistryCenterService {
+
+ private static final Logger log = LoggerFactory.getLogger(RegistryCenterService.class);
+
+ private Map registryCenterMap = new HashMap<>();
+
+ @Resource(name = AggregateRedisConfig.AGGREGATE_REACTIVE_REDIS_TEMPLATE)
+ private ReactiveStringRedisTemplate rt;
+
+ @PostConstruct
+ public void init() {
+ Result> result = initRegistryCenter();
+ if (result.code == Result.FAIL) {
+ throw new RuntimeException(result.msg, result.t);
+ }
+ result = lsnRegistryCenterChange();
+ if (result.code == Result.FAIL) {
+ throw new RuntimeException(result.msg, result.t);
+ }
+ }
+
+ private Result> initRegistryCenter() {
+ Result> result = Result.succ();
+ Flux> registryCenterEntries = rt.opsForHash().entries("fizz_registry");
+ registryCenterEntries.collectList()
+ .defaultIfEmpty(Collections.emptyList())
+ .flatMap(
+ es -> {
+ if (!es.isEmpty()) {
+ String json = null;
+ try {
+ for (Map.Entry