diff --git a/sop-admin/sop-admin-front/pages/service/limitManager.html b/sop-admin/sop-admin-front/pages/service/limitManager.html
index 5404e22e..376e7d54 100644
--- a/sop-admin/sop-admin-front/pages/service/limitManager.html
+++ b/sop-admin/sop-admin-front/pages/service/limitManager.html
@@ -57,8 +57,8 @@
diff --git a/sop-admin/sop-admin-front/pages/service/limitManager.js b/sop-admin/sop-admin-front/pages/service/limitManager.js
index 55c036f9..b9c29aa8 100644
--- a/sop-admin/sop-admin-front/pages/service/limitManager.js
+++ b/sop-admin/sop-admin-front/pages/service/limitManager.js
@@ -51,7 +51,7 @@ lib.importJs('../../assets/js/routerole.js')
});
function checkUpdateForm(formData) {
- var type = formData.type;
+ var type = formData.limitType;
if (type == 1) {
if (!/^[1-9]\d*$/.test(formData.execCountPerSecond)) {
layer.alert('每秒可处理请求数必须大于0')
@@ -118,6 +118,8 @@ lib.importJs('../../assets/js/routerole.js')
}
}
+ var tipType = '
'
+
function renderTable(postData) {
var limitTable = table.render({
elem: '#limitTable'
@@ -129,8 +131,8 @@ lib.importJs('../../assets/js/routerole.js')
{field: 'name', title: '接口名', width: 200}
, {field: 'version', title: '版本号', width: 80}
, {
- field: 'type', title: '限流策略', width: 80, templet: function (row) {
- return LIMIT_TYPE[row.type + ''];
+ field: 'limitType', title: '限流策略 ' + tipType, width: 100, templet: function (row) {
+ return LIMIT_TYPE[row.limitType + ''];
}
}
, {
@@ -139,11 +141,11 @@ lib.importJs('../../assets/js/routerole.js')
return '--'
}
var html = [];
- if (row.type == 1) {
+ if (row.limitType == 1) {
html.push('每秒可处理请求数:' + row.execCountPerSecond);
html.push('subCode:' + row.limitCode);
html.push('subMsg:' + row.limitMsg);
- } else if(row.type == 2) {
+ } else if(row.limitType == 2) {
html.push('令牌桶容量:' + row.tokenBucketCount);
}
return html.join(',');
@@ -173,7 +175,7 @@ lib.importJs('../../assets/js/routerole.js')
updateForm.setData(data);
$('.limit-type').hide();
- $('.type' + data.type).show();
+ $('.type' + data.limitType).show();
layer.open({
type: 1
@@ -191,4 +193,20 @@ lib.importJs('../../assets/js/routerole.js')
RouteRole.loadAllRole(form, 'roleArea');
-});
\ No newline at end of file
+});
+
+function showLimitTypeTip() {
+ var leakyRemark = '漏桶策略:每秒处理固定数量的请求,超出请求返回错误信息。';
+ var tokenRemark = '令牌桶策略:每秒放置固定数量的令牌数,不足的令牌数做等待处理,直到拿到令牌为止。';
+ var content = '
'
+ + leakyRemark
+ + '
'
+ + tokenRemark
+ + '
';
+
+ layer.open({
+ title: '限流策略说明'
+ ,area: ['600px', 'auto']
+ ,content: content
+ });
+}
\ No newline at end of file
diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/LimitApi.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/LimitApi.java
index e01112fe..75090c59 100644
--- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/LimitApi.java
+++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/LimitApi.java
@@ -88,7 +88,7 @@ public class LimitApi {
private ConfigRouteLimit getDefaultLimit() {
ConfigRouteLimit configRouteLimit = new ConfigRouteLimit();
- configRouteLimit.setType(LimitEnum.TYPE_LEAKY_BUCKET.getVal());
+ configRouteLimit.setLimitType(LimitEnum.TYPE_LEAKY_BUCKET.getVal());
configRouteLimit.setLimitStatus(LimitEnum.STATUS_CLOSE.getVal());
return configRouteLimit;
}
diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/param/LimitParam.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/param/LimitParam.java
index 32233037..b6577f4b 100644
--- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/param/LimitParam.java
+++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/param/LimitParam.java
@@ -21,10 +21,10 @@ public class LimitParam {
@NotBlank(message = "serviceId can not null")
private String serviceId;
- /** 限流策略,1:漏桶策略,2:令牌桶策略, 数据库字段:type */
+ /** 限流策略,1:漏桶策略,2:令牌桶策略, 数据库字段:limit_type */
@ApiDocField(description = "限流策略,1:漏桶策略,2:令牌桶策略")
@NotNull
- private Byte type;
+ private Byte limitType;
/** 每秒可处理请求数, 数据库字段:exec_count_per_second */
@ApiDocField(description = "每秒可处理请求数")
diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/result/LimitVO.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/result/LimitVO.java
index 72362cfa..166f72cc 100644
--- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/result/LimitVO.java
+++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/result/LimitVO.java
@@ -11,7 +11,7 @@ import lombok.Data;
@Data
public class LimitVO {
@ApiDocField(description = "是否存在记录")
- private int hasRecord;
+ private Integer hasRecord;
@ApiDocField(description = "路由id")
private String routeId;
@@ -32,10 +32,10 @@ public class LimitVO {
private String serviceId;
/**
- * 限流策略,1:漏桶策略,2:令牌桶策略, 数据库字段:type
+ * 限流策略,1:漏桶策略,2:令牌桶策略, 数据库字段:limit_type
*/
@ApiDocField(description = "限流策略,1:漏桶策略,2:令牌桶策略")
- private Byte type;
+ private Byte limitType;
/**
* 每秒可处理请求数, 数据库字段:exec_count_per_second
diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/RouteConfigDto.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/RouteConfigDto.java
index 5455f487..5a6fc6ca 100644
--- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/RouteConfigDto.java
+++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/RouteConfigDto.java
@@ -10,8 +10,8 @@ public class RouteConfigDto {
private String routeId;
- /** 限流策略,1:漏桶策略,2:令牌桶策略, 数据库字段:type */
- private Byte type;
+ /** 限流策略,1:漏桶策略,2:令牌桶策略, 数据库字段:limit_type */
+ private Byte limitType;
/** 每秒可处理请求数, 数据库字段:exec_count_per_second */
private Integer execCountPerSecond;
diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/entity/ConfigRouteLimit.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/entity/ConfigRouteLimit.java
index 6168695b..6b927d1c 100644
--- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/entity/ConfigRouteLimit.java
+++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/entity/ConfigRouteLimit.java
@@ -32,8 +32,8 @@ public class ConfigRouteLimit {
/** serviceId, 数据库字段:service_id */
private String serviceId;
- /** 限流策略,1:漏桶策略,2:令牌桶策略, 数据库字段:type */
- private Byte type;
+ /** 限流策略,1:漏桶策略,2:令牌桶策略, 数据库字段:limit_type */
+ private Byte limitType;
/** 每秒可处理请求数, 数据库字段:exec_count_per_second */
private Integer execCountPerSecond;
diff --git a/sop-common/pom.xml b/sop-common/pom.xml
index 1feaed2e..fc4fea87 100644
--- a/sop-common/pom.xml
+++ b/sop-common/pom.xml
@@ -138,6 +138,7 @@
org.apache.maven.plugins
maven-surefire-plugin
+ 2.12.4
true
@@ -145,6 +146,7 @@
org.apache.maven.plugins
maven-compiler-plugin
+ 3.1
${java.version}
${java.version}
@@ -164,24 +166,6 @@
-
-
- org.apache.maven.plugins
- maven-javadoc-plugin
- 2.9
-
-
- attach-javadocs
-
- jar
-
-
-
- -Xdoclint:none
-
-
-
-
diff --git a/sop-common/sop-gateway-common/pom.xml b/sop-common/sop-gateway-common/pom.xml
index 3af455eb..479a61f4 100644
--- a/sop-common/sop-gateway-common/pom.xml
+++ b/sop-common/sop-gateway-common/pom.xml
@@ -8,9 +8,8 @@
1.2.0-SNAPSHOT
../pom.xml
- com.gitee.sop
sop-gateway-common
- ${parent.version}
+ 1.2.0-SNAPSHOT
jar
sop-gateway-common
@@ -21,6 +20,12 @@
+
+ com.google.guava
+ guava
+ 27.1-jre
+
+
commons-fileupload
commons-fileupload
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/ApiConfig.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/ApiConfig.java
index f9326a63..e976cad9 100644
--- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/ApiConfig.java
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/ApiConfig.java
@@ -3,6 +3,8 @@ package com.gitee.sop.gatewaycommon.bean;
import com.gitee.sop.gatewaycommon.gateway.param.GatewayParamBuilder;
import com.gitee.sop.gatewaycommon.gateway.result.GatewayResult;
import com.gitee.sop.gatewaycommon.gateway.result.GatewayResultExecutor;
+import com.gitee.sop.gatewaycommon.limit.DefaultLimitManager;
+import com.gitee.sop.gatewaycommon.limit.LimitManager;
import com.gitee.sop.gatewaycommon.manager.DefaultIsvRoutePermissionManager;
import com.gitee.sop.gatewaycommon.manager.DefaultRouteConfigManager;
import com.gitee.sop.gatewaycommon.manager.IsvRoutePermissionManager;
@@ -101,6 +103,11 @@ public class ApiConfig {
*/
private RouteConfigManager routeConfigManager = new DefaultRouteConfigManager();
+ /**
+ * 限流管理
+ */
+ private LimitManager limitManager = new DefaultLimitManager();
+
// -------- fields ---------
/**
@@ -125,6 +132,11 @@ public class ApiConfig {
*/
private int timeoutSeconds = 60 * 5;
+ /**
+ * 是否开启限流功能
+ */
+ private boolean openLimit = true;
+
public void addAppSecret(Map appSecretPair) {
for (Map.Entry entry : appSecretPair.entrySet()) {
this.isvManager.update(new IsvDefinition(entry.getKey(), entry.getValue()));
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/Isv.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/Isv.java
index 9ceae332..5eb8e287 100644
--- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/Isv.java
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/Isv.java
@@ -7,19 +7,19 @@ public interface Isv {
/**
* appKey
- * @return
+ * @return 返回appKey
*/
String getAppKey();
/**
* 秘钥
- * @return
+ * @return 返回秘钥
*/
String getSecretInfo();
/**
* 0启用,1禁用
- * @return
+ * @return 返回状态
*/
Byte getStatus();
}
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/RouteConfig.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/RouteConfig.java
index 0093daa9..7b9aad95 100644
--- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/RouteConfig.java
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/RouteConfig.java
@@ -1,6 +1,16 @@
package com.gitee.sop.gatewaycommon.bean;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
+import com.google.common.util.concurrent.RateLimiter;
+import lombok.AccessLevel;
import lombok.Data;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicLong;
/**
* @author tanghc
@@ -13,33 +23,71 @@ public class RouteConfig {
private String routeId;
- /** 限流策略,1:漏桶策略,2:令牌桶策略, 数据库字段:type */
- private Byte type;
+ /** 限流策略,1:漏桶策略,2:令牌桶策略, 数据库字段:limit_type */
+ private Byte limitType = 1;
/** 每秒可处理请求数, 数据库字段:exec_count_per_second */
- private Integer execCountPerSecond;
+ private Integer execCountPerSecond = 10;
/** 返回的错误码, 数据库字段:limit_code */
- private String limitCode;
+ private String limitCode = "isp.service-busy";
/** 返回的错误信息, 数据库字段:limit_msg */
- private String limitMsg;
+ private String limitMsg = "服务繁忙,请稍后再试";
/** 令牌桶容量, 数据库字段:token_bucket_count */
- private Integer tokenBucketCount;
+ private Integer tokenBucketCount = 10;
/** 限流开启状态,1:开启,0关闭, 数据库字段:limit_status */
private Byte limitStatus = LIMIT_STATUS_CLOSE;
/**
- * 状态,0:待审核,1:启用,2:禁用
+ * 状态,0:待审核,1:启用,2:禁用。默认启用
*/
private Byte status = STATUS_ENABLE;
/**
- * 是否启用
+ * 漏桶计数器
+ */
+ private LoadingCache counter = CacheBuilder.newBuilder()
+ .expireAfterWrite(2, TimeUnit.SECONDS)
+ .build(new CacheLoader() {
+ @Override
+ public AtomicLong load(Long seconds) throws Exception {
+ return new AtomicLong(0);
+ }
+ });
+
+ /**
+ * 令牌桶
+ */
+ @Getter(AccessLevel.PRIVATE)
+ @Setter(AccessLevel.PRIVATE)
+ private volatile RateLimiter rateLimiter;
+
+ public synchronized void initRateLimiter() {
+ rateLimiter = RateLimiter.create(tokenBucketCount);
+ }
+
+ /**
+ * 获取令牌桶
* @return
*/
+ public synchronized RateLimiter fetchRateLimiter() {
+ if (rateLimiter == null) {
+ synchronized (this.routeId) {
+ if (rateLimiter == null) {
+ rateLimiter = RateLimiter.create(tokenBucketCount);
+ }
+ }
+ }
+ return rateLimiter;
+ }
+
+ /**
+ * 是否启用
+ * @return true:启用
+ */
public boolean enable() {
return status == STATUS_ENABLE;
}
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/RouteConfigDto.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/RouteConfigDto.java
index 664bb478..65750bee 100644
--- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/RouteConfigDto.java
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/RouteConfigDto.java
@@ -10,8 +10,8 @@ public class RouteConfigDto {
private String routeId;
- /** 限流策略,1:漏桶策略,2:令牌桶策略, 数据库字段:type */
- private Byte type;
+ /** 限流策略,1:漏桶策略,2:令牌桶策略, 数据库字段:limit_type */
+ private Byte limitType;
/** 每秒可处理请求数, 数据库字段:exec_count_per_second */
private Integer execCountPerSecond;
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/configuration/BaseGatewayConfiguration.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/configuration/BaseGatewayConfiguration.java
index 5e07b075..7694f84b 100644
--- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/configuration/BaseGatewayConfiguration.java
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/configuration/BaseGatewayConfiguration.java
@@ -33,9 +33,8 @@ public class BaseGatewayConfiguration extends AbstractConfiguration {
/**
* 自定义异常处理[@@]注册Bean时依赖的Bean,会从容器中直接获取,所以直接注入即可
*
- * @param viewResolversProvider
- * @param serverCodecConfigurer
- * @return
+ * @param viewResolversProvider viewResolversProvider
+ * @param serverCodecConfigurer serverCodecConfigurer
*/
@Primary
@Bean
@@ -52,8 +51,6 @@ public class BaseGatewayConfiguration extends AbstractConfiguration {
/**
* 处理返回结果
- *
- * @return
*/
@Bean
GatewayModifyResponseGatewayFilter gatewayModifyResponseGatewayFilter() {
@@ -62,8 +59,6 @@ public class BaseGatewayConfiguration extends AbstractConfiguration {
/**
* 读取post请求参数
- *
- * @return
*/
@Bean
ReadBodyRoutePredicateFactory readBodyRoutePredicateFactory() {
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/LimitFilter.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/LimitFilter.java
new file mode 100644
index 00000000..92102de3
--- /dev/null
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/LimitFilter.java
@@ -0,0 +1,67 @@
+package com.gitee.sop.gatewaycommon.gateway.filter;
+
+import com.gitee.sop.gatewaycommon.bean.ApiConfig;
+import com.gitee.sop.gatewaycommon.bean.ApiContext;
+import com.gitee.sop.gatewaycommon.bean.RouteConfig;
+import com.gitee.sop.gatewaycommon.bean.SopConstants;
+import com.gitee.sop.gatewaycommon.exception.ApiException;
+import com.gitee.sop.gatewaycommon.limit.LimitManager;
+import com.gitee.sop.gatewaycommon.limit.LimitType;
+import com.gitee.sop.gatewaycommon.manager.RouteConfigManager;
+import com.gitee.sop.gatewaycommon.message.ErrorImpl;
+import com.gitee.sop.gatewaycommon.param.ApiParam;
+import com.gitee.sop.gatewaycommon.param.ParamNames;
+import com.gitee.sop.gatewaycommon.util.RouteUtil;
+import com.gitee.sop.gatewaycommon.validate.Validator;
+import com.gitee.sop.gatewaycommon.zuul.ZuulContext;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.cloud.gateway.filter.GatewayFilterChain;
+import org.springframework.cloud.gateway.filter.GlobalFilter;
+import org.springframework.core.Ordered;
+import org.springframework.web.server.ServerWebExchange;
+import reactor.core.publisher.Mono;
+
+import java.util.Map;
+
+/**
+ * @author tanghc
+ */
+@Slf4j
+public class LimitFilter implements GlobalFilter, Ordered {
+
+ @Override
+ public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {
+ ApiConfig apiConfig = ApiConfig.getInstance();
+ // 限流功能未开启,直接返回
+ if (!apiConfig.isOpenLimit()) {
+ return chain.filter(exchange);
+ }
+ Map apiParam = exchange.getAttribute(SopConstants.CACHE_API_PARAM);
+ String routeId = apiParam.get(ParamNames.API_NAME).toString() + apiParam.get(ParamNames.VERSION_NAME);
+ RouteConfigManager routeConfigManager = apiConfig.getRouteConfigManager();
+ RouteConfig routeConfig = routeConfigManager.get(routeId);
+ if (routeConfig == null) {
+ return chain.filter(exchange);
+ }
+ // 某个路由限流功能未开启
+ if (routeConfig.getLimitStatus() == RouteConfig.LIMIT_STATUS_CLOSE) {
+ return chain.filter(exchange);
+ }
+ byte limitType = routeConfig.getLimitType().byteValue();
+ LimitManager limitManager = ApiConfig.getInstance().getLimitManager();
+ if (limitType == LimitType.LEAKY_BUCKET.getType()) {
+ boolean acquire = limitManager.acquire(routeConfig);
+ if (!acquire) {
+ throw new ApiException(new ErrorImpl(routeConfig.getLimitCode(), routeConfig.getLimitMsg()));
+ }
+ } else if (limitType == LimitType.TOKEN_BUCKET.getType()) {
+ limitManager.acquireToken(routeConfig);
+ }
+ return chain.filter(exchange);
+ }
+
+ @Override
+ public int getOrder() {
+ return Orders.LIMIT_ORDER;
+ }
+}
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/Orders.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/Orders.java
new file mode 100644
index 00000000..1485d969
--- /dev/null
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/Orders.java
@@ -0,0 +1,14 @@
+package com.gitee.sop.gatewaycommon.gateway.filter;
+
+import org.springframework.core.Ordered;
+
+/**
+ * @author tanghc
+ */
+public class Orders {
+ /** 验证拦截器order */
+ public static final int VALIDATE_ORDER = Ordered.HIGHEST_PRECEDENCE + 1000;
+
+ /** 验证拦截器order */
+ public static final int LIMIT_ORDER = VALIDATE_ORDER + 1;
+}
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/ValidateFilter.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/ValidateFilter.java
index f1345eec..7004ef83 100644
--- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/ValidateFilter.java
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/ValidateFilter.java
@@ -2,9 +2,13 @@ package com.gitee.sop.gatewaycommon.gateway.filter;
import com.gitee.sop.gatewaycommon.bean.ApiConfig;
import com.gitee.sop.gatewaycommon.bean.ApiContext;
+import com.gitee.sop.gatewaycommon.bean.RouteConfig;
import com.gitee.sop.gatewaycommon.bean.SopConstants;
import com.gitee.sop.gatewaycommon.exception.ApiException;
+import com.gitee.sop.gatewaycommon.manager.RouteConfigManager;
+import com.gitee.sop.gatewaycommon.message.ErrorEnum;
import com.gitee.sop.gatewaycommon.param.ApiParam;
+import com.gitee.sop.gatewaycommon.util.RouteUtil;
import com.gitee.sop.gatewaycommon.validate.Validator;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
@@ -25,6 +29,7 @@ public class ValidateFilter implements GlobalFilter, Ordered {
// 解析参数
ApiParam param = apiConfig.getGatewayParamBuilder().build(exchange);
exchange.getAttributes().put(SopConstants.CACHE_API_PARAM, param);
+ RouteUtil.checkEnable(param);
// 验证操作,这里有负责验证签名参数
Validator validator = apiConfig.getValidator();
try {
@@ -39,6 +44,6 @@ public class ValidateFilter implements GlobalFilter, Ordered {
@Override
public int getOrder() {
// 最优先执行
- return Ordered.HIGHEST_PRECEDENCE + 1000;
+ return Orders.VALIDATE_ORDER;
}
}
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/handler/GatewayExceptionHandler.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/handler/GatewayExceptionHandler.java
index a1eec192..be8331e7 100644
--- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/handler/GatewayExceptionHandler.java
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/handler/GatewayExceptionHandler.java
@@ -36,21 +36,15 @@ public class GatewayExceptionHandler implements ErrorWebExceptionHandler {
ResultExecutor resultExecutor = ApiContext.getApiConfig().getGatewayResultExecutor();
GatewayResult errorResult = resultExecutor.buildErrorResult(exchange, ex);
- /**
- * 错误记录
- */
+ // 错误记录
ServerHttpRequest request = exchange.getRequest();
log.error("[全局异常处理]异常请求路径:{}, msg:{}", request.getPath(), ex.getMessage(), ex);
- /**
- * 参考AbstractErrorWebExceptionHandler
- */
+ // 参考AbstractErrorWebExceptionHandler
if (exchange.getResponse().isCommitted()) {
return Mono.error(ex);
}
ServerRequest newRequest = ServerRequest.create(exchange, this.messageReaders);
- return RouterFunctions.route(RequestPredicates.all(), (serverRequest) -> {
- return this.renderErrorResponse(errorResult);
- }).route(newRequest)
+ return RouterFunctions.route(RequestPredicates.all(), (serverRequest) -> this.renderErrorResponse(errorResult)).route(newRequest)
.switchIfEmpty(Mono.error(ex))
.flatMap((handler) -> handler.handle(newRequest))
.flatMap((response) -> write(exchange, response));
@@ -75,7 +69,7 @@ public class GatewayExceptionHandler implements ErrorWebExceptionHandler {
/**
* 参考AbstractErrorWebExceptionHandler
*
- * @param messageReaders
+ * @param messageReaders messageReaders
*/
public void setMessageReaders(List> messageReaders) {
Assert.notNull(messageReaders, "'messageReaders' must not be null");
@@ -85,7 +79,7 @@ public class GatewayExceptionHandler implements ErrorWebExceptionHandler {
/**
* 参考AbstractErrorWebExceptionHandler
*
- * @param viewResolvers
+ * @param viewResolvers viewResolvers
*/
public void setViewResolvers(List viewResolvers) {
this.viewResolvers = viewResolvers;
@@ -94,7 +88,7 @@ public class GatewayExceptionHandler implements ErrorWebExceptionHandler {
/**
* 参考AbstractErrorWebExceptionHandler
*
- * @param messageWriters
+ * @param messageWriters messageWriters
*/
public void setMessageWriters(List> messageWriters) {
Assert.notNull(messageWriters, "'messageWriters' must not be null");
@@ -105,8 +99,8 @@ public class GatewayExceptionHandler implements ErrorWebExceptionHandler {
/**
* 参考DefaultErrorWebExceptionHandler
*
- * @param result
- * @return
+ * @param result 返回结果
+ * @return 返回mono
*/
protected Mono renderErrorResponse(GatewayResult result) {
return ServerResponse
@@ -118,9 +112,9 @@ public class GatewayExceptionHandler implements ErrorWebExceptionHandler {
/**
* 参考AbstractErrorWebExceptionHandler
*
- * @param exchange
- * @param response
- * @return
+ * @param exchange exchange
+ * @param response response
+ * @return 返回Mono
*/
private Mono extends Void> write(ServerWebExchange exchange,
ServerResponse response) {
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/route/GatewayRouteRepository.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/route/GatewayRouteRepository.java
index 54e333f4..8d8c913a 100644
--- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/route/GatewayRouteRepository.java
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/route/GatewayRouteRepository.java
@@ -1,5 +1,6 @@
package com.gitee.sop.gatewaycommon.gateway.route;
+import com.gitee.sop.gatewaycommon.bean.TargetRoute;
import com.gitee.sop.gatewaycommon.manager.RouteRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
@@ -22,6 +23,7 @@ import org.springframework.validation.Validator;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
+import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
@@ -58,7 +60,7 @@ public class GatewayRouteRepository implements ApplicationEventPublisherAware,
@Override
public Flux getRouteDefinitions() {
List list = routes.values().parallelStream()
- .map(targetRoute -> targetRoute.getTargetRouteDefinition())
+ .map(TargetRoute::getTargetRouteDefinition)
.collect(Collectors.toList());
return Flux.fromIterable(list);
}
@@ -81,6 +83,11 @@ public class GatewayRouteRepository implements ApplicationEventPublisherAware,
return routes.get(id);
}
+ @Override
+ public Collection getAll() {
+ return routes.values();
+ }
+
/**
* 增加路由
*/
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/route/NameVersionRoutePredicateFactory.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/route/NameVersionRoutePredicateFactory.java
index 1ee16ce3..b13a53c6 100644
--- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/route/NameVersionRoutePredicateFactory.java
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/route/NameVersionRoutePredicateFactory.java
@@ -1,11 +1,6 @@
package com.gitee.sop.gatewaycommon.gateway.route;
-import com.gitee.sop.gatewaycommon.bean.ApiConfig;
-import com.gitee.sop.gatewaycommon.bean.RouteConfig;
import com.gitee.sop.gatewaycommon.bean.SopConstants;
-import com.gitee.sop.gatewaycommon.bean.TargetRoute;
-import com.gitee.sop.gatewaycommon.manager.RouteConfigManager;
-import com.gitee.sop.gatewaycommon.manager.RouteRepositoryContext;
import com.gitee.sop.gatewaycommon.param.ParamNames;
import com.gitee.sop.gatewaycommon.util.RequestUtil;
import lombok.extern.slf4j.Slf4j;
@@ -45,7 +40,7 @@ public class NameVersionRoutePredicateFactory extends AbstractRoutePredicateFact
* config.param为nameVersion
*
* @param config
- * @return
+ * @return 返回断言
*/
@Override
public Predicate apply(Config config) {
@@ -65,14 +60,6 @@ public class NameVersionRoutePredicateFactory extends AbstractRoutePredicateFact
String name = params.getOrDefault(ParamNames.API_NAME, String.valueOf(System.currentTimeMillis()));
String version = params.getOrDefault(ParamNames.VERSION_NAME, "");
boolean match = (name + version).equals(nameVersion);
- if (match) {
- TargetRoute targetRoute = RouteRepositoryContext.getRouteRepository().get(nameVersion);
- RouteConfigManager routeConfigManager = ApiConfig.getInstance().getRouteConfigManager();
- RouteConfig routeConfig = routeConfigManager.get(nameVersion);
- if (targetRoute != null && !routeConfig.enable()) {
- return false;
- }
- }
return match;
};
}
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/route/ReadBodyRoutePredicateFactory.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/route/ReadBodyRoutePredicateFactory.java
index d53e1988..dc5b3259 100644
--- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/route/ReadBodyRoutePredicateFactory.java
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/route/ReadBodyRoutePredicateFactory.java
@@ -6,7 +6,7 @@ import java.util.Objects;
/**
* 获取form表单插件,使用方式:
- * @Bean
+ * @Bean
* ReadBodyRoutePredicateFactory readBodyRoutePredicateFactory() {
* return new ReadBodyRoutePredicateFactory();
* }
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/limit/DefaultLimitManager.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/limit/DefaultLimitManager.java
new file mode 100644
index 00000000..89b0eeed
--- /dev/null
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/limit/DefaultLimitManager.java
@@ -0,0 +1,52 @@
+package com.gitee.sop.gatewaycommon.limit;
+
+import com.gitee.sop.gatewaycommon.bean.RouteConfig;
+import com.google.common.cache.LoadingCache;
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.atomic.AtomicLong;
+
+/**
+ * @author tanghc
+ */
+@Slf4j
+public class DefaultLimitManager implements LimitManager {
+
+ @Override
+ public double acquireToken(RouteConfig routeConfig) {
+ if (routeConfig.getLimitStatus() == RouteConfig.LIMIT_STATUS_CLOSE) {
+ return 0;
+ }
+ if (LimitType.LEAKY_BUCKET.getType() == routeConfig.getLimitType().byteValue()) {
+ throw new IllegalStateException("漏桶策略无法调用此方法");
+ }
+ return routeConfig.fetchRateLimiter().acquire();
+ }
+
+
+ @Override
+ public boolean acquire(RouteConfig routeConfig) {
+ if (routeConfig.getLimitStatus() == RouteConfig.LIMIT_STATUS_CLOSE) {
+ return true;
+ }
+ if (LimitType.TOKEN_BUCKET.getType() == routeConfig.getLimitType().byteValue()) {
+ throw new IllegalStateException("令牌桶策略无法调用此方法");
+ }
+ int execCountPerSecond = routeConfig.getExecCountPerSecond();
+ long currentSeconds = System.currentTimeMillis() / 1000;
+ try {
+ LoadingCache counter = routeConfig.getCounter();
+ // 被限流了
+ if (counter.get(currentSeconds).incrementAndGet() > execCountPerSecond) {
+ return false;
+ } else {
+ return true;
+ }
+ } catch (ExecutionException e) {
+ log.error("漏桶限流出错,routeConfig", routeConfig, e);
+ return false;
+ }
+ }
+
+}
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/limit/LimitManager.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/limit/LimitManager.java
new file mode 100644
index 00000000..7a333548
--- /dev/null
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/limit/LimitManager.java
@@ -0,0 +1,29 @@
+package com.gitee.sop.gatewaycommon.limit;
+
+import com.gitee.sop.gatewaycommon.bean.RouteConfig;
+
+/**
+ * 限流管理
+ * @author tanghc
+ */
+public interface LimitManager {
+
+ /**
+ * 从令牌桶中获取令牌,如果使用{@link LimitType#TOKEN_BUCKET
+ * RateType.TOKEN_BUCKET}限流策略,则该方法生效
+ *
+ * @param routeConfig 路由配置
+ * @return 返回耗时时间,秒
+ */
+ double acquireToken(RouteConfig routeConfig);
+
+ /**
+ * 是否需要限流,如果使用{@link LimitType#LEAKY_BUCKET
+ * RateType.LIMIT}限流策略,则该方法生效
+ *
+ * @param routeConfig 路由配置
+ * @return 如果返回true,表示可以执行业务代码,返回false则需要限流
+ */
+ boolean acquire(RouteConfig routeConfig);
+
+}
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/limit/LimitType.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/limit/LimitType.java
new file mode 100644
index 00000000..e7a768ee
--- /dev/null
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/limit/LimitType.java
@@ -0,0 +1,28 @@
+package com.gitee.sop.gatewaycommon.limit;
+
+/**
+ * 限流策略
+ *
+ * @author tanghc
+ */
+public enum LimitType {
+ /**
+ * 漏桶策略。每秒处理固定数量的请求,超出请求返回错误信息。
+ */
+ LEAKY_BUCKET(1),
+ /**
+ * 令牌桶策略,每秒放置固定数量的令牌数,不足的令牌数做等待处理,直到拿到令牌为止。
+ */
+ TOKEN_BUCKET(2);
+
+ private byte type;
+
+ LimitType(int type) {
+ this.type = (byte)type;
+ }
+
+ public byte getType() {
+ return type;
+ }
+
+}
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/BaseRouteManager.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/BaseRouteManager.java
index ccc493e7..fe905877 100644
--- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/BaseRouteManager.java
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/BaseRouteManager.java
@@ -42,14 +42,14 @@ public abstract class BaseRouteManager, E exte
/**
* 返回路由根对象class
*
- * @return
+ * @return 返回R.class
*/
protected abstract Class getServiceRouteInfoClass();
/**
* 返回路由Item对象class
*
- * @return
+ * @return 返回E.class
*/
protected abstract Class getRouteDefinitionClass();
@@ -58,7 +58,7 @@ public abstract class BaseRouteManager, E exte
*
* @param serviceRouteInfo
* @param routeDefinition
- * @return
+ * @return 返回目标路由对象
*/
protected abstract T buildRouteDefinition(R serviceRouteInfo, E routeDefinition);
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/DefaultRouteConfigManager.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/DefaultRouteConfigManager.java
index 701c772e..5b56bb66 100644
--- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/DefaultRouteConfigManager.java
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/DefaultRouteConfigManager.java
@@ -29,13 +29,19 @@ public class DefaultRouteConfigManager implements RouteConfigManager {
@Override
public void update(RouteConfigDto routeConfigDto) {
- String key = routeConfigDto.getRouteId();
- RouteConfig routeConfig = routeConfigMap.get(key);
+ this.doUpdate(routeConfigDto.getRouteId(), routeConfigDto);
+ }
+
+ protected void doUpdate(String routeId, Object res) {
+ RouteConfig routeConfig = routeConfigMap.get(routeId);
if (routeConfig == null) {
routeConfig = newRouteConfig();
- routeConfigMap.put(key, routeConfig);
+ routeConfig.setRouteId(routeId);
+ routeConfigMap.put(routeId, routeConfig);
+ } else {
+ MyBeanUtil.copyPropertiesIgnoreNull(res, routeConfig);
}
- MyBeanUtil.copyPropertiesIgnoreNull(routeConfigDto, routeConfig);
+ routeConfig.initRateLimiter();
}
protected RouteConfig newRouteConfig() {
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/IsvRoutePermissionManager.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/IsvRoutePermissionManager.java
index 6ff3b314..283f1bfe 100644
--- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/IsvRoutePermissionManager.java
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/IsvRoutePermissionManager.java
@@ -14,21 +14,21 @@ public interface IsvRoutePermissionManager {
/**
* 加载权限
- * @param isvRoutePermission
+ * @param isvRoutePermission isvRoutePermission
*/
void update(IsvRoutePermission isvRoutePermission);
/**
* 判断是否有权限
- * @param appKey
- * @param routeId
- * @return
+ * @param appKey appKey
+ * @param routeId 路由id
+ * @return true:有
*/
boolean hasPermission(String appKey, String routeId);
/**
* 删除权限
- * @param appKey
+ * @param appKey appKey
*/
void remove(String appKey);
}
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/RouteConfigManager.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/RouteConfigManager.java
index 67ace4df..941fbe59 100644
--- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/RouteConfigManager.java
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/RouteConfigManager.java
@@ -8,18 +8,21 @@ import com.gitee.sop.gatewaycommon.bean.RouteConfigDto;
* @author tanghc
*/
public interface RouteConfigManager {
+ /**
+ * 加载
+ */
void load();
/**
* 更新路由配置
- * @param routeConfigDto
+ * @param routeConfigDto 路由配置
*/
void update(RouteConfigDto routeConfigDto);
/**
* 获取路由配置
- * @param routeId
- * @return
+ * @param routeId 路由id
+ * @return 返回RouteConfig
*/
RouteConfig get(String routeId);
}
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/RouteRepository.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/RouteRepository.java
index b8158ec6..d2a26770 100644
--- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/RouteRepository.java
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/RouteRepository.java
@@ -2,6 +2,8 @@ package com.gitee.sop.gatewaycommon.manager;
import com.gitee.sop.gatewaycommon.bean.TargetRoute;
+import java.util.Collection;
+
/**
* @author tanghc
*/
@@ -9,20 +11,26 @@ public interface RouteRepository {
/**
* 获取路由信息
* @param id 路由id
- * @return
+ * @return 返回路由信息
*/
T get(String id);
+ /**
+ * 返回所有路由信息
+ * @return 返回所有路由信息
+ */
+ Collection getAll();
+
/**
* 添加路由
- * @param targetRoute
- * @return
+ * @param targetRoute 模板路由对象
+ * @return 返回路由id
*/
String add(T targetRoute);
/**
* 更新路由
- * @param targetRoute
+ * @param targetRoute 模板路由对象
*/
void update(T targetRoute);
@@ -34,7 +42,7 @@ public interface RouteRepository {
/**
* 删除service下的所有路由
- * @param serviceId
+ * @param serviceId 服务id
*/
void deleteAll(String serviceId);
}
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/ZookeeperContext.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/ZookeeperContext.java
index 33a717f2..53ba87be 100644
--- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/ZookeeperContext.java
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/ZookeeperContext.java
@@ -99,7 +99,7 @@ public class ZookeeperContext {
*
* @param path 已存在的
* @param data
- * @return
+ * @return 返回Stat
* @throws Exception
*/
public static Stat updatePathData(String path, String data) throws Exception {
@@ -128,7 +128,7 @@ public class ZookeeperContext {
* 新建或保存节点
* @param path
* @param data
- * @return
+ * @return 返回path
* @throws Exception
*/
public static String createOrUpdateData(String path, String data) throws Exception {
@@ -144,7 +144,7 @@ public class ZookeeperContext {
* 监听一个节点
* @param path
* @param onChange 节点修改后触发
- * @return
+ * @return 返回path
* @throws Exception
*/
public static String listenPath(String path, Consumer onChange) throws Exception {
@@ -172,7 +172,7 @@ public class ZookeeperContext {
* 获取子节点数据
*
* @param parentPath 父节点
- * @return
+ * @return 返回子节点数据
* @throws Exception
*/
public static List getChildrenData(String parentPath) throws Exception {
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/message/ErrorImpl.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/message/ErrorImpl.java
index cf5c72ed..110f9eec 100644
--- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/message/ErrorImpl.java
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/message/ErrorImpl.java
@@ -7,6 +7,9 @@ import lombok.Data;
*/
@Data
public class ErrorImpl implements Error {
+ public static final String ISP_SERVICE_NOT_AVAILABLE = "isp.service-not-available";
+ public static final String SERVICE_NOT_AVAILABLE = "service not available";
+
private String code;
private String msg;
private String sub_code;
@@ -16,6 +19,10 @@ public class ErrorImpl implements Error {
public ErrorImpl() {
}
+ public ErrorImpl(String sub_code, String sub_msg) {
+ this(ISP_SERVICE_NOT_AVAILABLE, SERVICE_NOT_AVAILABLE, sub_code, sub_msg, null);
+ }
+
public ErrorImpl(String code, String msg, String sub_code, String sub_msg, String solution) {
this.code = code;
this.msg = msg;
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/param/ApiParam.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/param/ApiParam.java
index c91564f6..b62eabb4 100644
--- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/param/ApiParam.java
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/param/ApiParam.java
@@ -1,6 +1,7 @@
package com.gitee.sop.gatewaycommon.param;
import com.alibaba.fastjson.JSONObject;
+import com.alibaba.fastjson.annotation.JSONField;
import com.gitee.sop.gatewaycommon.bean.SopConstants;
import org.apache.commons.lang3.StringUtils;
@@ -28,6 +29,11 @@ public class ApiParam extends JSONObject implements Param {
private transient ApiUploadContext apiUploadContext;
+ @JSONField(serialize = false)
+ public String getRouteId() {
+ return this.fetchNameVersion();
+ }
+
/**
* 获取sign,并从param中删除
*
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/result/BaseExecutorAdapter.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/result/BaseExecutorAdapter.java
index f23a33cc..5978dd3a 100644
--- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/result/BaseExecutorAdapter.java
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/result/BaseExecutorAdapter.java
@@ -36,14 +36,14 @@ public abstract class BaseExecutorAdapter implements ResultExecutor
/**
* 获取业务方约定的返回码
* @param t
- * @return
+ * @return 返回返回码
*/
public abstract int getResponseStatus(T t);
/**
* 返回Api参数
* @param t
- * @return
+ * @return 返回api参数
*/
public abstract Map getApiParam(T t);
@@ -79,7 +79,7 @@ public abstract class BaseExecutorAdapter implements ResultExecutor
/**
* 该路由是否合并结果
* @param request
- * @return
+ * @return true:需要合并
*/
protected boolean isMergeResult(T request) {
// 默认全局设置
@@ -130,9 +130,9 @@ public abstract class BaseExecutorAdapter implements ResultExecutor
if (method != null) {
name = String.valueOf(method);
}
- Object _sign = params.get(ParamNames.SIGN_NAME);
- if (_sign != null) {
- sign = String.valueOf(_sign);
+ Object clientSign = params.get(ParamNames.SIGN_NAME);
+ if (clientSign != null) {
+ sign = String.valueOf(clientSign);
}
}
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/session/ApiHttpSession.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/session/ApiHttpSession.java
index d235f572..1e9ea661 100644
--- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/session/ApiHttpSession.java
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/session/ApiHttpSession.java
@@ -107,7 +107,7 @@ public class ApiHttpSession implements HttpSession, Serializable {
}
/**
- * @return
+ * @return 返回HttpSessionContext。已废弃不能使用
* @deprecated 已废弃不能使用
*/
@Override
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/session/RedisHttpSession.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/session/RedisHttpSession.java
index fab86419..d684b060 100644
--- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/session/RedisHttpSession.java
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/session/RedisHttpSession.java
@@ -60,8 +60,8 @@ public class RedisHttpSession implements HttpSession, Serializable {
/**
* 创建新的session
*
- * @param servletContext
- * @param sessionId
+ * @param servletContext servletContext
+ * @param sessionId sessionId
* @param sessionTimeout 过期时间,单位秒
* @param redisTemplate redis客户端
* @param keyPrefix 存入的key前缀
@@ -93,8 +93,8 @@ public class RedisHttpSession implements HttpSession, Serializable {
/**
* 创建已经存在的session,数据在redis里面
*
- * @param sessionId
- * @param servletContext
+ * @param sessionId sessionId
+ * @param servletContext servletContext
* @param redisTemplate redis客户端
* @param keyPrefix 存入的key前缀
* @return 返回session
@@ -161,8 +161,8 @@ public class RedisHttpSession implements HttpSession, Serializable {
}
/**
+ * @return 返回HttpSessionContext。已废弃不能使用
* @deprecated 已废弃,始终返回null
- * @return
*/
@Override
@Deprecated
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/util/RequestUtil.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/util/RequestUtil.java
index 2670b487..28a60acc 100644
--- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/util/RequestUtil.java
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/util/RequestUtil.java
@@ -26,7 +26,7 @@ public class RequestUtil {
* 将get类型的参数转换成map,
*
* @param query charset=utf-8&biz_content=xxx
- * @return
+ * @return 返回map参数
*/
public static Map parseQueryToMap(String query) {
if (query == null) {
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/util/ResponseUtil.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/util/ResponseUtil.java
index 085c4a48..9048f128 100644
--- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/util/ResponseUtil.java
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/util/ResponseUtil.java
@@ -40,7 +40,7 @@ public class ResponseUtil {
* map转成xml
*
* @param parameters
- * @return
+ * @return 返回xml内容
*/
public static String mapToXml(JSONObject parameters) {
String content = doMap2xml(parameters);
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/util/RouteUtil.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/util/RouteUtil.java
index bc003390..d763a7a6 100644
--- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/util/RouteUtil.java
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/util/RouteUtil.java
@@ -1,5 +1,11 @@
package com.gitee.sop.gatewaycommon.util;
+import com.gitee.sop.gatewaycommon.bean.ApiConfig;
+import com.gitee.sop.gatewaycommon.bean.RouteConfig;
+import com.gitee.sop.gatewaycommon.manager.RouteConfigManager;
+import com.gitee.sop.gatewaycommon.message.ErrorEnum;
+import com.gitee.sop.gatewaycommon.param.ApiParam;
+
/**
* @author tanghc
*/
@@ -7,10 +13,23 @@ public class RouteUtil {
private RouteUtil(){}
- public static final String REGEX = "\\#";
+ private static final String REGEX = "\\#";
public static final String PROTOCOL_LOAD_BALANCE = "lb://";
+ /**
+ * 检测能否访问
+ * @param param 接口参数
+ */
+ public static void checkEnable(ApiParam param) {
+ String routeId = param.fetchNameVersion();
+ RouteConfigManager routeConfigManager = ApiConfig.getInstance().getRouteConfigManager();
+ RouteConfig routeConfig = routeConfigManager.get(routeId);
+ if (!routeConfig.enable()) {
+ throw ErrorEnum.ISP_API_DISABLED.getErrorMeta().getException();
+ }
+ }
+
public static String findPath(String uri) {
// #后面是对应的path
String[] uriArr = uri.split(REGEX);
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/validate/AbstractSigner.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/validate/AbstractSigner.java
index e507db8b..4d6b1bf7 100644
--- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/validate/AbstractSigner.java
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/validate/AbstractSigner.java
@@ -14,9 +14,9 @@ public abstract class AbstractSigner implements Signer {
/**
* 构建服务端签名串
*
- * @param params
- * @param secret
- * @return
+ * @param params 接口参数
+ * @param secret 秘钥
+ * @return 返回服务端签名串
*/
protected abstract String buildServerSign(ApiParam params, String secret);
@@ -30,7 +30,7 @@ public abstract class AbstractSigner implements Signer {
return clientSign.equals(serverSign);
}
- public static String byte2hex(byte[] bytes) {
+ protected static String byte2hex(byte[] bytes) {
StringBuilder sign = new StringBuilder();
for (int i = 0; i < bytes.length; i++) {
String hex = Integer.toHexString(bytes[i] & 0xFF);
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/validate/ApiValidator.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/validate/ApiValidator.java
index 6bf21014..627becc0 100644
--- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/validate/ApiValidator.java
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/validate/ApiValidator.java
@@ -60,6 +60,7 @@ public class ApiValidator implements Validator {
checkFormat(param);
}
+
/**
* 校验上传文件内容
*
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/configuration/BaseZuulConfiguration.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/configuration/BaseZuulConfiguration.java
index 402e6e79..45d17017 100644
--- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/configuration/BaseZuulConfiguration.java
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/configuration/BaseZuulConfiguration.java
@@ -5,6 +5,7 @@ import com.gitee.sop.gatewaycommon.manager.AbstractConfiguration;
import com.gitee.sop.gatewaycommon.manager.RouteRepositoryContext;
import com.gitee.sop.gatewaycommon.zuul.filter.ErrorFilter;
import com.gitee.sop.gatewaycommon.zuul.filter.PostResultFilter;
+import com.gitee.sop.gatewaycommon.zuul.filter.PreLimitFilter;
import com.gitee.sop.gatewaycommon.zuul.filter.PreRoutePermissionFilter;
import com.gitee.sop.gatewaycommon.zuul.filter.PreValidateFilter;
import com.gitee.sop.gatewaycommon.zuul.route.SopRouteLocator;
@@ -48,7 +49,7 @@ public class BaseZuulConfiguration extends AbstractConfiguration {
* @return
*/
@Bean
- public PreDecorationFilter preDecorationFilter(ZuulRouteRepository zuulRouteRepository, ProxyRequestHelper proxyRequestHelper) {
+ PreDecorationFilter preDecorationFilter(ZuulRouteRepository zuulRouteRepository, ProxyRequestHelper proxyRequestHelper) {
// 自定义路由
RouteLocator routeLocator = new SopRouteLocator(zuulRouteRepository);
return new PreDecorationFilter(routeLocator,
@@ -61,7 +62,6 @@ public class BaseZuulConfiguration extends AbstractConfiguration {
* 路由管理
* @param environment
* @param zuulRouteRepository
- * @return
*/
@Bean
ZuulZookeeperRouteManager zuulZookeeperRouteManager(Environment environment, ZuulRouteRepository zuulRouteRepository) {
@@ -70,16 +70,22 @@ public class BaseZuulConfiguration extends AbstractConfiguration {
/**
* 前置校验
- * @return
*/
@Bean
PreValidateFilter preValidateFilter() {
return new PreValidateFilter();
}
+ /**
+ * 开启限流
+ */
+ @Bean
+ PreLimitFilter preLimitFilter() {
+ return new PreLimitFilter();
+ }
+
/**
* 权限校验
- * @return
*/
@Bean
PreRoutePermissionFilter preRoutePermissionFilter() {
@@ -88,7 +94,6 @@ public class BaseZuulConfiguration extends AbstractConfiguration {
/**
* 错误处理扩展
- * @return
*/
@Bean
ErrorFilter errorFilter() {
@@ -97,7 +102,6 @@ public class BaseZuulConfiguration extends AbstractConfiguration {
/**
* 结果返回
- * @return
*/
@Bean
PostResultFilter postResultFilter() {
@@ -106,7 +110,6 @@ public class BaseZuulConfiguration extends AbstractConfiguration {
/**
* 统一错误处理
- * @return
*/
@Bean
ZuulErrorController baseZuulController() {
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/filter/BaseZuulFilter.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/filter/BaseZuulFilter.java
index 3a2b974c..0abc09a4 100644
--- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/filter/BaseZuulFilter.java
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/filter/BaseZuulFilter.java
@@ -15,8 +15,15 @@ public abstract class BaseZuulFilter extends ZuulFilter {
protected Logger log = LoggerFactory.getLogger(getClass());
+ /** 签名验证过滤 */
public static final int PRE_VALIDATE_FILTER_ORDER = -1000;
+ /** 权限验证过滤 */
+ public static final int PRE_ROUTE_PERMISSION_FILTER_ORDER = PRE_VALIDATE_FILTER_ORDER + 1;
+
+ /** 限流过滤 */
+ public static final int PRE_LIMIT_FILTER_ORDER = PRE_ROUTE_PERMISSION_FILTER_ORDER + 1;
+
private Integer filterOrder;
/**
@@ -28,7 +35,7 @@ public abstract class BaseZuulFilter extends ZuulFilter {
/**
* 获取过滤器顺序
- * @return
+ * @return 返回顺序,越小优先执行
* @see ZuulFilter#filterOrder() filterOrder()
*/
protected abstract int getFilterOrder();
@@ -36,7 +43,7 @@ public abstract class BaseZuulFilter extends ZuulFilter {
/**
* 执行run
* @param requestContext
- * @return
+ * @return Some arbitrary artifact may be returned. Current implementation ignores it.
* @throws ZuulException
*/
protected abstract Object doRun(RequestContext requestContext) throws ZuulException;
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/filter/PreLimitFilter.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/filter/PreLimitFilter.java
new file mode 100644
index 00000000..d0542feb
--- /dev/null
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/filter/PreLimitFilter.java
@@ -0,0 +1,62 @@
+package com.gitee.sop.gatewaycommon.zuul.filter;
+
+import com.gitee.sop.gatewaycommon.bean.ApiConfig;
+import com.gitee.sop.gatewaycommon.bean.RouteConfig;
+import com.gitee.sop.gatewaycommon.bean.TargetRoute;
+import com.gitee.sop.gatewaycommon.exception.ApiException;
+import com.gitee.sop.gatewaycommon.limit.LimitManager;
+import com.gitee.sop.gatewaycommon.limit.LimitType;
+import com.gitee.sop.gatewaycommon.manager.RouteConfigManager;
+import com.gitee.sop.gatewaycommon.manager.RouteRepositoryContext;
+import com.gitee.sop.gatewaycommon.message.ErrorImpl;
+import com.gitee.sop.gatewaycommon.param.ApiParam;
+import com.gitee.sop.gatewaycommon.zuul.ZuulContext;
+import com.netflix.zuul.context.RequestContext;
+import com.netflix.zuul.exception.ZuulException;
+
+/**
+ * 限流拦截器
+ * @author tanghc
+ */
+public class PreLimitFilter extends BaseZuulFilter {
+ @Override
+ protected FilterType getFilterType() {
+ return FilterType.PRE;
+ }
+
+ @Override
+ protected int getFilterOrder() {
+ return PRE_LIMIT_FILTER_ORDER;
+ }
+
+ @Override
+ protected Object doRun(RequestContext requestContext) throws ZuulException {
+ ApiConfig apiConfig = ApiConfig.getInstance();
+ // 限流功能未开启,直接返回
+ if (!apiConfig.isOpenLimit()) {
+ return null;
+ }
+ ApiParam apiParam = ZuulContext.getApiParam();
+ String routeId = apiParam.getRouteId();
+ RouteConfigManager routeConfigManager = apiConfig.getRouteConfigManager();
+ RouteConfig routeConfig = routeConfigManager.get(routeId);
+ if (routeConfig == null) {
+ return null;
+ }
+ // 某个路由限流功能未开启
+ if (routeConfig.getLimitStatus() == RouteConfig.LIMIT_STATUS_CLOSE) {
+ return null;
+ }
+ byte limitType = routeConfig.getLimitType().byteValue();
+ LimitManager limitManager = ApiConfig.getInstance().getLimitManager();
+ if (limitType == LimitType.LEAKY_BUCKET.getType()) {
+ boolean acquire = limitManager.acquire(routeConfig);
+ if (!acquire) {
+ throw new ApiException(new ErrorImpl(routeConfig.getLimitCode(), routeConfig.getLimitMsg()));
+ }
+ } else if (limitType == LimitType.TOKEN_BUCKET.getType()) {
+ limitManager.acquireToken(routeConfig);
+ }
+ return null;
+ }
+}
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/filter/PreValidateFilter.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/filter/PreValidateFilter.java
index 1874d8f5..228a1478 100644
--- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/filter/PreValidateFilter.java
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/filter/PreValidateFilter.java
@@ -2,8 +2,12 @@ package com.gitee.sop.gatewaycommon.zuul.filter;
import com.gitee.sop.gatewaycommon.bean.ApiContext;
import com.gitee.sop.gatewaycommon.bean.ApiConfig;
+import com.gitee.sop.gatewaycommon.bean.RouteConfig;
import com.gitee.sop.gatewaycommon.exception.ApiException;
+import com.gitee.sop.gatewaycommon.manager.RouteConfigManager;
+import com.gitee.sop.gatewaycommon.message.ErrorEnum;
import com.gitee.sop.gatewaycommon.param.ApiParam;
+import com.gitee.sop.gatewaycommon.util.RouteUtil;
import com.gitee.sop.gatewaycommon.validate.Validator;
import com.gitee.sop.gatewaycommon.zuul.ZuulContext;
import com.netflix.zuul.context.RequestContext;
@@ -31,6 +35,7 @@ public class PreValidateFilter extends BaseZuulFilter {
// 解析参数
ApiParam param = apiConfig.getZuulParamBuilder().build(requestContext);
ZuulContext.setApiParam(param);
+ RouteUtil.checkEnable(param);
// 验证操作,这里有负责验证签名参数
Validator validator = apiConfig.getValidator();
try {
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/route/SopRouteLocator.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/route/SopRouteLocator.java
index e22c57de..e28a7b50 100644
--- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/route/SopRouteLocator.java
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/route/SopRouteLocator.java
@@ -1,9 +1,5 @@
package com.gitee.sop.gatewaycommon.zuul.route;
-import com.gitee.sop.gatewaycommon.bean.ApiConfig;
-import com.gitee.sop.gatewaycommon.bean.RouteConfig;
-import com.gitee.sop.gatewaycommon.manager.RouteConfigManager;
-import com.gitee.sop.gatewaycommon.message.ErrorEnum;
import com.gitee.sop.gatewaycommon.param.ApiParam;
import com.gitee.sop.gatewaycommon.zuul.ZuulContext;
import org.springframework.cloud.netflix.zuul.filters.Route;
@@ -17,6 +13,7 @@ import java.util.stream.Collectors;
/**
* 路由定位
+ *
* @author tanghc
*/
public class SopRouteLocator implements RouteLocator, Ordered {
@@ -34,7 +31,7 @@ public class SopRouteLocator implements RouteLocator, Ordered {
@Override
public List getRoutes() {
- return zuulRouteRepository.listAll()
+ return zuulRouteRepository.getAll()
.parallelStream()
.map(zuulTargetRoute -> zuulTargetRoute.getTargetRouteDefinition())
.collect(Collectors.toList());
@@ -42,8 +39,9 @@ public class SopRouteLocator implements RouteLocator, Ordered {
/**
* 这里决定使用哪个路由
+ *
* @param path
- * @return
+ * @return 返回跳转的路由
*/
@Override
public Route getMatchingRoute(String path) {
@@ -53,12 +51,6 @@ public class SopRouteLocator implements RouteLocator, Ordered {
if (zuulTargetRoute == null) {
return null;
}
- // 路由是否启用
- RouteConfigManager routeConfigManager = ApiConfig.getInstance().getRouteConfigManager();
- RouteConfig routeConfig = routeConfigManager.get(zuulTargetRoute.getRouteDefinition().getId());
- if (!routeConfig.enable()) {
- throw ErrorEnum.ISP_API_DISABLED.getErrorMeta().getException();
- }
return zuulTargetRoute.getTargetRouteDefinition();
}
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/route/ZuulRouteRepository.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/route/ZuulRouteRepository.java
index 6ecdc6ea..4f62544f 100644
--- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/route/ZuulRouteRepository.java
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/route/ZuulRouteRepository.java
@@ -19,35 +19,36 @@ public class ZuulRouteRepository implements RouteRepository {
/**
* key:nameVersion
*/
- private Map nameVersionServiceIdMap = new ConcurrentHashMap<>(128);
-
- public List listAll() {
- return new ArrayList<>(nameVersionServiceIdMap.values());
- }
+ private Map nameVersionTargetRouteMap = new ConcurrentHashMap<>(128);
@Override
public ZuulTargetRoute get(String id) {
- ZuulTargetRoute route = nameVersionServiceIdMap.get(id);
+ ZuulTargetRoute route = nameVersionTargetRouteMap.get(id);
if (route == null) {
throw ErrorEnum.ISV_INVALID_METHOD.getErrorMeta().getException();
}
return route;
}
+ @Override
+ public Collection getAll() {
+ return nameVersionTargetRouteMap.values();
+ }
+
@Override
public String add(ZuulTargetRoute targetRoute) {
- nameVersionServiceIdMap.put(targetRoute.getRouteDefinition().getId(), targetRoute);
- return null;
+ nameVersionTargetRouteMap.put(targetRoute.getRouteDefinition().getId(), targetRoute);
+ return targetRoute.getRouteDefinition().getId();
}
@Override
public void update(ZuulTargetRoute targetRoute) {
- nameVersionServiceIdMap.put(targetRoute.getRouteDefinition().getId(), targetRoute);
+ nameVersionTargetRouteMap.put(targetRoute.getRouteDefinition().getId(), targetRoute);
}
@Override
public void deleteAll(String serviceId) {
- Collection values = nameVersionServiceIdMap.values();
+ Collection values = nameVersionTargetRouteMap.values();
List idList = values.stream()
.map(zuulTargetRoute -> zuulTargetRoute.getRouteDefinition().getId())
.collect(Collectors.toList());
@@ -59,6 +60,6 @@ public class ZuulRouteRepository implements RouteRepository {
@Override
public void delete(String id) {
- nameVersionServiceIdMap.remove(id);
+ nameVersionTargetRouteMap.remove(id);
}
}
diff --git a/sop-common/sop-service-common/pom.xml b/sop-common/sop-service-common/pom.xml
index 689053ee..78e6b080 100644
--- a/sop-common/sop-service-common/pom.xml
+++ b/sop-common/sop-service-common/pom.xml
@@ -9,9 +9,8 @@
1.2.0-SNAPSHOT
../pom.xml
- com.gitee.sop
sop-service-common
- ${parent.version}
+ 1.2.0-SNAPSHOT
jar
sop-service-common
diff --git a/sop-gateway/src/main/java/com/gitee/sop/gateway/config/ZuulConfig.java b/sop-gateway/src/main/java/com/gitee/sop/gateway/config/ZuulConfig.java
index 63bd1ad8..5c481ef6 100644
--- a/sop-gateway/src/main/java/com/gitee/sop/gateway/config/ZuulConfig.java
+++ b/sop-gateway/src/main/java/com/gitee/sop/gateway/config/ZuulConfig.java
@@ -9,7 +9,9 @@ import com.gitee.sop.gatewaycommon.manager.IsvRoutePermissionManager;
import com.gitee.sop.gatewaycommon.secret.IsvManager;
import com.gitee.sop.gatewaycommon.zuul.configuration.AlipayZuulConfiguration;
import com.gitee.sop.gatewaycommon.zuul.configuration.TaobaoZuulConfiguration;
+import com.gitee.sop.gatewaycommon.zuul.filter.PreLimitFilter;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.HashMap;
@@ -44,6 +46,7 @@ public class ZuulConfig extends AlipayZuulConfiguration {
protected void doAfter() {
managerInitializer.init();
}
+
}
/**
diff --git a/sop-gateway/src/main/java/com/gitee/sop/gateway/entity/ConfigRouteLimit.java b/sop-gateway/src/main/java/com/gitee/sop/gateway/entity/ConfigRouteLimit.java
index 8926bc43..da4584e5 100644
--- a/sop-gateway/src/main/java/com/gitee/sop/gateway/entity/ConfigRouteLimit.java
+++ b/sop-gateway/src/main/java/com/gitee/sop/gateway/entity/ConfigRouteLimit.java
@@ -28,8 +28,8 @@ public class ConfigRouteLimit {
/** 路由id, 数据库字段:route_id */
private String routeId;
- /** 限流策略,1:漏桶策略,2:令牌桶策略, 数据库字段:type */
- private Byte type;
+ /** 限流策略,1:漏桶策略,2:令牌桶策略, 数据库字段:limit_type */
+ private Byte limitType;
/** 每秒可处理请求数, 数据库字段:exec_count_per_second */
private Integer execCountPerSecond;
diff --git a/sop-gateway/src/main/java/com/gitee/sop/gateway/manager/DbRouteConfigManager.java b/sop-gateway/src/main/java/com/gitee/sop/gateway/manager/DbRouteConfigManager.java
index a76e78cd..670d18c1 100644
--- a/sop-gateway/src/main/java/com/gitee/sop/gateway/manager/DbRouteConfigManager.java
+++ b/sop-gateway/src/main/java/com/gitee/sop/gateway/manager/DbRouteConfigManager.java
@@ -4,18 +4,21 @@ import com.alibaba.fastjson.JSON;
import com.gitee.fastmybatis.core.query.Query;
import com.gitee.sop.gateway.mapper.ConfigRouteBaseMapper;
import com.gitee.sop.gateway.mapper.ConfigRouteLimitMapper;
+import com.gitee.sop.gatewaycommon.bean.BaseRouteDefinition;
import com.gitee.sop.gatewaycommon.bean.ChannelMsg;
import com.gitee.sop.gatewaycommon.bean.RouteConfig;
import com.gitee.sop.gatewaycommon.bean.RouteConfigDto;
+import com.gitee.sop.gatewaycommon.bean.TargetRoute;
import com.gitee.sop.gatewaycommon.manager.DefaultRouteConfigManager;
+import com.gitee.sop.gatewaycommon.manager.RouteRepositoryContext;
import com.gitee.sop.gatewaycommon.manager.ZookeeperContext;
-import com.gitee.sop.gatewaycommon.util.MyBeanUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
+import java.util.Collection;
/**
* @author tanghc
@@ -35,6 +38,8 @@ public class DbRouteConfigManager extends DefaultRouteConfigManager {
@Override
public void load() {
+ loadAllRoute();
+
Query query = new Query();
configRouteBaseMapper.list(query)
@@ -53,10 +58,24 @@ public class DbRouteConfigManager extends DefaultRouteConfigManager {
}
- protected void putVal(String key, Object object) {
- RouteConfig routeConfig = routeConfigMap.getOrDefault(key, newRouteConfig());
- MyBeanUtil.copyPropertiesIgnoreNull(object, routeConfig);
- routeConfigMap.put(key, routeConfig);
+ protected void loadAllRoute() {
+ Collection extends TargetRoute> targetRoutes = RouteRepositoryContext.getRouteRepository().getAll();
+ targetRoutes.stream()
+ .forEach(targetRoute -> {
+ BaseRouteDefinition routeDefinition = targetRoute.getRouteDefinition();
+ initRouteConfig(routeDefinition);
+ });
+ }
+
+ protected void initRouteConfig(BaseRouteDefinition routeDefinition) {
+ String routeId = routeDefinition.getId();
+ RouteConfig routeConfig = newRouteConfig();
+ routeConfig.setRouteId(routeId);
+ routeConfigMap.put(routeId, routeConfig);
+ }
+
+ protected void putVal(String routeId, Object object) {
+ this.doUpdate(routeId, object);
}
diff --git a/sop-test/src/test/java/com/gitee/sop/LimitDemoPostTest.java b/sop-test/src/test/java/com/gitee/sop/LimitDemoPostTest.java
new file mode 100644
index 00000000..2fb2e50f
--- /dev/null
+++ b/sop-test/src/test/java/com/gitee/sop/LimitDemoPostTest.java
@@ -0,0 +1,80 @@
+package com.gitee.sop;
+
+import com.alibaba.fastjson.JSON;
+import com.gitee.sop.alipay.AlipaySignature;
+import org.junit.Test;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * 限流测试
+ */
+public class LimitDemoPostTest extends TestBase {
+
+ String url = "http://localhost:8081/api"; // zuul
+ String appId = "2019032617262200001";
+ // 支付宝私钥
+ String privateKey = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCXJv1pQFqWNA/++OYEV7WYXwexZK/J8LY1OWlP9X0T6wHFOvxNKRvMkJ5544SbgsJpVcvRDPrcxmhPbi/sAhdO4x2PiPKIz9Yni2OtYCCeaiE056B+e1O2jXoLeXbfi9fPivJZkxH/tb4xfLkH3bA8ZAQnQsoXA0SguykMRZntF0TndUfvDrLqwhlR8r5iRdZLB6F8o8qXH6UPDfNEnf/K8wX5T4EB1b8x8QJ7Ua4GcIUqeUxGHdQpzNbJdaQvoi06lgccmL+PHzminkFYON7alj1CjDN833j7QMHdPtS9l7B67fOU/p2LAAkPMtoVBfxQt9aFj7B8rEhGCz02iJIBAgMBAAECggEARqOuIpY0v6WtJBfmR3lGIOOokLrhfJrGTLF8CiZMQha+SRJ7/wOLPlsH9SbjPlopyViTXCuYwbzn2tdABigkBHYXxpDV6CJZjzmRZ+FY3S/0POlTFElGojYUJ3CooWiVfyUMhdg5vSuOq0oCny53woFrf32zPHYGiKdvU5Djku1onbDU0Lw8w+5tguuEZ76kZ/lUcccGy5978FFmYpzY/65RHCpvLiLqYyWTtaNT1aQ/9pw4jX9HO9NfdJ9gYFK8r/2f36ZE4hxluAfeOXQfRC/WhPmiw/ReUhxPznG/WgKaa/OaRtAx3inbQ+JuCND7uuKeRe4osP2jLPHPP6AUwQKBgQDUNu3BkLoKaimjGOjCTAwtp71g1oo+k5/uEInAo7lyEwpV0EuUMwLA/HCqUgR4K9pyYV+Oyb8d6f0+Hz0BMD92I2pqlXrD7xV2WzDvyXM3s63NvorRooKcyfd9i6ccMjAyTR2qfLkxv0hlbBbsPHz4BbU63xhTJp3Ghi0/ey/1HQKBgQC2VsgqC6ykfSidZUNLmQZe3J0p/Qf9VLkfrQ+xaHapOs6AzDU2H2osuysqXTLJHsGfrwVaTs00ER2z8ljTJPBUtNtOLrwNRlvgdnzyVAKHfOgDBGwJgiwpeE9voB1oAV/mXqSaUWNnuwlOIhvQEBwekqNyWvhLqC7nCAIhj3yvNQKBgQCqYbeec56LAhWP903Zwcj9VvG7sESqXUhIkUqoOkuIBTWFFIm54QLTA1tJxDQGb98heoCIWf5x/A3xNI98RsqNBX5JON6qNWjb7/dobitti3t99v/ptDp9u8JTMC7penoryLKK0Ty3bkan95Kn9SC42YxaSghzqkt+uvfVQgiNGQKBgGxU6P2aDAt6VNwWosHSe+d2WWXt8IZBhO9d6dn0f7ORvcjmCqNKTNGgrkewMZEuVcliueJquR47IROdY8qmwqcBAN7Vg2K7r7CPlTKAWTRYMJxCT1Hi5gwJb+CZF3+IeYqsJk2NF2s0w5WJTE70k1BSvQsfIzAIDz2yE1oPHvwVAoGAA6e+xQkVH4fMEph55RJIZ5goI4Y76BSvt2N5OKZKd4HtaV+eIhM3SDsVYRLIm9ZquJHMiZQGyUGnsvrKL6AAVNK7eQZCRDk9KQz+0GKOGqku0nOZjUbAu6A2/vtXAaAuFSFx1rUQVVjFulLexkXR3KcztL1Qu2k5pB6Si0K/uwQ=";
+
+ @Test
+ public void testLimit() throws InterruptedException {
+ int threadsCount = 10; // threadsCount个线程同时提交
+ final CountDownLatch countDownLatch = new CountDownLatch(1);
+ final CountDownLatch count = new CountDownLatch(threadsCount);
+ final AtomicInteger success = new AtomicInteger();
+ for (int i = 0; i < threadsCount; i++) {
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ countDownLatch.await(); // 等在这里,执行countDownLatch.countDown();集体触发
+ // 业务方法
+ doBusiness(Thread.currentThread().getName());
+ success.incrementAndGet();
+ } catch (Exception e) {
+ } finally {
+ count.countDown();
+ }
+ }
+ }).start();
+ }
+ countDownLatch.countDown();
+ count.await();
+ System.out.println("成功次数:" + success);
+ }
+
+ // 这个请求会路由到story服务
+ public void doBusiness(String threadName) throws Exception {
+
+ // 公共请求参数
+ Map params = new HashMap();
+ params.put("app_id", appId);
+ params.put("method", "alipay.story.get");
+ params.put("format", "json");
+ params.put("charset", "utf-8");
+ params.put("sign_type", "RSA2");
+ params.put("timestamp", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
+ params.put("version", "1.2");
+
+ // 业务参数
+ Map bizContent = new HashMap<>();
+ bizContent.put("id", "1");
+ bizContent.put("name", "葫芦娃");
+
+ params.put("biz_content", JSON.toJSONString(bizContent));
+
+ String content = AlipaySignature.getSignContent(params);
+ String sign = AlipaySignature.rsa256Sign(content, privateKey, "utf-8");
+
+ params.put("sign", sign);
+
+ String responseData = post(url, params);// 发送请求
+ System.out.println(responseData);
+ }
+
+}