diff --git a/README.md b/README.md
index f9041d1..8969457 100644
--- a/README.md
+++ b/README.md
@@ -66,6 +66,7 @@ A Managerment API Gateway in Java . Fizz Gateway 是一个基于 Java开发的
| v1.0.0 | v1.0.0 | v1.0.0 |
| v1.1.0 | v1.1.0 | v1.1.0 |
| v1.1.1 | v1.1.1 | v1.1.1 |
+| v1.2.0 | v1.2.0 | v1.1.1 |
请根据社区版的版本下载对应的管理后台版本
@@ -93,13 +94,13 @@ A Managerment API Gateway in Java . Fizz Gateway 是一个基于 Java开发的
##### 管理后台服务端(fizz-manager-professional)
-1. 首次安装执行`fizz-manager-professional-1.1.1-mysql.sql`数据库脚本
-2. 将`application-prod.yml`、`boot.sh`、`fizz-manager-professional-1.1.1.jar`拷贝到`/data/webapps/fizz-manager-professional`目录下
+1. 首次安装执行`fizz-manager-professional-1.2.0-mysql.sql`数据库脚本
+2. 将`application-prod.yml`、`boot.sh`、`fizz-manager-professional-1.2.0.jar`拷贝到`/data/webapps/fizz-manager-professional`目录下
3. 修改`application-prod.yml`文件,将相关配置修改成部署环境的配置
4. 修改`boot.sh`文件,将`RUN_CMD`变量值修改成部署环境的JAVA实际路径
5. 执行 `chmod +x boot.sh` 命令给`boot.sh`增加执行权限
6. 执行 `./boot.sh start` 命令启动服务,支持 start/stop/restart/status命令
-7. 服务启动后访问 http://IP:8000/fizz-manager (将IP替换成服务部署机器IP地址),使用超级管理员账户`admin`密码`Aa123!`登录
+7. 服务启动后访问前端登录地址,使用超级管理员账户`admin`密码`Aa123!`登录
##### 管理后台前端(fizz-admin-professional)
@@ -126,11 +127,14 @@ server {
#### 二、安装fizz-gateway-community社区版
-说明:如果使用apollo配置中心,可把application.yml文件内容迁到配置中心(apollo上应用名为:fizz-gateway);使用不使用apollo可去掉下面启动命令里的apollo参数。
+说明:
+
+1. 支持配置中心:apollo、nacos,支持注册中心:eureka、nacos,详细配置方法查看application.yml文件。
+2. 如果使用apollo配置中心,可把application.yml文件内容迁到配置中心(apollo上应用名为:fizz-gateway);如果不使用apollo可去掉下面启动命令里的apollo参数。
安装方式一:脚本启动:
-1. 下载fizz-gateway-community的最新代码,修改application.yml配置文件里eureka、redis的配置,使用maven命令`mvn clean package -DskipTests=true`构建并把构建好的fizz-gateway-community-1.1.1.jar和boot.sh放同一目录
+1. 下载fizz-gateway-community的最新代码,修改application.yml配置文件里配置中心、注册中心、redis的配置,使用maven命令`mvn clean package -DskipTests=true`构建并把构建好的fizz-gateway-community-1.2.0.jar和boot.sh放同一目录
2. 修改boot.sh脚本的apollo连接,JVM内存配置
3. 执行 `./boot.sh start` 命令启动服务,支持 start/stop/restart/status命令
@@ -138,13 +142,13 @@ server {
1. 本地clone仓库上的最新代码
2. 将项目fizz-gateway导入IDE
-3. 导入完成后设置项目启动配置及修改application.yml配置文件里eureka、redis的配置,在VM选项中加入`-Denv=dev -Dapollo.meta=http://localhost:66`(Apollo配置中心地址)
+3. 导入完成后设置项目启动配置及修改application.yml配置文件里配置中心、注册中心、redis的配置,在VM选项中加入`-Denv=dev -Dapollo.meta=http://localhost:66`(Apollo配置中心地址)
安装方式三:jar启动:
-1. 本地clone仓库上的最新代码,修改application.yml配置文件里eureka、redis的配置
+1. 本地clone仓库上的最新代码,修改application.yml配置文件里配置中心、注册中心、redis的配置
2. 在项目根目录fizz-gateway-community下执行Maven命令`mvn clean package -DskipTests=true`打包
-3. 进入target目录,使用命令`java -jar -Denv=DEV -Dapollo.meta=http://localhost:66 fizz-gateway-community-1.1.1.jar`启动服务
+3. 进入target目录,使用命令`java -jar -Denv=DEV -Dapollo.meta=http://localhost:66 fizz-gateway-community-1.2.0.jar`启动服务
最后访问网关,地址形式为:http://127.0.0.1:8600/proxy/[服务名]/[API Path]
diff --git a/docs/CNAME b/docs/CNAME
new file mode 100644
index 0000000..692ef2e
--- /dev/null
+++ b/docs/CNAME
@@ -0,0 +1 @@
+fizzgate.com
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 41a21d4..691a288 100644
--- a/pom.xml
+++ b/pom.xml
@@ -10,7 +10,7 @@
we
fizz-gateway-community
- 1.1.1
+ 1.2.0
fizz-gateway-community
@@ -37,6 +37,7 @@
2.13.3
4.1.53.Final
4.5.13
+ 0.2.7
@@ -148,6 +149,17 @@
2.2.5.RELEASE
+
+ com.alibaba.boot
+ nacos-config-spring-boot-starter
+ ${nacos.version}
+
+
+ com.alibaba.boot
+ nacos-discovery-spring-boot-starter
+ ${nacos.version}
+
+
org.apache.commons
commons-pool2
diff --git a/sh/boot.sh b/sh/boot.sh
index 9f0a930..5e6eb48 100644
--- a/sh/boot.sh
+++ b/sh/boot.sh
@@ -6,7 +6,7 @@ cd `dirname $0`
#变量定义
APOLLO_META_SERVER=http://localhost:66
ENV=dev
-APP_NAME=fizz-gateway-community-1.1.1.jar
+APP_NAME=fizz-gateway-community-1.2.0.jar
APP_DEP_DIR=/data/webapps/fizz-gateway
APP_LOG_DIR=/data/logs/fizz-gateway
JAVA_CMD=/usr/local/java/bin/java
diff --git a/src/main/java/we/FizzGatewayApplication.java b/src/main/java/we/FizzGatewayApplication.java
index 319b5ed..25d46ae 100644
--- a/src/main/java/we/FizzGatewayApplication.java
+++ b/src/main/java/we/FizzGatewayApplication.java
@@ -1,6 +1,6 @@
package we;
-import com.ctrip.framework.apollo.spring.annotation.EnableApolloConfig;
+import com.alibaba.nacos.spring.context.annotation.config.NacosPropertySource;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
@@ -12,7 +12,7 @@ import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
exclude = {ErrorWebFluxAutoConfiguration.class, RedisAutoConfiguration.class, RedisReactiveAutoConfiguration.class},
scanBasePackages = {"we"}
)
-@EnableApolloConfig
+@NacosPropertySource(dataId = "application", groupId = "fizz-gateway", autoRefreshed = true)
@EnableDiscoveryClient
public class FizzGatewayApplication {
diff --git a/src/main/java/we/config/ApolloConfig.java b/src/main/java/we/config/ApolloConfig.java
new file mode 100644
index 0000000..f41e8a6
--- /dev/null
+++ b/src/main/java/we/config/ApolloConfig.java
@@ -0,0 +1,15 @@
+package we.config;
+
+import com.ctrip.framework.apollo.spring.annotation.EnableApolloConfig;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * Apollo config
+ * @author zhongjie
+ */
+@ConditionalOnProperty(name = "apollo.enabled")
+@EnableApolloConfig
+@Configuration
+public class ApolloConfig {
+}
diff --git a/src/main/java/we/config/AppConfigProperties.java b/src/main/java/we/config/AppConfigProperties.java
index 5e19b1d..268131c 100644
--- a/src/main/java/we/config/AppConfigProperties.java
+++ b/src/main/java/we/config/AppConfigProperties.java
@@ -17,6 +17,7 @@
package we.config;
+import com.alibaba.nacos.api.config.annotation.NacosValue;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
@@ -27,6 +28,7 @@ import org.springframework.context.annotation.Configuration;
@Configuration
public class AppConfigProperties {
+ @NacosValue(value = "${spring.profiles.active}", autoRefreshed = true)
@Value("${spring.profiles.active}")
private String env;
diff --git a/src/main/java/we/config/SystemConfig.java b/src/main/java/we/config/SystemConfig.java
index 0d8bab6..4911ff4 100644
--- a/src/main/java/we/config/SystemConfig.java
+++ b/src/main/java/we/config/SystemConfig.java
@@ -17,10 +17,12 @@
package we.config;
+import com.alibaba.nacos.api.config.annotation.NacosValue;
import com.ctrip.framework.apollo.model.ConfigChange;
import com.ctrip.framework.apollo.model.ConfigChangeEvent;
import com.ctrip.framework.apollo.spring.annotation.ApolloConfigChangeListener;
+import org.springframework.util.ObjectUtils;
import we.plugin.auth.GatewayGroup;
import we.util.Constants;
import we.util.JacksonUtils;
@@ -61,6 +63,7 @@ public class SystemConfig {
//
// private Set currentServerGatewayGroupSet;
+ @NacosValue(value = "${spring.profiles.active}")
@Value("${spring.profiles.active}")
private String profile;
@@ -140,11 +143,9 @@ public class SystemConfig {
String nv = c.getNewValue();
log.info(p + " old: " + ov + ", new: " + nv);
if (p.equals("log.response-body")) {
- logResponseBody = Boolean.valueOf(nv);
- afterLogResponseBodySet();
+ this.updateLogResponseBody(Boolean.parseBoolean(nv));
} else if (p.equals("log.headers")) {
- logHeaders = nv;
- afterLogHeadersSet();
+ this.updateLogHeaders(nv);
} /*else if (p.equals("gateway-group")) {
gatewayGroup = nv;
afterGatewayGroupSet();
@@ -152,4 +153,32 @@ public class SystemConfig {
}
);
}
+
+ private void updateLogResponseBody(boolean newValue) {
+ logResponseBody = newValue;
+ this.afterLogResponseBodySet();
+ }
+
+ private void updateLogHeaders(String newValue) {
+ logHeaders = newValue;
+ afterLogHeadersSet();
+ }
+
+ @NacosValue(value = "${log.response-body:false}", autoRefreshed = true)
+ public void setLogResponseBody(boolean logResponseBody) {
+ if (this.logResponseBody == logResponseBody) {
+ return;
+ }
+ log.info("log.response-body old: " + this.logResponseBody + ", new: " + logResponseBody);
+ this.updateLogResponseBody(logResponseBody);
+ }
+
+ @NacosValue(value = "${log.headers:x}", autoRefreshed = true)
+ public void setLogHeaders(String logHeaders) {
+ if (ObjectUtils.nullSafeEquals(this.logHeaders, logHeaders)) {
+ return;
+ }
+ log.info("log.headers old: " + this.logHeaders + ", new: " + logHeaders);
+ this.updateLogHeaders(logHeaders);
+ }
}
diff --git a/src/main/java/we/controller/ManagerConfigController.java b/src/main/java/we/controller/ManagerConfigController.java
index 92fa2f3..eb2929b 100644
--- a/src/main/java/we/controller/ManagerConfigController.java
+++ b/src/main/java/we/controller/ManagerConfigController.java
@@ -17,6 +17,7 @@
package we.controller;
+import com.alibaba.nacos.api.config.annotation.NacosValue;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
@@ -44,6 +45,7 @@ import java.util.stream.Collectors;
@RestController
@RequestMapping(value = "/managerConfig")
public class ManagerConfigController {
+ @NacosValue(value = "${fizz.manager.config.key:fizz-manager-key}", autoRefreshed = true)
@Value("${fizz.manager.config.key:fizz-manager-key}")
private String key;
diff --git a/src/main/java/we/filter/PreFilter.java b/src/main/java/we/filter/PreFilter.java
index 1e2241e..7d7dcc1 100644
--- a/src/main/java/we/filter/PreFilter.java
+++ b/src/main/java/we/filter/PreFilter.java
@@ -17,6 +17,7 @@
package we.filter;
+import com.alibaba.nacos.api.config.annotation.NacosValue;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -56,9 +57,11 @@ public class PreFilter extends ProxyAggrFilter {
private static final FilterResult succFr = FilterResult.SUCCESS(PRE_FILTER);
+ @NacosValue(value = "${spring.profiles.active}")
@Value("${spring.profiles.active}")
private String profile;
+ @NacosValue(value = "${b-services:x}")
@Value("${b-services:x}")
private Set bServices = new HashSet<>();
diff --git a/src/main/java/we/fizz/ConfigLoader.java b/src/main/java/we/fizz/ConfigLoader.java
index e8a661c..81254a9 100644
--- a/src/main/java/we/fizz/ConfigLoader.java
+++ b/src/main/java/we/fizz/ConfigLoader.java
@@ -20,6 +20,7 @@ package we.fizz;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
+import com.alibaba.nacos.api.config.annotation.NacosValue;
import we.config.AppConfigProperties;
import we.fizz.input.ClientInputConfig;
import we.fizz.input.Input;
@@ -69,6 +70,7 @@ public class ConfigLoader {
@Resource(name = AGGREGATE_REACTIVE_REDIS_TEMPLATE)
private ReactiveStringRedisTemplate reactiveStringRedisTemplate;
+ @NacosValue(value = "${fizz.aggregate.read-local-config-flag:false}", autoRefreshed = true)
@Value("${fizz.aggregate.read-local-config-flag:false}")
private Boolean readLocalConfigFlag;
diff --git a/src/main/java/we/fizz/input/ScriptHelper.java b/src/main/java/we/fizz/input/ScriptHelper.java
index a6644d9..eee3aa8 100644
--- a/src/main/java/we/fizz/input/ScriptHelper.java
+++ b/src/main/java/we/fizz/input/ScriptHelper.java
@@ -29,7 +29,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alibaba.fastjson.JSON;
-import com.ctrip.framework.apollo.core.utils.StringUtils;
+import org.springframework.util.StringUtils;
import we.constants.CommonConstants;
import we.exception.StopAndResponseException;
@@ -57,7 +57,7 @@ public class ScriptHelper {
Script script = new Script();
script.setType((String) scriptCfg.get("type"));
script.setSource((String) scriptCfg.get("source"));
- if (StringUtils.isBlank(script.getType()) || StringUtils.isBlank(script.getSource())) {
+ if (!StringUtils.hasText(script.getType()) || !StringUtils.hasText(script.getSource())) {
return null;
}
diff --git a/src/main/java/we/plugin/auth/ApiConfigService.java b/src/main/java/we/plugin/auth/ApiConfigService.java
index 84751f4..31e6b8d 100644
--- a/src/main/java/we/plugin/auth/ApiConfigService.java
+++ b/src/main/java/we/plugin/auth/ApiConfigService.java
@@ -17,6 +17,7 @@
package we.plugin.auth;
+import com.alibaba.nacos.api.config.annotation.NacosValue;
import com.ctrip.framework.apollo.model.ConfigChange;
import com.ctrip.framework.apollo.model.ConfigChangeEvent;
import com.ctrip.framework.apollo.spring.annotation.ApolloConfigChangeListener;
@@ -30,6 +31,7 @@ import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Service;
+import org.springframework.util.ObjectUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@@ -75,13 +77,26 @@ public class ApiConfigService {
k -> {
ConfigChange cc = cce.getChange(k);
if (cc.getPropertyName().equalsIgnoreCase("serviceWhiteList")) {
- log.info("old service white list: " + cc.getOldValue());
- serviceWhiteList = cc.getNewValue();
- afterServiceWhiteListSet();
+ this.updateServiceWhiteList(cc.getOldValue(), cc.getNewValue());
}
}
);
}
+
+ private void updateServiceWhiteList(String oldValue, String newValue) {
+ if (ObjectUtils.nullSafeEquals(oldValue, newValue)) {
+ return;
+ }
+ log.info("old service white list: " + oldValue);
+ serviceWhiteList = newValue;
+ afterServiceWhiteListSet();
+ }
+
+ @NacosValue(value = "${serviceWhiteList:x}", autoRefreshed = true)
+ public void setServiceWhiteList(String serviceWhiteList) {
+ this.updateServiceWhiteList(this.serviceWhiteList, serviceWhiteList);
+ }
+
public void afterServiceWhiteListSet() {
if (StringUtils.isNotBlank(serviceWhiteList)) {
whiteListSet.clear();
@@ -94,6 +109,7 @@ public class ApiConfigService {
}
}
+ @NacosValue(value = "${auth.compatible-wh:false}", autoRefreshed = true)
@Value("${auth.compatible-wh:false}")
private boolean compatibleWh;
@@ -109,6 +125,7 @@ public class ApiConfigService {
@Autowired(required = false)
private CustomAuth customAuth;
+ @NacosValue(value = "${openServiceWhiteList:false}", autoRefreshed = true)
@Value("${openServiceWhiteList:false}")
private boolean openServiceWhiteList = false;
diff --git a/src/main/java/we/plugin/stat/StatPluginFilter.java b/src/main/java/we/plugin/stat/StatPluginFilter.java
index a314537..8eb25d6 100644
--- a/src/main/java/we/plugin/stat/StatPluginFilter.java
+++ b/src/main/java/we/plugin/stat/StatPluginFilter.java
@@ -17,6 +17,7 @@
package we.plugin.stat;
+import com.alibaba.nacos.api.config.annotation.NacosValue;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -63,12 +64,15 @@ public class StatPluginFilter extends PluginFilter {
private static final String reqTime = "\"reqTime\":";
+ @NacosValue(value = "${stat.open:false}", autoRefreshed = true)
@Value("${stat.open:false}")
private boolean statOpen = false;
+ @NacosValue(value = "${stat.channel:fizz_access_stat}", autoRefreshed = true)
@Value("${stat.channel:fizz_access_stat}")
private String fizzAccessStatChannel;
+ @NacosValue(value = "${stat.topic:}", autoRefreshed = true)
@Value("${stat.topic:}")
private String fizzAccessStatTopic;
diff --git a/src/main/java/we/proxy/AbstractDiscoveryClientUriSelector.java b/src/main/java/we/proxy/AbstractDiscoveryClientUriSelector.java
new file mode 100644
index 0000000..94ab1de
--- /dev/null
+++ b/src/main/java/we/proxy/AbstractDiscoveryClientUriSelector.java
@@ -0,0 +1,17 @@
+package we.proxy;
+
+import we.util.Constants;
+import we.util.ThreadContext;
+
+/**
+ * Abstract implementation of {@code DiscoveryClientUriSelector}
+ *
+ * @author zhongjie
+ */
+abstract public class AbstractDiscoveryClientUriSelector implements DiscoveryClientUriSelector {
+
+ protected String buildUri(String ipAddr, int port, String path) {
+ StringBuilder b = ThreadContext.getStringBuilder();
+ return b.append(Constants.Symbol.HTTP_PROTOCOL_PREFIX).append(ipAddr).append(Constants.Symbol.COLON).append(port).append(path).toString();
+ }
+}
diff --git a/src/main/java/we/proxy/DisableDiscoveryUriSelector.java b/src/main/java/we/proxy/DisableDiscoveryUriSelector.java
new file mode 100644
index 0000000..093225f
--- /dev/null
+++ b/src/main/java/we/proxy/DisableDiscoveryUriSelector.java
@@ -0,0 +1,19 @@
+package we.proxy;
+
+import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
+import org.springframework.stereotype.Service;
+
+/**
+ * The disable implementation of {@code DiscoveryClientUriSelector}, used when Nacos and Eureka discovery are not enabled.
+ *
+ * @author zhongjie
+ */
+
+@ConditionalOnExpression("${nacos.discovery.enabled} == false and ${eureka.client.enabled} == false")
+@Service
+public class DisableDiscoveryUriSelector implements DiscoveryClientUriSelector {
+ @Override
+ public String getNextUri(String service, String relativeUri) {
+ throw new RuntimeException("No " + service + " because discovery disabled", null, false, false) {};
+ }
+}
diff --git a/src/main/java/we/proxy/DiscoveryClientUriSelector.java b/src/main/java/we/proxy/DiscoveryClientUriSelector.java
new file mode 100644
index 0000000..8d5f326
--- /dev/null
+++ b/src/main/java/we/proxy/DiscoveryClientUriSelector.java
@@ -0,0 +1,16 @@
+package we.proxy;
+
+/**
+ * A {@code DiscoveryClientUriSelector} is used to select the uri for the next request
+ *
+ * @author zhongjie
+ */
+public interface DiscoveryClientUriSelector {
+ /**
+ * find a instance of service by discovery and return the uri that http://{instance-ip-addr}:{instance-port}{relativeUri}
+ * @param service service name
+ * @param relativeUri relative uri
+ * @return the uri for the next request
+ */
+ String getNextUri(String service, String relativeUri);
+}
diff --git a/src/main/java/we/proxy/EurekaUriSelector.java b/src/main/java/we/proxy/EurekaUriSelector.java
new file mode 100644
index 0000000..a355549
--- /dev/null
+++ b/src/main/java/we/proxy/EurekaUriSelector.java
@@ -0,0 +1,55 @@
+package we.proxy;
+
+import com.netflix.appinfo.InstanceInfo;
+import com.netflix.discovery.EurekaClient;
+import com.netflix.discovery.shared.Applications;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.util.List;
+
+/**
+ * The Eureka implementation of {@code DiscoveryClientUriSelector}
+ *
+ * @author zhongjie
+ */
+@ConditionalOnProperty(value = "eureka.client.enabled", matchIfMissing = true)
+@Service
+public class EurekaUriSelector extends AbstractDiscoveryClientUriSelector {
+
+ @Resource
+ private EurekaClient eurekaClient;
+
+ @Override
+ public String getNextUri(String service, String relativeUri) {
+ InstanceInfo inst = roundRobinChoose1instFrom(service);
+ return buildUri(inst.getIPAddr(), inst.getPort(), relativeUri);
+ }
+
+
+ // private static List aggrMemberInsts = new ArrayList<>();
+ // static {
+ // InstanceInfo i0 = InstanceInfo.Builder.newBuilder().setAppName("TRIP-MINI").setIPAddr("xxx.25.63.192").setPort(7094).build();
+ // aggrMemberInsts.add(i0);
+ // }
+ // private static AtomicLong counter = new AtomicLong(0);
+ // private static final String aggrMember = "trip-mini";
+
+
+ private InstanceInfo roundRobinChoose1instFrom(String service) {
+
+ // if (aggrMember.equals(service)) {
+ // int idx = (int) (counter.incrementAndGet() % aggrMemberInsts.size());
+ // return aggrMemberInsts.get(idx);
+ // }
+
+ List insts = eurekaClient.getInstancesByVipAddress(service, false);
+ if (insts == null || insts.isEmpty()) {
+ throw new RuntimeException("eureka no " + service, null, false, false) {};
+ }
+ Applications apps = eurekaClient.getApplications();
+ int index = (int) (apps.getNextIndex(service.toUpperCase(), false).incrementAndGet() % insts.size());
+ return insts.get(index);
+ }
+}
diff --git a/src/main/java/we/proxy/FizzWebClient.java b/src/main/java/we/proxy/FizzWebClient.java
index d1be262..90a550e 100644
--- a/src/main/java/we/proxy/FizzWebClient.java
+++ b/src/main/java/we/proxy/FizzWebClient.java
@@ -17,10 +17,7 @@
package we.proxy;
-import com.netflix.appinfo.InstanceInfo;
-import com.netflix.discovery.EurekaClient;
-import com.netflix.discovery.shared.Applications;
-
+import com.alibaba.nacos.api.config.annotation.NacosValue;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
@@ -43,10 +40,7 @@ import we.util.WebUtils;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
-import java.util.ArrayList;
-import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
-import java.util.concurrent.atomic.AtomicLong;
/**
* @author hongqiaowei
@@ -62,7 +56,7 @@ public class FizzWebClient {
private static final String localhost = "localhost";
@Resource
- private EurekaClient eurekaClient;
+ private DiscoveryClientUriSelector discoveryClientUriSelector;
@Resource(name = ProxyWebClientConfig.proxyWebClient)
private WebClient proxyWebClient;
@@ -70,6 +64,7 @@ public class FizzWebClient {
@Resource(name = AggrWebClientConfig.aggrWebClient)
private WebClient aggrWebClient;
+ @NacosValue(value = "${fizz-web-client.timeout:-1}")
@Value("${fizz-web-client.timeout:-1}")
private long timeout = -1;
@@ -140,8 +135,7 @@ public class FizzWebClient {
// what about multiple nginx instance
// current
- InstanceInfo inst = roundRobinChoose1instFrom(service);
- String uri = buildUri(inst, relativeUri);
+ String uri = discoveryClientUriSelector.getNextUri(service, relativeUri);
return send2uri(originReqIdOrBizId, method, uri, headers, body, cbc);
}
@@ -225,37 +219,8 @@ public class FizzWebClient {
// TODO 请求完成后,做metric, 以反哺后续的请求转发
}
- private String buildUri(InstanceInfo inst, String path) {
- StringBuilder b = ThreadContext.getStringBuilder();
- return b.append(Constants.Symbol.HTTP_PROTOCOL_PREFIX).append(inst.getIPAddr()).append(Constants.Symbol.COLON).append(inst.getPort()).append(path).toString();
- }
- // private static List aggrMemberInsts = new ArrayList<>();
- // static {
- // InstanceInfo i0 = InstanceInfo.Builder.newBuilder().setAppName("TRIP-MINI").setIPAddr("xxx.25.63.192").setPort(7094).build();
- // aggrMemberInsts.add(i0);
- // }
- // private static AtomicLong counter = new AtomicLong(0);
- // private static final String aggrMember = "trip-mini";
-
-
- private InstanceInfo roundRobinChoose1instFrom(String service) {
-
- // if (aggrMember.equals(service)) {
- // int idx = (int) (counter.incrementAndGet() % aggrMemberInsts.size());
- // return aggrMemberInsts.get(idx);
- // }
-
- List insts = eurekaClient.getInstancesByVipAddress(service, false);
- if (insts == null || insts.isEmpty()) {
- throw new RuntimeException("eureka no " + service, null, false, false) {};
- }
- Applications apps = eurekaClient.getApplications();
- int index = (int) (apps.getNextIndex(service.toUpperCase(), false).incrementAndGet() % insts.size());
- return insts.get(index);
- }
-
private String extractServiceOrAddress(String uriOrSvc) {
return uriOrSvc.substring(7, uriOrSvc.indexOf(Constants.Symbol.FORWARD_SLASH, 10));
}
diff --git a/src/main/java/we/proxy/NacosUriSelector.java b/src/main/java/we/proxy/NacosUriSelector.java
new file mode 100644
index 0000000..fff4144
--- /dev/null
+++ b/src/main/java/we/proxy/NacosUriSelector.java
@@ -0,0 +1,86 @@
+package we.proxy;
+
+import com.alibaba.boot.nacos.discovery.properties.NacosDiscoveryProperties;
+import com.alibaba.boot.nacos.discovery.properties.Register;
+import com.alibaba.nacos.api.annotation.NacosInjected;
+import com.alibaba.nacos.api.exception.NacosException;
+import com.alibaba.nacos.api.naming.NamingService;
+import com.alibaba.nacos.api.naming.pojo.Instance;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.stereotype.Service;
+import org.springframework.util.StringUtils;
+
+import javax.annotation.PostConstruct;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * The Nacos implementation of {@code DiscoveryClientUriSelector}
+ *
+ * @author zhongjie
+ */
+@ConditionalOnProperty(value = "nacos.discovery.enabled")
+@Service
+public class NacosUriSelector extends AbstractDiscoveryClientUriSelector {
+ private static final Logger log = LoggerFactory.getLogger(NacosUriSelector.class);
+
+ public NacosUriSelector(NacosDiscoveryProperties discoveryProperties) {
+ this.discoveryProperties = discoveryProperties;
+ }
+
+ @NacosInjected
+ private NamingService naming;
+ private NacosDiscoveryProperties discoveryProperties;
+ private String groupName;
+ private List clusterNameList;
+ private boolean useGroupName;
+ private boolean userClusterName;
+
+ @PostConstruct
+ public void init() {
+ Register register = discoveryProperties.getRegister();
+ if (register != null) {
+ this.groupName = register.getGroupName();
+ if (StringUtils.hasText(groupName)) {
+ this.useGroupName = true;
+ }
+ String clusterName = register.getClusterName();
+ if (StringUtils.hasText(clusterName)) {
+ this.userClusterName = true;
+ this.clusterNameList = Collections.singletonList(clusterName);
+ }
+
+ }
+ }
+
+ @Override
+ public String getNextUri(String service, String relativeUri) {
+ Instance instance = this.selectOneHealthyInstance(service);
+ return super.buildUri(instance.getIp(), instance.getPort(), relativeUri);
+ }
+
+ private Instance selectOneHealthyInstance(String service) {
+ Instance instance = null;
+ try {
+ if (useGroupName && userClusterName) {
+ instance = naming.selectOneHealthyInstance(service, groupName, clusterNameList);
+ } else if (useGroupName) {
+ instance = naming.selectOneHealthyInstance(service, groupName);
+ } else if (userClusterName) {
+ instance = naming.selectOneHealthyInstance(service, clusterNameList);
+ } else {
+ instance = naming.selectOneHealthyInstance(service);
+ }
+ } catch (NacosException e) {
+ log.warn("Nacos selectOneHealthyInstance({}) exception", service, e);
+ }
+
+ if (instance == null) {
+ throw new RuntimeException("Nacos no " + service, null, false, false) {};
+ }
+
+ return instance;
+ }
+}
diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml
index eaa6ac7..1b0c449 100644
--- a/src/main/resources/application.yml
+++ b/src/main/resources/application.yml
@@ -1,27 +1,82 @@
-#apollo:
-# bootstrap:
-# enabled: true
-# namespaces: application
-# eagerLoad:
-# enabled: true
+# if you do not use Apollo, ignore the follow config
+######################### Apollo config start #####################################
+apollo:
+ # if use Apollo set this flag to true
+ enabled: false
+ bootstrap:
+ # if use Apollo set this flag to true
+ enabled: false
+ namespaces: application
+ eagerLoad:
+ # if use Apollo set this flag to true
+ enabled: false
+######################### Apollo config end #######################################
-spring.profiles.active: dev
+# if you do not use Nacos, ignore the follow config
+######################### Nacos config start ######################################
+nacos:
+ config:
+ # if use Nacos config set this flag to true
+ enabled: false
+ # need replace
+ server-addr: localhost:8848
+ auto-refresh: true
+ group: fizz-gateway
+ data-id: application
+ type: PROPERTIES
+ # need replace
+ namespace: c37ecd3b-e8b3-42cc-ba94-98e931e33683
+ discovery:
+ # if use Nacos discovery set this flag to true
+ enabled: false
+ # need replace
+ server-addr: localhost:8848
+ auto-register: true
+ register:
+ group-name: fizz-gateway
+######################### Nacos config end #######################################
-server.port: 8600
+# if you do not use Eureka, ignore the follow config
+######################### Eureka config start ####################################
+eureka:
+ client:
+ # if use Eureka set this flag to true
+ enabled: false
+ serviceUrl:
+ # need replace
+ defaultZone: http://localhost:6600/eureka/
+ instance:
+ prefer-ip-address: true
+######################### Eureka config end ######################################
-eureka.instance.prefer-ip-address: true
-eureka.client.serviceUrl.defaultZone: http://localhost:6600/eureka/
-spring.application.name: fizz-gateway
-spring.cloud.loadbalancer.ribbon.enabled: false
+server:
+ port: 8600
+spring:
+ profiles:
+ active: dev
+ application:
+ name: fizz-gateway
+ cloud:
+ loadbalancer:
+ ribbon:
+ enabled: false
-aggregate.redis.host: localhost
-aggregate.redis.port: 6379
-aggregate.redis.password: 123456
-aggregate.redis.database: 10
+aggregate:
+ redis:
+ # need replace
+ host: localhost
+ # need replace
+ port: 6379
+ # need replace
+ password: 123456
+ # need replace
+ database: 9
+proxy-webclient:
+ name: proxy
+aggr-webclient:
+ name: aggr
+fizz-web-client:
+ timeout: 20000
+log:
+ headers: COOKIE,FIZZ-APPID,FIZZ-SECRETKEY,FIZZ-SIGN,FIZZ-TS,FIZZ-RSV
-proxy-webclient.name: proxy
-aggr-webclient.name: aggr
-
-fizz-web-client.timeout: 20000
-
-log.headers: COOKIE,FIZZ-APPID,FIZZ-SECRETKEY,FIZZ-SIGN,FIZZ-TS,FIZZ-RSV