From 994b48616331398afa9bd8945296974246fabe1c Mon Sep 17 00:00:00 2001 From: tanghc Date: Fri, 10 Jan 2020 14:02:21 +0800 Subject: [PATCH 01/55] =?UTF-8?q?=E4=BB=A3=E7=A0=81=E8=BD=AC=E7=A7=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../configuration/BaseZuulConfiguration.java | 20 +++++++++++- .../WebappZuulConfiguration.java | 1 + .../controller/ConfigChannelController.java | 32 +++++++++---------- .../zuul}/controller/ErrorLogController.java | 5 +-- .../zuul}/controller/RestServlet.java | 4 +-- .../zuul}/controller/ZuulIndexController.java | 31 +++++++++++++++--- 6 files changed, 68 insertions(+), 25 deletions(-) rename {sop-gateway/src/main/java/com/gitee/sop/gateway => sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul}/controller/ConfigChannelController.java (72%) rename {sop-gateway/src/main/java/com/gitee/sop/gateway => sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul}/controller/ErrorLogController.java (95%) rename {sop-gateway/src/main/java/com/gitee/sop/gateway => sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul}/controller/RestServlet.java (94%) rename {sop-gateway/src/main/java/com/gitee/sop/gateway => sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul}/controller/ZuulIndexController.java (65%) 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 ecc2f54f..3b6dbc9f 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 @@ -6,14 +6,17 @@ import com.gitee.sop.gatewaycommon.manager.AbstractConfiguration; import com.gitee.sop.gatewaycommon.manager.RouteRepositoryContext; import com.gitee.sop.gatewaycommon.param.ParamBuilder; import com.gitee.sop.gatewaycommon.zuul.ValidateService; +import com.gitee.sop.gatewaycommon.zuul.controller.ConfigChannelController; +import com.gitee.sop.gatewaycommon.zuul.controller.ErrorLogController; +import com.gitee.sop.gatewaycommon.zuul.controller.ZuulIndexController; import com.gitee.sop.gatewaycommon.zuul.filter.ErrorFilter; import com.gitee.sop.gatewaycommon.zuul.filter.FormBodyWrapperFilterExt; import com.gitee.sop.gatewaycommon.zuul.filter.PostResultFilter; +import com.gitee.sop.gatewaycommon.zuul.filter.PreEnvGrayFilter; import com.gitee.sop.gatewaycommon.zuul.filter.PreHttpServletRequestWrapperFilter; import com.gitee.sop.gatewaycommon.zuul.filter.PreLimitFilter; import com.gitee.sop.gatewaycommon.zuul.filter.PreParameterFormatterFilter; import com.gitee.sop.gatewaycommon.zuul.filter.PreValidateFilter; -import com.gitee.sop.gatewaycommon.zuul.filter.PreEnvGrayFilter; import com.gitee.sop.gatewaycommon.zuul.filter.Servlet30WrapperFilterExt; import com.gitee.sop.gatewaycommon.zuul.route.SopRouteLocator; import com.gitee.sop.gatewaycommon.zuul.route.ZuulRouteCache; @@ -39,6 +42,21 @@ public class BaseZuulConfiguration extends AbstractConfiguration { @Autowired protected ServerProperties server; + @Bean + public ConfigChannelController configChannelController() { + return new ConfigChannelController(); + } + + @Bean + public ErrorLogController errorLogController() { + return new ErrorLogController(); + } + + @Bean + public ZuulIndexController zuulIndexController() { + return new ZuulIndexController(); + } + @Bean @ConditionalOnMissingBean ParamBuilder paramBuilder() { diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/configuration/WebappZuulConfiguration.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/configuration/WebappZuulConfiguration.java index ff16de63..1517226e 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/configuration/WebappZuulConfiguration.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/configuration/WebappZuulConfiguration.java @@ -8,6 +8,7 @@ import com.gitee.sop.gatewaycommon.result.CustomDataNameBuilder; * * @author tanghc */ +@Deprecated public class WebappZuulConfiguration extends BaseZuulConfiguration { static { diff --git a/sop-gateway/src/main/java/com/gitee/sop/gateway/controller/ConfigChannelController.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/controller/ConfigChannelController.java similarity index 72% rename from sop-gateway/src/main/java/com/gitee/sop/gateway/controller/ConfigChannelController.java rename to sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/controller/ConfigChannelController.java index b6a96478..2f1acd07 100644 --- a/sop-gateway/src/main/java/com/gitee/sop/gateway/controller/ConfigChannelController.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/controller/ConfigChannelController.java @@ -1,21 +1,21 @@ -package com.gitee.sop.gateway.controller; +package com.gitee.sop.gatewaycommon.zuul.controller; import com.alibaba.fastjson.JSON; -import com.gitee.sop.gateway.manager.DbEnvGrayManager; -import com.gitee.sop.gateway.manager.DbIPBlacklistManager; -import com.gitee.sop.gateway.manager.DbIsvManager; -import com.gitee.sop.gateway.manager.DbIsvRoutePermissionManager; -import com.gitee.sop.gateway.manager.DbLimitConfigManager; -import com.gitee.sop.gateway.manager.DbRouteConfigManager; import com.gitee.sop.gatewaycommon.bean.GatewayPushDTO; import com.gitee.sop.gatewaycommon.bean.NacosConfigs; import com.gitee.sop.gatewaycommon.bean.SpringContext; import com.gitee.sop.gatewaycommon.manager.ChannelMsgProcessor; +import com.gitee.sop.gatewaycommon.manager.EnvGrayManager; +import com.gitee.sop.gatewaycommon.manager.IPBlacklistManager; +import com.gitee.sop.gatewaycommon.manager.IsvRoutePermissionManager; +import com.gitee.sop.gatewaycommon.manager.LimitConfigManager; +import com.gitee.sop.gatewaycommon.manager.RouteConfigManager; +import com.gitee.sop.gatewaycommon.secret.IsvManager; import com.gitee.sop.gatewaycommon.util.RequestUtil; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpServletRequest; import java.io.IOException; @@ -26,24 +26,24 @@ import java.util.Map; * @author tanghc */ @Slf4j -@RestController +@Controller public class ConfigChannelController { private static Map> processorMap = new HashMap<>(16); static { - processorMap.put(NacosConfigs.GROUP_CHANNEL + NacosConfigs.DATA_ID_GRAY, DbEnvGrayManager.class); - processorMap.put(NacosConfigs.GROUP_CHANNEL + NacosConfigs.DATA_ID_IP_BLACKLIST, DbIPBlacklistManager.class); - processorMap.put(NacosConfigs.GROUP_CHANNEL + NacosConfigs.DATA_ID_ISV, DbIsvManager.class); - processorMap.put(NacosConfigs.GROUP_CHANNEL + NacosConfigs.DATA_ID_ROUTE_PERMISSION, DbIsvRoutePermissionManager.class); - processorMap.put(NacosConfigs.GROUP_CHANNEL + NacosConfigs.DATA_ID_LIMIT_CONFIG, DbLimitConfigManager.class); - processorMap.put(NacosConfigs.GROUP_CHANNEL + NacosConfigs.DATA_ID_ROUTE_CONFIG, DbRouteConfigManager.class); + processorMap.put(NacosConfigs.GROUP_CHANNEL + NacosConfigs.DATA_ID_GRAY, EnvGrayManager.class); + processorMap.put(NacosConfigs.GROUP_CHANNEL + NacosConfigs.DATA_ID_IP_BLACKLIST, IPBlacklistManager.class); + processorMap.put(NacosConfigs.GROUP_CHANNEL + NacosConfigs.DATA_ID_ISV, IsvManager.class); + processorMap.put(NacosConfigs.GROUP_CHANNEL + NacosConfigs.DATA_ID_ROUTE_PERMISSION, IsvRoutePermissionManager.class); + processorMap.put(NacosConfigs.GROUP_CHANNEL + NacosConfigs.DATA_ID_LIMIT_CONFIG, LimitConfigManager.class); + processorMap.put(NacosConfigs.GROUP_CHANNEL + NacosConfigs.DATA_ID_ROUTE_CONFIG, RouteConfigManager.class); } @Value("${zuul.secret}") private String secret; - @PostMapping("/configChannelMsg") + @PostMapping("/sop/configChannelMsg") public String configChannel(HttpServletRequest request) throws IOException { String requestJson = RequestUtil.getText(request); String sign = request.getHeader("sign"); diff --git a/sop-gateway/src/main/java/com/gitee/sop/gateway/controller/ErrorLogController.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/controller/ErrorLogController.java similarity index 95% rename from sop-gateway/src/main/java/com/gitee/sop/gateway/controller/ErrorLogController.java rename to sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/controller/ErrorLogController.java index 93ab0dc6..3c773afb 100644 --- a/sop-gateway/src/main/java/com/gitee/sop/gateway/controller/ErrorLogController.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/controller/ErrorLogController.java @@ -1,4 +1,4 @@ -package com.gitee.sop.gateway.controller; +package com.gitee.sop.gatewaycommon.zuul.controller; import com.gitee.sop.gatewaycommon.bean.ApiConfig; import com.gitee.sop.gatewaycommon.bean.ErrorEntity; @@ -9,6 +9,7 @@ import com.gitee.sop.gatewaycommon.result.JsonResult; import com.gitee.sop.gatewaycommon.util.RequestUtil; import com.gitee.sop.gatewaycommon.validate.taobao.TaobaoSigner; import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @@ -19,7 +20,7 @@ import java.util.Map; /** * @author tanghc */ -@RestController +@Controller public class ErrorLogController { TaobaoSigner signer = new TaobaoSigner(); diff --git a/sop-gateway/src/main/java/com/gitee/sop/gateway/controller/RestServlet.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/controller/RestServlet.java similarity index 94% rename from sop-gateway/src/main/java/com/gitee/sop/gateway/controller/RestServlet.java rename to sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/controller/RestServlet.java index b6baadbb..1a1a484e 100644 --- a/sop-gateway/src/main/java/com/gitee/sop/gateway/controller/RestServlet.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/controller/RestServlet.java @@ -1,4 +1,4 @@ -package com.gitee.sop.gateway.controller; +package com.gitee.sop.gatewaycommon.zuul.controller; import com.gitee.sop.gatewaycommon.bean.SopConstants; import org.springframework.beans.factory.annotation.Value; @@ -14,7 +14,7 @@ import java.io.IOException; * 传统web开发入口 * @author tanghc */ -@WebServlet(urlPatterns = "/rest/*") +//@WebServlet(urlPatterns = "/rest/*") public class RestServlet extends HttpServlet { private static final String EMPTY_VERSION = ""; diff --git a/sop-gateway/src/main/java/com/gitee/sop/gateway/controller/ZuulIndexController.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/controller/ZuulIndexController.java similarity index 65% rename from sop-gateway/src/main/java/com/gitee/sop/gateway/controller/ZuulIndexController.java rename to sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/controller/ZuulIndexController.java index 86d01ef9..ac1606e4 100644 --- a/sop-gateway/src/main/java/com/gitee/sop/gateway/controller/ZuulIndexController.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/controller/ZuulIndexController.java @@ -1,4 +1,4 @@ -package com.gitee.sop.gateway.controller; +package com.gitee.sop.gatewaycommon.zuul.controller; import com.gitee.sop.gatewaycommon.bean.SopConstants; import com.gitee.sop.gatewaycommon.zuul.ValidateService; @@ -9,8 +9,10 @@ import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; +import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import java.io.IOException; /** * zuul网关入口 @@ -21,12 +23,17 @@ import javax.servlet.http.HttpServletResponse; @Controller public class ZuulIndexController { + private static final String EMPTY_VERSION = ""; + @Autowired private ValidateService validateService; @Value("${zuul.servlet-path:/zuul}") private String path; + @Value("${sop.restful.path:/rest}") + private String restPath; + /** * 验证回调,可自定义实现接口 */ @@ -49,6 +56,25 @@ public class ZuulIndexController { validateService.validate(request, response, callback); } + /** + * restful入口 + * @param request + * @param response + * @throws ServletException + * @throws IOException + */ + @RequestMapping("/rest/**") + public void rest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + String url = request.getRequestURL().toString(); + int index = url.indexOf(restPath); + // 取/rest的后面部分 + String path = url.substring(index + restPath.length()); + request.setAttribute(SopConstants.REDIRECT_METHOD_KEY, path); + request.setAttribute(SopConstants.REDIRECT_VERSION_KEY, EMPTY_VERSION); + request.setAttribute(SopConstants.SOP_NOT_MERGE, true); + request.getRequestDispatcher(this.path).forward(request, response); + } + @RequestMapping("/{method}/{version}/") public void redirect( @PathVariable("method") String method @@ -60,7 +86,4 @@ public class ZuulIndexController { request.setAttribute(SopConstants.REDIRECT_VERSION_KEY, version); validateService.validate(request, response, callback); } - - - } From 3d0a940b2c5799cd65b3620838a9ca14f01a86b1 Mon Sep 17 00:00:00 2001 From: tanghc Date: Fri, 10 Jan 2020 18:20:29 +0800 Subject: [PATCH 02/55] =?UTF-8?q?=E7=BD=91=E5=85=B3=E4=BA=8C=E5=90=88?= =?UTF-8?q?=E4=B8=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../files/10096_使用SpringCloudGateway.md | 90 +------- doc/docs/files/10110_预发布灰度发布.md | 10 +- .../sop/adminserver/api/service/LogApi.java | 8 +- .../service/ConfigPushService.java | 9 +- .../main/resources/application-dev.properties | 2 +- sop-common/pom.xml | 4 +- sop-common/sop-bridge-gateway/pom.xml | 35 +++ .../bridge/SopGatewayAutoConfiguration.java | 12 ++ .../src/main/resources/sop-bridge.properties | 25 +++ sop-common/sop-bridge-zuul/pom.xml | 31 +++ .../bridge/SopGatewayAutoConfiguration.java | 14 ++ .../src/main/resources/sop-bridge.properties | 27 +++ .../sop/gatewaycommon/bean/ApiConfig.java | 9 +- .../bean/BaseErrorLogController.java | 64 ++++++ .../env/SopEnvironmentPostProcessor.java | 39 ++++ .../gateway/ServerWebExchangeUtil.java | 177 ++++++++++----- .../BaseGatewayConfiguration.java | 115 +++------- .../controller/ConfigChannelController.java | 75 +++++++ .../controller/ErrorLogController.java | 21 ++ .../gateway/controller/GatewayController.java | 43 ++++ .../gateway/filter/EnvGrayFilter.java | 2 +- .../gateway/filter/IndexFilter.java | 153 +++++++++++++ .../filter/LoadBalancerClientExtFilter.java | 58 ----- .../gateway/filter/ValidateFilter.java | 48 ----- .../handler/GatewayExceptionHandler.java | 47 ++-- .../gateway/param/GatewayParamBuilder.java | 27 --- .../gateway/result/GatewayResultExecutor.java | 16 +- .../gateway/route/GatewayRouteCache.java | 38 +--- .../gateway/route/GatewayRouteRepository.java | 45 ++-- .../NameVersionRoutePredicateFactory.java | 105 --------- .../route/ReadBodyRoutePredicateFactory.java | 202 ------------------ .../gatewaycommon/manager/BaseRouteCache.java | 21 +- .../manager/RouteRepository.java | 5 + .../manager/RouteRepositoryContext.java | 4 +- .../sop/gatewaycommon/param/ApiParam.java | 10 + .../result/BaseExecutorAdapter.java | 31 +-- .../gatewaycommon/validate/ApiValidator.java | 10 +- .../configuration/BaseZuulConfiguration.java | 3 +- .../configuration/ZuulErrorController.java | 18 +- .../controller/ConfigChannelController.java | 5 +- .../zuul/controller/ErrorLogController.java | 61 +----- .../zuul/controller/RestServlet.java | 45 ---- .../zuul/result/ZuulResultExecutor.java | 4 +- .../main/resources/META-INF/spring.factories | 3 + .../storyweb/controller/AlipayController.java | 7 +- .../controller/FileUploadDemoController.java | 2 +- .../controller/result/FileUploadResult.java | 1 + sop-gateway/pom.xml | 29 +-- .../sop/gateway/SopGatewayApplication.java | 6 - .../sop/gateway/config/GatewayConfig.java | 1 + .../gitee/sop/gateway/config/ZuulConfig.java | 2 +- .../main/resources/application-dev.properties | 45 +--- .../com/gitee/sop/sdk/client/OpenRequest.java | 2 +- 53 files changed, 857 insertions(+), 1009 deletions(-) create mode 100644 sop-common/sop-bridge-gateway/pom.xml create mode 100644 sop-common/sop-bridge-gateway/src/main/java/com/gitee/sop/bridge/SopGatewayAutoConfiguration.java create mode 100644 sop-common/sop-bridge-gateway/src/main/resources/sop-bridge.properties create mode 100644 sop-common/sop-bridge-zuul/pom.xml create mode 100644 sop-common/sop-bridge-zuul/src/main/java/com/gitee/sop/bridge/SopGatewayAutoConfiguration.java create mode 100644 sop-common/sop-bridge-zuul/src/main/resources/sop-bridge.properties create mode 100644 sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/BaseErrorLogController.java create mode 100644 sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/env/SopEnvironmentPostProcessor.java create mode 100644 sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/controller/ConfigChannelController.java create mode 100644 sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/controller/ErrorLogController.java create mode 100644 sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/controller/GatewayController.java create mode 100644 sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/IndexFilter.java delete mode 100644 sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/LoadBalancerClientExtFilter.java delete mode 100644 sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/ValidateFilter.java delete mode 100644 sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/param/GatewayParamBuilder.java delete mode 100644 sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/route/NameVersionRoutePredicateFactory.java delete mode 100644 sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/route/ReadBodyRoutePredicateFactory.java delete mode 100644 sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/controller/RestServlet.java create mode 100644 sop-common/sop-gateway-common/src/main/resources/META-INF/spring.factories diff --git a/doc/docs/files/10096_使用SpringCloudGateway.md b/doc/docs/files/10096_使用SpringCloudGateway.md index dc74bbc6..cdad27e0 100644 --- a/doc/docs/files/10096_使用SpringCloudGateway.md +++ b/doc/docs/files/10096_使用SpringCloudGateway.md @@ -1,92 +1,16 @@ # 使用SpringCloudGateway -SOP默认网关是使用Spring Cloud Zuul,您也可以切换成Spring Cloud Gateway,完整代码见`spring-cloud-gateway`分支。 - -如果您的系统并发量不大,建议使用zuul,因为zuul的功能更全面,有新功能会优先实现在zuul上。 - -- SOP中 Spring Cloud Zuul 和 Spring Cloud Gateway功能对比 - -| 功能 | Spring Cloud Zuul | Spring Cloud Gateway | -| ----- | ---- | ----------------------- | -| 签名验证|√ | √ | -| 统一异常处理|√ | √ | -| 统一返回内容|√ | √ | -| session管理|√ | √ | -| 秘钥管理|√ | √ | -| 微服务端自动验证(JSR-303)|√ | √ | -| 文件上传|√ | √ | -| 文件下载|√ | √ | -| 接口限流|√ | √ | -| 文档整合|√ | √ | -| 应用授权|√ | √ | -| 监控日志|√ | √ | -| 支持nacos|√ | √ | -| 网关动态修改参数|√ | √ | - -使用Spring Cloud Gateway步骤如下: - -- 打开sop-gateway/pom.xml,注释spring cloud zuul依赖,打开Spring Cloud Gateway依赖 +修改`sop-gateway/pom.xml`配置,artifactId部分改成`sop-bridge-gateway`即可 ```xml - - - - - - - org.springframework.cloud - spring-cloud-starter-gateway - - org.springframework.boot - spring-boot-starter-webflux + com.gitee.sop + + + + sop-bridge-gateway + 2.5.10-SNAPSHOT - - org.springframework.boot - spring-boot-starter-actuator - - - -``` - -- 打开启动类`SopGatewayApplication.java`, 注释zuul相关注解 - -```java -package com.gitee.sop.gateway; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -//import org.springframework.cloud.netflix.zuul.EnableZuulProxy; - -// 开启网关功能 -//@EnableZuulProxy -@SpringBootApplication -public class SopGatewayApplication { - - public static void main(String[] args) { - SpringApplication.run(SopGatewayApplication.class, args); - } - -} -``` - -- 禁用ZuulConfig类,注释掉@Configuration注解即可 - -```java -//@Configuration -public class ZuulConfig extends AlipayZuulConfiguration {...} -``` - -- 启用GatewayConfig类,打开@Configuration注释 - -```java -@Configuration -public class GatewayConfig extends AlipayGatewayConfiguration {...} ``` 修改完毕,重启sop-gateway diff --git a/doc/docs/files/10110_预发布灰度发布.md b/doc/docs/files/10110_预发布灰度发布.md index 74370b5c..f850baee 100644 --- a/doc/docs/files/10110_预发布灰度发布.md +++ b/doc/docs/files/10110_预发布灰度发布.md @@ -11,7 +11,7 @@ |open1.domain.com |网关服务器1 | |openpre.domain.com | 网关服务器2,作为预发布请求入口| -线上网关入口为`http://open.domain.com/api`,请求网关`http://open.domain.com/api`会负载均衡到这两台服务器 +线上网关入口为`http://open.domain.com/`,请求网关`http://open.domain.com/`会负载均衡到这两台服务器 SOP开启预发布步骤如下: @@ -26,18 +26,16 @@ pre.domain=openpre.domain.com 微服务启动参数添加:`--spring.cloud.nacos.discovery.metadata.env=pre`(eureka下是:`--eureka.instance.metadata-map.env=pre`)。 建议线上配两套启动脚本,其中预发布启动脚本添加启动参数`--eureka.instance.metadata-map.env=pre` -登录SOP-Admin,在服务列表中点击预发布,然后预发布请求地址变成:`http://openpre.domain.com/api`。 +登录SOP-Admin,在服务列表中点击预发布,然后预发布请求地址变成:`http://openpre.domain.com/`。 从`openpre.domain.com`请求进来的用户都会进预发布服务器,其它情况都走非预发布服务器。 ## 使用灰度发布 灰度发布可允许指定的用户访问灰度服务器,其它用户还是走正常流程。 -微服务启动参数添加:`--spring.cloud.nacos.discovery.metadata.env=gray`(eureka下是:`--eureka.instance.metadata-map.env=gray`)。 +登录SOP-Admin,前往`服务列表`。 -登录SOP-Admin,前往服务列表。 - -- 先设置灰度参数,指定灰度用户和灰度接口 +- 先设置灰度参数,指定灰度appId和灰度接口 - 服务器实例开启灰度 参考类: diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/LogApi.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/LogApi.java index 9b16cf4e..e59d49c7 100644 --- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/LogApi.java +++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/LogApi.java @@ -41,13 +41,15 @@ public class LogApi { public static final String LOG_MONITOR_INSTANCE = "log.monitor.instance"; public static final String CODE_SUCCESS = "10000"; private static final String CODE_KEY = "code"; + public static final String SOP_LIST_ERRORS_PATH = "/sop/listErrors"; + public static final String SOP_CLEAR_ERRORS_PATH = "/sop/clearErrors"; @Autowired ConfigCommonMapper configCommonMapper; RestTemplate restTemplate = new RestTemplate(); - @Value("${zuul.secret}") + @Value("${sop.secret}") private String secret; @Api(name = "monitor.log.list") @@ -66,7 +68,7 @@ public class LogApi { logMonitorInstanceVOParent.setMonitorName(configCommon.getContent()); ret.add(logMonitorInstanceVOParent); try { - String logData = this.requestLogServer(ipPort, "listErrors"); + String logData = this.requestLogServer(ipPort, SOP_LIST_ERRORS_PATH); JSONObject jsonObject = JSON.parseObject(logData); if (CODE_SUCCESS.equals(jsonObject.getString("code"))) { int errorTotal = 0; @@ -97,7 +99,7 @@ public class LogApi { } try { String ipPort = configCommon.getConfigKey(); - this.requestLogServer(ipPort, "clearErrors"); + this.requestLogServer(ipPort, SOP_CLEAR_ERRORS_PATH); } catch (Exception e) { throw new BizException("清除失败"); } diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/service/ConfigPushService.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/service/ConfigPushService.java index d5f2d023..c2b0e943 100644 --- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/service/ConfigPushService.java +++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/service/ConfigPushService.java @@ -29,7 +29,7 @@ import java.util.stream.Stream; @Service public class ConfigPushService { - private static final String GATEWAY_PUSH_URL = "http://%s/configChannelMsg"; + private static final String GATEWAY_PUSH_URL = "http://%s/sop/configChannelMsg"; private static final String API_GATEWAY_SERVICE_ID = "sop-gateway"; private static HttpTool httpTool = new HttpTool(); @@ -40,7 +40,7 @@ public class ConfigPushService { @Value("${gateway.host:}") private String gatewayHost; - @Value("${zuul.secret}") + @Value("${sop.secret}") private String secret; public void publishConfig(String dataId, String groupId, ChannelMsg channelMsg) { @@ -59,6 +59,11 @@ public class ConfigPushService { private void pushByHost(Collection hosts, GatewayPushDTO gatewayPushDTO) { for (String host : hosts) { String url = String.format(GATEWAY_PUSH_URL, host); + log.info("推送配置, dataId={}, groupId={}, operation={}, url={}", + gatewayPushDTO.getDataId() + , gatewayPushDTO.getGroupId() + , gatewayPushDTO.getChannelMsg().getOperation() + , url); try { String requestBody = JSON.toJSONString(gatewayPushDTO); Map header = new HashMap<>(8); diff --git a/sop-admin/sop-admin-server/src/main/resources/application-dev.properties b/sop-admin/sop-admin-server/src/main/resources/application-dev.properties index d3995efc..2588e1a7 100644 --- a/sop-admin/sop-admin-server/src/main/resources/application-dev.properties +++ b/sop-admin/sop-admin-server/src/main/resources/application-dev.properties @@ -38,4 +38,4 @@ mybatis.fill.com.gitee.fastmybatis.core.support.DateFillInsert=gmt_create mybatis.fill.com.gitee.fastmybatis.core.support.DateFillUpdate=gmt_modified # 不用改,如果要改,请全局替换修改 -zuul.secret=MZZOUSTua6LzApIWXCwEgbBmxSzpzC +sop.secret=MZZOUSTua6LzApIWXCwEgbBmxSzpzC diff --git a/sop-common/pom.xml b/sop-common/pom.xml index 98e0cf7c..09743364 100644 --- a/sop-common/pom.xml +++ b/sop-common/pom.xml @@ -36,7 +36,9 @@ sop-gateway-common sop-service-common - + sop-bridge-zuul + sop-bridge-gateway + diff --git a/sop-common/sop-bridge-gateway/pom.xml b/sop-common/sop-bridge-gateway/pom.xml new file mode 100644 index 00000000..328eaf22 --- /dev/null +++ b/sop-common/sop-bridge-gateway/pom.xml @@ -0,0 +1,35 @@ + + + + sop-common + com.gitee.sop + 2.5.10-SNAPSHOT + + 4.0.0 + 2.5.10-SNAPSHOT + + sop-bridge-gateway + + + + com.gitee.sop + sop-gateway-common + 2.5.10-SNAPSHOT + + + + org.springframework.cloud + spring-cloud-starter-gateway + + + org.springframework.boot + spring-boot-starter-webflux + + + org.springframework.boot + spring-boot-starter-actuator + + + \ No newline at end of file diff --git a/sop-common/sop-bridge-gateway/src/main/java/com/gitee/sop/bridge/SopGatewayAutoConfiguration.java b/sop-common/sop-bridge-gateway/src/main/java/com/gitee/sop/bridge/SopGatewayAutoConfiguration.java new file mode 100644 index 00000000..d38488fd --- /dev/null +++ b/sop-common/sop-bridge-gateway/src/main/java/com/gitee/sop/bridge/SopGatewayAutoConfiguration.java @@ -0,0 +1,12 @@ +package com.gitee.sop.bridge; + +import com.gitee.sop.gatewaycommon.gateway.configuration.AlipayGatewayConfiguration; +import org.springframework.context.annotation.Import; + +/** + * https://blog.csdn.net/seashouwang/article/details/80299571 + * @author tanghc + */ +@Import(AlipayGatewayConfiguration.class) +public class SopGatewayAutoConfiguration { +} diff --git a/sop-common/sop-bridge-gateway/src/main/resources/sop-bridge.properties b/sop-common/sop-bridge-gateway/src/main/resources/sop-bridge.properties new file mode 100644 index 00000000..c3106eb8 --- /dev/null +++ b/sop-common/sop-bridge-gateway/src/main/resources/sop-bridge.properties @@ -0,0 +1,25 @@ +# 不用改,如果要改,请全局替换修改 +sop.secret=MZZOUSTua6LzApIWXCwEgbBmxSzpzC + +# https://blog.csdn.net/qq_36872046/article/details/81058045 +# 路由转发超时时间,毫秒,默认值1000,详见:RibbonClientConfiguration.DEFAULT_READ_TIMEOUT。 +# 如果微服务端 处理时间过长,会导致ribbon read超时,解决办法将这个值调大一点 +ribbon.ReadTimeout=2000 +# 设置为true(默认false),则所有请求都重试,默认只支持get请求重试 +# 请谨慎设置,因为post请求大多都是写入请求,如果要支持重试,确保服务的幂等性 +ribbon.OkToRetryOnAllOperations=false + +spring.cloud.gateway.discovery.locator.lower-case-service-id=true +spring.cloud.gateway.discovery.locator.enabled=true + +# 不用改 +mybatis.fill.com.gitee.fastmybatis.core.support.DateFillInsert=gmt_create +mybatis.fill.com.gitee.fastmybatis.core.support.DateFillUpdate=gmt_modified + +# 文件上传配置 +spring.servlet.multipart.enabled=true +# 这里设置大一点没关系,真实大小由upload.max-file-size控制 +spring.servlet.multipart.max-file-size=50MB + +# 允许上传文件大小,不能超过这个值,单位:B,KB,MB +upload.max-file-size=2MB \ No newline at end of file diff --git a/sop-common/sop-bridge-zuul/pom.xml b/sop-common/sop-bridge-zuul/pom.xml new file mode 100644 index 00000000..1fa813b4 --- /dev/null +++ b/sop-common/sop-bridge-zuul/pom.xml @@ -0,0 +1,31 @@ + + + + sop-common + com.gitee.sop + 2.5.10-SNAPSHOT + + 4.0.0 + 2.5.10-SNAPSHOT + + sop-bridge-zuul + + + + com.gitee.sop + sop-gateway-common + 2.5.10-SNAPSHOT + + + + org.springframework.cloud + spring-cloud-starter-netflix-zuul + + + org.springframework.retry + spring-retry + + + \ No newline at end of file diff --git a/sop-common/sop-bridge-zuul/src/main/java/com/gitee/sop/bridge/SopGatewayAutoConfiguration.java b/sop-common/sop-bridge-zuul/src/main/java/com/gitee/sop/bridge/SopGatewayAutoConfiguration.java new file mode 100644 index 00000000..05762ea2 --- /dev/null +++ b/sop-common/sop-bridge-zuul/src/main/java/com/gitee/sop/bridge/SopGatewayAutoConfiguration.java @@ -0,0 +1,14 @@ +package com.gitee.sop.bridge; + +import com.gitee.sop.gatewaycommon.zuul.configuration.AlipayZuulConfiguration; +import org.springframework.cloud.netflix.zuul.EnableZuulProxy; +import org.springframework.context.annotation.Import; + +/** + * https://blog.csdn.net/seashouwang/article/details/80299571 + * @author tanghc + */ +@EnableZuulProxy +@Import(AlipayZuulConfiguration.class) +public class SopGatewayAutoConfiguration { +} diff --git a/sop-common/sop-bridge-zuul/src/main/resources/sop-bridge.properties b/sop-common/sop-bridge-zuul/src/main/resources/sop-bridge.properties new file mode 100644 index 00000000..3a83a34f --- /dev/null +++ b/sop-common/sop-bridge-zuul/src/main/resources/sop-bridge.properties @@ -0,0 +1,27 @@ +# 入口地址,不用改,默认是/zuul +zuul.servlet-path=/api +# 禁用默认的过滤器,不能删,不用改 +zuul.FormBodyWrapperFilter.pre.disable=true +zuul.Servlet30WrapperFilter.pre.disable=true +# 不用改,如果要改,请全局替换修改 +sop.secret=MZZOUSTua6LzApIWXCwEgbBmxSzpzC + +# https://blog.csdn.net/qq_36872046/article/details/81058045 +# 路由转发超时时间,毫秒,默认值1000,详见:RibbonClientConfiguration.DEFAULT_READ_TIMEOUT。 +# 如果微服务端 处理时间过长,会导致ribbon read超时,解决办法将这个值调大一点 +ribbon.ReadTimeout=2000 +# 设置为true(默认false),则所有请求都重试,默认只支持get请求重试 +# 请谨慎设置,因为post请求大多都是写入请求,如果要支持重试,确保服务的幂等性 +ribbon.OkToRetryOnAllOperations=false + +# 不用改 +mybatis.fill.com.gitee.fastmybatis.core.support.DateFillInsert=gmt_create +mybatis.fill.com.gitee.fastmybatis.core.support.DateFillUpdate=gmt_modified + +# 文件上传配置 +spring.servlet.multipart.enabled=true +# 这里设置大一点没关系,真实大小由upload.max-file-size控制 +spring.servlet.multipart.max-file-size=50MB + +# 允许上传文件大小,不能超过这个值,单位:B,KB,MB +upload.max-file-size=2MB 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 34ee0bb1..d348be42 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 @@ -1,7 +1,5 @@ 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; @@ -60,7 +58,7 @@ public class ApiConfig { /** * gateway合并结果处理 */ - private ResultExecutor gatewayResultExecutor = new GatewayResultExecutor(); + private ResultExecutor gatewayResultExecutor = new GatewayResultExecutor(); /** * zuul合并结果处理 @@ -82,11 +80,6 @@ public class ApiConfig { */ private Signer signer = new ApiSigner(); - /** - * 参数解析,gateway - */ - private ParamBuilder gatewayParamBuilder = new GatewayParamBuilder(); - /** * 参数解析,zuul */ diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/BaseErrorLogController.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/BaseErrorLogController.java new file mode 100644 index 00000000..3505efc0 --- /dev/null +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/BaseErrorLogController.java @@ -0,0 +1,64 @@ +package com.gitee.sop.gatewaycommon.bean; + +import com.gitee.sop.gatewaycommon.manager.ServiceErrorManager; +import com.gitee.sop.gatewaycommon.param.ApiParam; +import com.gitee.sop.gatewaycommon.result.ApiResult; +import com.gitee.sop.gatewaycommon.result.JsonResult; +import com.gitee.sop.gatewaycommon.validate.taobao.TaobaoSigner; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.web.bind.annotation.GetMapping; + +import java.util.Collection; + +/** + * @author tanghc + */ +public abstract class BaseErrorLogController { + + TaobaoSigner signer = new TaobaoSigner(); + + @Value("${sop.secret}") + private String secret; + + protected abstract ApiParam getApiParam(T t); + + @GetMapping("/sop/listErrors") + public ApiResult listErrors(T request) { + try { + this.check(request); + ServiceErrorManager serviceErrorManager = ApiConfig.getInstance().getServiceErrorManager(); + Collection allErrors = serviceErrorManager.listAllErrors(); + JsonResult apiResult = new JsonResult(); + apiResult.setData(allErrors); + return apiResult; + } catch (Exception e) { + ApiResult apiResult = new ApiResult(); + apiResult.setCode("505050"); + apiResult.setMsg(e.getMessage()); + return apiResult; + } + } + + @GetMapping("/sop/clearErrors") + public ApiResult clearErrors(T request) { + try { + this.check(request); + ServiceErrorManager serviceErrorManager = ApiConfig.getInstance().getServiceErrorManager(); + serviceErrorManager.clear(); + return new ApiResult(); + } catch (Exception e) { + ApiResult apiResult = new ApiResult(); + apiResult.setCode("505050"); + apiResult.setMsg(e.getMessage()); + return apiResult; + } + } + + protected void check(T request) { + ApiParam apiParam = getApiParam(request); + boolean right = signer.checkSign(apiParam, secret); + if (!right) { + throw new RuntimeException("签名校验失败"); + } + } +} diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/env/SopEnvironmentPostProcessor.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/env/SopEnvironmentPostProcessor.java new file mode 100644 index 00000000..a4122b3a --- /dev/null +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/env/SopEnvironmentPostProcessor.java @@ -0,0 +1,39 @@ +package com.gitee.sop.gatewaycommon.env; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.env.EnvironmentPostProcessor; +import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.core.env.PropertiesPropertySource; +import org.springframework.core.env.PropertySource; +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; + +import java.io.IOException; +import java.util.Properties; + +/** + * 自定义环境处理,在运行SpringApplication之前加载任意配置文件到Environment环境中 + */ +public class SopEnvironmentPostProcessor implements EnvironmentPostProcessor { + + private final Properties properties = new Properties(); + + @Override + public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) { + Resource resource = new ClassPathResource("sop-bridge.properties"); + // 加载成PropertySource对象,并添加到Environment环境中 + environment.getPropertySources().addLast(loadProfiles(resource)); + } + + private PropertySource loadProfiles(Resource resource) { + if (resource == null || !resource.exists()) { + throw new IllegalArgumentException("资源" + resource + "不存在"); + } + try { + properties.load(resource.getInputStream()); + return new PropertiesPropertySource(resource.getFilename(), properties); + } catch (IOException ex) { + throw new IllegalStateException("加载配置文件失败" + resource, ex); + } + } +} diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/ServerWebExchangeUtil.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/ServerWebExchangeUtil.java index 688db17e..631fe2b4 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/ServerWebExchangeUtil.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/ServerWebExchangeUtil.java @@ -1,6 +1,7 @@ package com.gitee.sop.gatewaycommon.gateway; import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; import com.gitee.sop.gatewaycommon.bean.SopConstants; import com.gitee.sop.gatewaycommon.gateway.common.FileUploadHttpServletRequest; import com.gitee.sop.gatewaycommon.gateway.common.RequestContentDataExtractor; @@ -13,107 +14,177 @@ import org.apache.commons.lang3.StringUtils; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.MediaType; +import org.springframework.http.codec.HttpMessageReader; import org.springframework.http.converter.FormHttpMessageConverter; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.util.MultiValueMap; import org.springframework.web.multipart.MultipartHttpServletRequest; import org.springframework.web.multipart.commons.CommonsMultipartResolver; +import org.springframework.web.reactive.function.server.HandlerStrategies; +import org.springframework.web.reactive.function.server.ServerRequest; import org.springframework.web.server.ServerWebExchange; +import org.springframework.web.server.WebFilterChain; +import reactor.core.publisher.Mono; import javax.servlet.http.HttpServletRequest; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.util.Collections; -import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.function.Consumer; -import static com.gitee.sop.gatewaycommon.bean.SopConstants.CACHE_REQUEST_BODY_FOR_MAP; -import static com.gitee.sop.gatewaycommon.bean.SopConstants.CACHE_REQUEST_BODY_OBJECT_KEY; - /** * @author tanghc */ @Slf4j public class ServerWebExchangeUtil { + private static final String UNKNOWN_PATH = "/sop/unknown"; + private static final String VALIDATE_ERROR_PATH = "/sop/validateError"; + private static final String REST_PATH = "/rest"; + private static FormHttpMessageConverter formHttpMessageConverter = new FormHttpMessageConverter(); + private static final List> messageReaders; + + static { + messageReaders = HandlerStrategies.withDefaults().messageReaders(); + } + /** - * 获取请求参数 + * 重定向 * - * @param exchange ServerWebExchange - * @return 返回请求参数 + * @param exchange exchange + * @param apiParam apiParam + * @return 返回新的ServerWebExchange,配合chain.filter(newExchange);使用 */ - public static ApiParam getApiParam(ServerWebExchange exchange) { - return exchange.getAttribute(SopConstants.CACHE_API_PARAM); + public static ServerWebExchange getForwardExchange(ServerWebExchange exchange, ApiParam apiParam) { + ServerHttpRequest newRequest = getForwardRequest(exchange.getRequest(), apiParam); + return exchange.mutate().request(newRequest).build(); + } + + public static ServerHttpRequest getForwardRequest(ServerHttpRequest request, ApiParam apiParam) { + return request + .mutate() + .header(SopConstants.REDIRECT_VERSION_KEY, apiParam.fetchVersion()) + .path(getForwardPath(apiParam)).build(); } /** - * 设置请求参数 + * 构建一个接受请求体的request * - * @param exchange ServerWebExchange - * @param apiParam 请求参数 + * @param exchange exchange + * @return 返回ServerRequest */ - public static void setApiParam(ServerWebExchange exchange, ApiParam apiParam) { - exchange.getAttributes().put(SopConstants.CACHE_API_PARAM, apiParam); + public static ServerRequest createReadBodyRequest(ServerWebExchange exchange) { + return ServerRequest.create(exchange, messageReaders); + } + + public static ServerWebExchange getRestfulExchange(ServerWebExchange exchange, String path) { + int index = path.indexOf(REST_PATH); + // 取"/rest"的后面部分 + String newPath = path.substring(index + REST_PATH.length()); + ApiParam apiParam = new ApiParam(); + apiParam.setName(newPath); + apiParam.setVersion(""); + setApiParam(exchange, apiParam); + return getForwardExchange(exchange, newPath); } /** - * 获取Spring Cloud Gateway请求的原始参数。前提是要使用ReadBodyRoutePredicateFactory + * 重定向 * - * @param exchange ServerWebExchange - * @return 没有参数返回null - * @see com.gitee.sop.gatewaycommon.gateway.route.ReadBodyRoutePredicateFactory + * @param exchange exchange + * @param forwardPath 重定向path + * @return 返回新的ServerWebExchange,配合chain.filter(newExchange);使用 */ - public static ApiParam getRequestParams(ServerWebExchange exchange) { - ApiParam apiParamExist = exchange.getAttribute(CACHE_REQUEST_BODY_FOR_MAP); - if (apiParamExist != null) { - return apiParamExist; + public static ServerWebExchange getForwardExchange(ServerWebExchange exchange, String forwardPath) { + ServerHttpRequest newRequest = exchange.getRequest() + .mutate() + .path(forwardPath).build(); + return exchange.mutate().request(newRequest).build(); + } + + public static Mono forwardUnknown(ServerWebExchange exchange, WebFilterChain chain) { + // 非法访问 + ServerWebExchange newExchange = ServerWebExchangeUtil.getForwardExchange(exchange, UNKNOWN_PATH); + return chain.filter(newExchange); + } + + private static String getForwardPath(ApiParam apiParam) { + // 如果有异常,则重定向到这个path + if (apiParam.getThrowable() != null) { + return VALIDATE_ERROR_PATH; + } + String forwardPath = UNKNOWN_PATH; + String method = apiParam.fetchName(); + if (org.springframework.util.StringUtils.hasText(method)) { + forwardPath = "/" + method + "/"; + } + return forwardPath; + } + + public static ApiParam getApiParam(ServerWebExchange exchange, String body) { + MediaType contentType = exchange.getRequest().getHeaders().getContentType(); + if (contentType == null) { + contentType = MediaType.APPLICATION_FORM_URLENCODED; } ApiParam apiParam = new ApiParam(); + String ip = Optional.ofNullable(exchange.getRequest().getRemoteAddress()) + .map(address -> address.getAddress().getHostAddress()) + .orElse(""); + apiParam.setIp(ip); Map params = null; - if (exchange.getRequest().getMethod() == HttpMethod.GET) { - MultiValueMap queryParams = exchange.getRequest().getQueryParams(); - params = buildParams(queryParams); + String contentTypeStr = contentType.toString().toLowerCase(); + // 如果是json方式提交 + if (StringUtils.containsAny(contentTypeStr, "json", "text")) { + JSONObject jsonObject = JSON.parseObject(body); + apiParam.putAll(jsonObject); + } else if (StringUtils.containsIgnoreCase(contentTypeStr, "multipart")) { + // 如果是文件上传请求 + HttpServletRequest fileUploadRequest = getFileUploadRequest(exchange, body); + setFileUploadRequest(exchange, fileUploadRequest); + RequestUtil.UploadInfo uploadInfo = RequestUtil.getUploadInfo(fileUploadRequest); + params = uploadInfo.getUploadParams(); + apiParam.setUploadContext(uploadInfo.getUploadContext()); } else { - String cachedBody = exchange.getAttribute(CACHE_REQUEST_BODY_OBJECT_KEY); - if (cachedBody != null) { - MediaType contentType = exchange.getRequest().getHeaders().getContentType(); - String contentTypeStr = contentType == null ? "" : contentType.toString().toLowerCase(); - // 如果是json方式提交 - if (StringUtils.containsAny(contentTypeStr, "json", "text")) { - params = JSON.parseObject(cachedBody); - } else if (StringUtils.containsIgnoreCase(contentTypeStr, "multipart")) { - // 如果是文件上传请求 - HttpServletRequest fileUploadRequest = getFileUploadRequest(exchange, cachedBody); - setFileUploadRequest(exchange, fileUploadRequest); - RequestUtil.UploadInfo uploadInfo = RequestUtil.getUploadInfo(fileUploadRequest); - params = uploadInfo.getUploadParams(); - apiParam.setUploadContext(uploadInfo.getUploadContext()); - } else { - params = RequestUtil.parseQueryToMap(cachedBody); - } - } + // APPLICATION_FORM_URLENCODED请求 + params = RequestUtil.parseQueryToMap(body); } if (params != null) { apiParam.putAll(params); - exchange.getAttributes().put(CACHE_REQUEST_BODY_FOR_MAP, apiParam); } + setApiParam(exchange, apiParam); return apiParam; } + public static ApiParam getApiParam(ServerWebExchange exchange, Map params) { + ApiParam apiParam = new ApiParam(); + apiParam.putAll(params); + setApiParam(exchange, apiParam); + return apiParam; + } - public static Map buildParams(MultiValueMap queryParams) { - if (queryParams == null || queryParams.size() == 0) { - return null; - } - Map params = new HashMap<>(queryParams.size()); - for (Map.Entry> entry : queryParams.entrySet()) { - params.put(entry.getKey(), entry.getValue().get(0)); - } - return params; + /** + * 获取请求参数 + * + * @param exchange ServerWebExchange + * @return 返回请求参数 + */ + public static ApiParam getApiParam(ServerWebExchange exchange) { + return exchange.getAttribute(SopConstants.CACHE_API_PARAM); + } + + /** + * 设置请求参数 + * + * @param exchange ServerWebExchange + * @param apiParam 请求参数 + */ + public static void setApiParam(ServerWebExchange exchange, ApiParam apiParam) { + exchange.getAttributes().put(SopConstants.CACHE_API_PARAM, apiParam); } /** 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 7df72e6f..d5d2375f 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 @@ -1,47 +1,29 @@ package com.gitee.sop.gatewaycommon.gateway.configuration; import com.gitee.sop.gatewaycommon.bean.ApiConfig; +import com.gitee.sop.gatewaycommon.gateway.controller.ConfigChannelController; +import com.gitee.sop.gatewaycommon.gateway.controller.ErrorLogController; +import com.gitee.sop.gatewaycommon.gateway.controller.GatewayController; import com.gitee.sop.gatewaycommon.gateway.filter.EnvGrayFilter; import com.gitee.sop.gatewaycommon.gateway.filter.GatewayModifyResponseGatewayFilter; +import com.gitee.sop.gatewaycommon.gateway.filter.IndexFilter; import com.gitee.sop.gatewaycommon.gateway.filter.LimitFilter; -import com.gitee.sop.gatewaycommon.gateway.filter.LoadBalancerClientExtFilter; import com.gitee.sop.gatewaycommon.gateway.filter.ParameterFormatterFilter; -import com.gitee.sop.gatewaycommon.gateway.filter.ValidateFilter; import com.gitee.sop.gatewaycommon.gateway.handler.GatewayExceptionHandler; import com.gitee.sop.gatewaycommon.gateway.route.GatewayRouteCache; import com.gitee.sop.gatewaycommon.gateway.route.GatewayRouteRepository; -import com.gitee.sop.gatewaycommon.gateway.route.NameVersionRoutePredicateFactory; -import com.gitee.sop.gatewaycommon.gateway.route.ReadBodyRoutePredicateFactory; import com.gitee.sop.gatewaycommon.manager.AbstractConfiguration; import com.gitee.sop.gatewaycommon.manager.RouteRepositoryContext; -import com.gitee.sop.gatewaycommon.param.ParamBuilder; -import com.gitee.sop.gatewaycommon.param.ParamNames; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.ObjectProvider; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Primary; import org.springframework.core.Ordered; import org.springframework.core.annotation.Order; -import org.springframework.core.io.buffer.DataBuffer; -import org.springframework.core.io.buffer.DefaultDataBufferFactory; import org.springframework.http.codec.ServerCodecConfigurer; -import org.springframework.util.MultiValueMap; -import org.springframework.web.reactive.function.BodyInserters; -import org.springframework.web.reactive.function.server.RequestPredicate; -import org.springframework.web.reactive.function.server.RequestPredicates; -import org.springframework.web.reactive.function.server.RouterFunction; -import org.springframework.web.reactive.function.server.RouterFunctions; -import org.springframework.web.reactive.function.server.ServerResponse; import org.springframework.web.reactive.result.view.ViewResolver; -import org.springframework.web.server.ServerWebExchange; -import reactor.core.publisher.Mono; -import java.net.URI; import java.util.Collections; import java.util.List; @@ -56,8 +38,25 @@ public class BaseGatewayConfiguration extends AbstractConfiguration { ApiConfig.getInstance().setUseGateway(true); } - @Value("${sop.restful.path:/rest}") - private String restPath; + @Bean + public IndexFilter indexFilter() { + return new IndexFilter(); + } + + @Bean + public GatewayController gatewayErrorController() { + return new GatewayController(); + } + + @Bean + public ConfigChannelController configChannelController() { + return new ConfigChannelController(); + } + + @Bean + public ErrorLogController errorLogController() { + return new ErrorLogController(); + } /** * 自定义异常处理[@@]注册Bean时依赖的Bean,会从容器中直接获取,所以直接注入即可 @@ -68,7 +67,7 @@ public class BaseGatewayConfiguration extends AbstractConfiguration { @Primary @Bean @Order(Ordered.HIGHEST_PRECEDENCE) - public ErrorWebExceptionHandler errorWebExceptionHandler(ObjectProvider> viewResolversProvider, + public ErrorWebExceptionHandler sopErrorWebExceptionHandler(ObjectProvider> viewResolversProvider, ServerCodecConfigurer serverCodecConfigurer) { GatewayExceptionHandler jsonExceptionHandler = new GatewayExceptionHandler(); @@ -78,12 +77,6 @@ public class BaseGatewayConfiguration extends AbstractConfiguration { return jsonExceptionHandler; } - @Bean - @ConditionalOnMissingBean - ParamBuilder paramBuilder() { - return ApiConfig.getInstance().getGatewayParamBuilder(); - } - /** * 处理返回结果 */ @@ -92,24 +85,6 @@ public class BaseGatewayConfiguration extends AbstractConfiguration { return new GatewayModifyResponseGatewayFilter(); } - /** - * 读取post请求参数 - */ - @Bean - ReadBodyRoutePredicateFactory readBodyRoutePredicateFactory() { - return new ReadBodyRoutePredicateFactory(); - } - - @Bean - NameVersionRoutePredicateFactory paramRoutePredicateFactory() { - return new NameVersionRoutePredicateFactory(); - } - - @Bean - ValidateFilter validateFilter() { - return new ValidateFilter(); - } - @Bean ParameterFormatterFilter parameterFormatterFilter() { return new ParameterFormatterFilter(); @@ -120,11 +95,6 @@ public class BaseGatewayConfiguration extends AbstractConfiguration { return new LimitFilter(); } - @Bean - LoadBalancerClientExtFilter loadBalancerClientExtFilter() { - return new LoadBalancerClientExtFilter(); - } - @Bean GatewayRouteCache gatewayRouteCache(GatewayRouteRepository gatewayRouteRepository) { return new GatewayRouteCache(gatewayRouteRepository); @@ -143,41 +113,4 @@ public class BaseGatewayConfiguration extends AbstractConfiguration { return new EnvGrayFilter(); } - /** - * 307 Temporary Redirect(临时重定向): - *

- * 在这种情况下,请求应该与另一个URI重复,但后续的请求应仍使用原始的URI。 - * 与302相反,当重新发出原始请求时,不允许更改请求方法。 例如,应该使用另一个POST请求来重复POST请求 - *

- * 308 Permanent Redirect (永久重定向): - *

- * 请求和所有将来的请求应该使用另一个URI重复。 - * 307和308重复302和301的行为,但不允许HTTP方法更改。 例如,将表单提交给永久重定向的资源可能会顺利进行。 - *

- * https://www.cnblogs.com/wuguanglin/p/redirect.html - * - * @return - */ - @Bean - @ConditionalOnProperty(value = "sop.restful.enable", havingValue = "true") - RouterFunction routerFunction() { - RequestPredicate requestPredicate = RequestPredicates.all() - .and(RequestPredicates.path(restPath + "/**")); - return RouterFunctions.route(requestPredicate, (serverRequest) -> { - String path = serverRequest.path(); - int index = path.indexOf(restPath); - // 取/rest的后面部分 - String servletPath = path.substring(index + restPath.length()); - String query = serverRequest.uri().getQuery(); - String appendQuery = ParamNames.API_NAME + "=" + servletPath + "&" + ParamNames.VERSION_NAME + "="; - if (StringUtils.isBlank(query)) { - query = appendQuery; - } else { - query += '&' + appendQuery; - } - return ServerResponse - .temporaryRedirect(URI.create("/?" + query)) - .build(); - }); - } } diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/controller/ConfigChannelController.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/controller/ConfigChannelController.java new file mode 100644 index 00000000..1ccc64e1 --- /dev/null +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/controller/ConfigChannelController.java @@ -0,0 +1,75 @@ +package com.gitee.sop.gatewaycommon.gateway.controller; + +import com.alibaba.fastjson.JSON; +import com.gitee.sop.gatewaycommon.bean.GatewayPushDTO; +import com.gitee.sop.gatewaycommon.bean.NacosConfigs; +import com.gitee.sop.gatewaycommon.bean.SpringContext; +import com.gitee.sop.gatewaycommon.gateway.ServerWebExchangeUtil; +import com.gitee.sop.gatewaycommon.manager.ChannelMsgProcessor; +import com.gitee.sop.gatewaycommon.manager.EnvGrayManager; +import com.gitee.sop.gatewaycommon.manager.IPBlacklistManager; +import com.gitee.sop.gatewaycommon.manager.IsvRoutePermissionManager; +import com.gitee.sop.gatewaycommon.manager.LimitConfigManager; +import com.gitee.sop.gatewaycommon.manager.RouteConfigManager; +import com.gitee.sop.gatewaycommon.secret.IsvManager; +import com.gitee.sop.gatewaycommon.util.RequestUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.reactive.function.server.ServerRequest; +import org.springframework.web.server.ServerWebExchange; +import reactor.core.publisher.Mono; + +import java.util.HashMap; +import java.util.Map; + +/** + * @author tanghc + */ +@Slf4j +@RestController +public class ConfigChannelController { + + private static Map> processorMap = new HashMap<>(16); + + static { + processorMap.put(NacosConfigs.GROUP_CHANNEL + NacosConfigs.DATA_ID_GRAY, EnvGrayManager.class); + processorMap.put(NacosConfigs.GROUP_CHANNEL + NacosConfigs.DATA_ID_IP_BLACKLIST, IPBlacklistManager.class); + processorMap.put(NacosConfigs.GROUP_CHANNEL + NacosConfigs.DATA_ID_ISV, IsvManager.class); + processorMap.put(NacosConfigs.GROUP_CHANNEL + NacosConfigs.DATA_ID_ROUTE_PERMISSION, IsvRoutePermissionManager.class); + processorMap.put(NacosConfigs.GROUP_CHANNEL + NacosConfigs.DATA_ID_LIMIT_CONFIG, LimitConfigManager.class); + processorMap.put(NacosConfigs.GROUP_CHANNEL + NacosConfigs.DATA_ID_ROUTE_CONFIG, RouteConfigManager.class); + } + + @Value("${sop.secret}") + private String secret; + + @PostMapping("/sop/configChannelMsg") + public Mono configChannel(ServerWebExchange exchange) { + ServerRequest serverRequest = ServerWebExchangeUtil.createReadBodyRequest(exchange); + // 读取请求体中的内容 + return serverRequest.bodyToMono(String.class) + .flatMap(requestJson -> { + String sign = exchange.getRequest().getHeaders().getFirst("sign"); + try { + // 签名验证 + RequestUtil.checkResponseBody(requestJson, sign, secret); + } catch (Exception e) { + log.error("configChannelMsg错误", e); + return Mono.just(e.getMessage()); + } + GatewayPushDTO gatewayPushDTO = JSON.parseObject(requestJson, GatewayPushDTO.class); + ChannelMsgProcessor channelMsgProcessor = getChannelMsgProcessor(gatewayPushDTO); + channelMsgProcessor.process(gatewayPushDTO.getChannelMsg()); + return Mono.just("ok"); + }); + } + + private ChannelMsgProcessor getChannelMsgProcessor(GatewayPushDTO gatewayPushDTO) { + String key = gatewayPushDTO.getGroupId() + gatewayPushDTO.getDataId(); + Class aClass = processorMap.get(key); + return SpringContext.getBean(aClass); + } + +} diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/controller/ErrorLogController.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/controller/ErrorLogController.java new file mode 100644 index 00000000..978e533a --- /dev/null +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/controller/ErrorLogController.java @@ -0,0 +1,21 @@ +package com.gitee.sop.gatewaycommon.gateway.controller; + +import com.gitee.sop.gatewaycommon.bean.BaseErrorLogController; +import com.gitee.sop.gatewaycommon.param.ApiParam; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.server.ServerWebExchange; + +import java.util.Map; + +/** + * @author tanghc + */ +@RestController +public class ErrorLogController extends BaseErrorLogController { + + @Override + protected ApiParam getApiParam(ServerWebExchange request) { + Map params = request.getRequest().getQueryParams().toSingleValueMap(); + return ApiParam.build(params); + } +} diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/controller/GatewayController.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/controller/GatewayController.java new file mode 100644 index 00000000..c67c4a19 --- /dev/null +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/controller/GatewayController.java @@ -0,0 +1,43 @@ +package com.gitee.sop.gatewaycommon.gateway.controller; + +import com.gitee.sop.gatewaycommon.bean.ApiContext; +import com.gitee.sop.gatewaycommon.exception.ApiException; +import com.gitee.sop.gatewaycommon.gateway.ServerWebExchangeUtil; +import com.gitee.sop.gatewaycommon.message.ErrorEnum; +import com.gitee.sop.gatewaycommon.param.ApiParam; +import com.gitee.sop.gatewaycommon.result.ResultExecutor; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.server.ServerWebExchange; +import reactor.core.publisher.Mono; + +/** + * @author tanghc + */ +@RestController +public class GatewayController { + + /** + * 处理签名错误返回 + * + * @param exchange exchange + * @return 返回最终结果 + */ + @RequestMapping("/sop/validateError") + public Mono validateError(ServerWebExchange exchange) { + ApiParam apiParam = ServerWebExchangeUtil.getApiParam(exchange); + // 合并微服务传递过来的结果,变成最终结果 + ResultExecutor resultExecutor = ApiContext.getApiConfig().getGatewayResultExecutor(); + String gatewayResult = resultExecutor.buildErrorResult(exchange, apiParam.getThrowable()); + return Mono.just(gatewayResult); + } + + @RequestMapping("/sop/unknown") + public Mono unknown(ServerWebExchange exchange) { + ApiException exception = ErrorEnum.ISV_INVALID_METHOD.getErrorMeta().getException(); + ResultExecutor resultExecutor = ApiContext.getApiConfig().getGatewayResultExecutor(); + String gatewayResult = resultExecutor.buildErrorResult(exchange, exception); + return Mono.just(gatewayResult); + } + +} diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/EnvGrayFilter.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/EnvGrayFilter.java index 38c9aebe..9c0f9fd0 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/EnvGrayFilter.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/EnvGrayFilter.java @@ -27,7 +27,7 @@ public class EnvGrayFilter implements GlobalFilter, Ordered { String nameVersion = apiParam.fetchNameVersion(); TargetRoute targetRoute = RouteRepositoryContext.getRouteRepository().get(nameVersion); if (targetRoute == null) { - return null; + return chain.filter(exchange); } String serviceId = targetRoute.getServiceRouteInfo().fetchServiceIdLowerCase(); // 如果服务在灰度阶段,返回一个灰度版本号 diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/IndexFilter.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/IndexFilter.java new file mode 100644 index 00000000..9b380231 --- /dev/null +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/IndexFilter.java @@ -0,0 +1,153 @@ +package com.gitee.sop.gatewaycommon.gateway.filter; + +import com.gitee.sop.gatewaycommon.bean.SopConstants; +import com.gitee.sop.gatewaycommon.exception.ApiException; +import com.gitee.sop.gatewaycommon.gateway.ServerWebExchangeUtil; +import com.gitee.sop.gatewaycommon.manager.EnvironmentContext; +import com.gitee.sop.gatewaycommon.manager.EnvironmentKeys; +import com.gitee.sop.gatewaycommon.param.ApiParam; +import com.gitee.sop.gatewaycommon.validate.Validator; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cloud.gateway.support.BodyInserterContext; +import org.springframework.cloud.gateway.support.CachedBodyOutputMessage; +import org.springframework.core.Ordered; +import org.springframework.core.annotation.Order; +import org.springframework.core.io.buffer.DataBuffer; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.codec.HttpMessageReader; +import org.springframework.http.server.reactive.ServerHttpRequest; +import org.springframework.http.server.reactive.ServerHttpRequestDecorator; +import org.springframework.web.reactive.function.BodyInserter; +import org.springframework.web.reactive.function.BodyInserters; +import org.springframework.web.reactive.function.server.HandlerStrategies; +import org.springframework.web.reactive.function.server.ServerRequest; +import org.springframework.web.server.ServerWebExchange; +import org.springframework.web.server.WebFilter; +import org.springframework.web.server.WebFilterChain; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +import java.net.URI; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; + +/** + * 入口 + * + * @author tanghc + */ +@Slf4j +@Order(Ordered.HIGHEST_PRECEDENCE) +public class IndexFilter implements WebFilter { + + private static final String INDEX_PATH = "/"; + private static final String REST_PATH_PREFIX = "/rest"; + private static final String SOP_PATH_PREFIX = "/sop"; + + @Autowired + private Validator validator; + + @Override + public Mono filter(ServerWebExchange exchange, WebFilterChain chain) { + ServerHttpRequest request = exchange.getRequest(); + String path = request.getURI().getPath(); + // SOP路径,直接放行 + if (path.startsWith(SOP_PATH_PREFIX)) { + return chain.filter(exchange); + } + // 如果是restful请求,直接转发 + if (path.startsWith(REST_PATH_PREFIX)) { + String sopRestfulEnableValue = EnvironmentKeys.SOP_RESTFUL_ENABLE.getValue(); + if (!Objects.equals("true", sopRestfulEnableValue)) { + log.error("尝试调用restful请求,但sop.restful.enable未开启"); + return ServerWebExchangeUtil.forwardUnknown(exchange, chain); + } + ServerWebExchange newExchange = ServerWebExchangeUtil.getRestfulExchange(exchange, path); + return chain.filter(newExchange); + } + if (Objects.equals(path, INDEX_PATH)) { + if (request.getMethod() == HttpMethod.POST) { + ServerRequest serverRequest = ServerWebExchangeUtil.createReadBodyRequest(exchange); + // 读取请求体中的内容 + Mono modifiedBody = serverRequest.bodyToMono(String.class) + .flatMap(body -> { + // 构建ApiParam + ApiParam apiParam = ServerWebExchangeUtil.getApiParam(exchange, body); + // 签名验证 + doValidate(apiParam); + return Mono.just(body); + }); + BodyInserter bodyInserter = BodyInserters.fromPublisher(modifiedBody, (Class) String.class); + HttpHeaders headers = new HttpHeaders(); + headers.putAll(exchange.getRequest().getHeaders()); + + // the new content type will be computed by bodyInserter + // and then set in the request decorator + headers.remove(HttpHeaders.CONTENT_LENGTH); + + CachedBodyOutputMessage outputMessage = new CachedBodyOutputMessage( + exchange, headers); + return bodyInserter.insert(outputMessage, new BodyInserterContext()) + .then(Mono.defer(() -> { + ServerHttpRequest decorator = decorate(exchange, headers, outputMessage); + ServerWebExchange newExchange = exchange.mutate().request(decorator).build(); + return chain.filter(newExchange); + })); + + } else { + URI uri = exchange.getRequest().getURI(); + // 原始参数 + String originalQuery = uri.getRawQuery(); + // 构建ApiParam + ApiParam apiParam = ServerWebExchangeUtil.getApiParam(exchange, originalQuery); + // 签名验证 + doValidate(apiParam); + ServerWebExchange newExchange = ServerWebExchangeUtil.getForwardExchange(exchange, apiParam); + return chain.filter(newExchange); + } + } else { + return ServerWebExchangeUtil.forwardUnknown(exchange, chain); + } + } + + private void doValidate(ApiParam apiParam) { + try { + validator.validate(apiParam); + } catch (ApiException e) { + log.error("验证失败,ip:{}, params:{}, errorMsg:{}", apiParam.fetchIp(), apiParam.toJSONString(), e.getMessage()); + apiParam.setThrowable(e); + } + } + + private ServerHttpRequestDecorator decorate( + ServerWebExchange exchange + , HttpHeaders headers + , CachedBodyOutputMessage outputMessage + ) { + ApiParam apiParam = ServerWebExchangeUtil.getApiParam(exchange); + ServerHttpRequest newRequest = ServerWebExchangeUtil.getForwardRequest(exchange.getRequest(), apiParam); + return new ServerHttpRequestDecorator(newRequest) { + @Override + public HttpHeaders getHeaders() { + long contentLength = headers.getContentLength(); + HttpHeaders httpHeaders = new HttpHeaders(); + httpHeaders.putAll(super.getHeaders()); + if (contentLength > 0) { + httpHeaders.setContentLength(contentLength); + } else { + httpHeaders.set(HttpHeaders.TRANSFER_ENCODING, "chunked"); + } + httpHeaders.set(SopConstants.REDIRECT_VERSION_KEY, apiParam.fetchVersion()); + return httpHeaders; + } + + @Override + public Flux getBody() { + return outputMessage.getBody(); + } + }; + } +} \ No newline at end of file diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/LoadBalancerClientExtFilter.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/LoadBalancerClientExtFilter.java deleted file mode 100644 index 8cd9ad21..00000000 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/LoadBalancerClientExtFilter.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.gitee.sop.gatewaycommon.gateway.filter; - -import com.gitee.sop.gatewaycommon.bean.SopConstants; -import com.gitee.sop.gatewaycommon.util.RouteUtil; -import lombok.extern.slf4j.Slf4j; -import org.springframework.cloud.gateway.filter.GatewayFilterChain; -import org.springframework.cloud.gateway.filter.GlobalFilter; -import org.springframework.cloud.gateway.route.Route; -import org.springframework.core.Ordered; -import org.springframework.util.StringUtils; -import org.springframework.web.server.ServerWebExchange; -import org.springframework.web.util.UriComponentsBuilder; -import reactor.core.publisher.Mono; - -import java.net.URI; - -import static org.springframework.cloud.gateway.filter.LoadBalancerClientFilter.LOAD_BALANCER_CLIENT_FILTER_ORDER; -import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR; -import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR; - -/** - * 在LoadBalancerClientFilter后面处理,从Route中找到具体的path,然后插入到uri的path中 - * - * @author tanghc - */ -@Slf4j -public class LoadBalancerClientExtFilter implements GlobalFilter, Ordered { - - @Override - public int getOrder() { - return LOAD_BALANCER_CLIENT_FILTER_ORDER + 1; - } - - @Override - public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) { - Route route = exchange.getAttribute(GATEWAY_ROUTE_ATTR); - String path = this.findPath(exchange, route); - if (StringUtils.hasLength(path)) { - URI url = exchange.getAttribute(GATEWAY_REQUEST_URL_ATTR); - UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.fromUri(url); - uriComponentsBuilder.path(path); - URI requestUrl = uriComponentsBuilder.build(true).toUri(); - exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, requestUrl); - } - return chain.filter(exchange); - } - - protected String findPath(ServerWebExchange exchange, Route route) { - String path = exchange.getAttribute(SopConstants.REDIRECT_PATH_KEY); - if (path != null) { - return path; - } - URI routeUri = route.getUri(); - String uriStr = routeUri.toString(); - return RouteUtil.findPath(uriStr); - } - -} 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 deleted file mode 100644 index 72c6d582..00000000 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/ValidateFilter.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.gitee.sop.gatewaycommon.gateway.filter; - -import com.gitee.sop.gatewaycommon.exception.ApiException; -import com.gitee.sop.gatewaycommon.gateway.ServerWebExchangeUtil; -import com.gitee.sop.gatewaycommon.param.ApiParam; -import com.gitee.sop.gatewaycommon.param.ParamBuilder; -import com.gitee.sop.gatewaycommon.validate.Validator; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -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; - -/** - * @author tanghc - */ -@Slf4j -public class ValidateFilter implements GlobalFilter, Ordered { - - @Autowired - private ParamBuilder paramBuilder; - - @Autowired - private Validator validator; - - @Override - public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) { - // 解析参数 - ApiParam param = paramBuilder.build(exchange); - ServerWebExchangeUtil.setApiParam(exchange, param); - // 验证操作,这里有负责验证签名参数 - try { - validator.validate(param); - } catch (ApiException e) { - log.error("验证失败,params:{}", param.toJSONString(), e); - throw e; - } - return chain.filter(exchange); - } - - @Override - public int getOrder() { - // 最优先执行 - return Orders.VALIDATE_FILTER_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 7d19b212..0f623358 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 @@ -2,15 +2,15 @@ package com.gitee.sop.gatewaycommon.gateway.handler; import com.gitee.sop.gatewaycommon.bean.ApiContext; import com.gitee.sop.gatewaycommon.gateway.ServerWebExchangeUtil; -import com.gitee.sop.gatewaycommon.gateway.result.GatewayResult; import com.gitee.sop.gatewaycommon.param.ApiParam; import com.gitee.sop.gatewaycommon.result.ResultExecutor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; import org.springframework.http.codec.HttpMessageReader; import org.springframework.http.codec.HttpMessageWriter; -import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.util.Assert; import org.springframework.web.reactive.function.BodyInserters; import org.springframework.web.reactive.function.server.RequestPredicates; @@ -33,10 +33,26 @@ public class GatewayExceptionHandler implements ErrorWebExceptionHandler { private static final Logger log = LoggerFactory.getLogger(GatewayExceptionHandler.class); + + /** + * MessageReader + */ + private List> messageReaders = Collections.emptyList(); + + /** + * MessageWriter + */ + private List> messageWriters = Collections.emptyList(); + + /** + * ViewResolvers + */ + private List viewResolvers = Collections.emptyList(); + @Override public Mono handle(ServerWebExchange exchange, Throwable ex) { - ResultExecutor resultExecutor = ApiContext.getApiConfig().getGatewayResultExecutor(); - GatewayResult errorResult = resultExecutor.buildErrorResult(exchange, ex); + ResultExecutor resultExecutor = ApiContext.getApiConfig().getGatewayResultExecutor(); + String errorResult = resultExecutor.buildErrorResult(exchange, ex); ApiParam apiParam = ServerWebExchangeUtil.getApiParam(exchange); // 错误记录 log.error("gateway网关报错,params:{}, errorMsg:{}", apiParam, ex.getMessage(), ex); @@ -52,21 +68,6 @@ public class GatewayExceptionHandler implements ErrorWebExceptionHandler { } - /** - * MessageReader - */ - private List> messageReaders = Collections.emptyList(); - - /** - * MessageWriter - */ - private List> messageWriters = Collections.emptyList(); - - /** - * ViewResolvers - */ - private List viewResolvers = Collections.emptyList(); - /** * 参考AbstractErrorWebExceptionHandler * @@ -103,11 +104,11 @@ public class GatewayExceptionHandler implements ErrorWebExceptionHandler { * @param result 返回结果 * @return 返回mono */ - protected Mono renderErrorResponse(GatewayResult result) { + protected Mono renderErrorResponse(String result) { return ServerResponse - .status(result.getHttpStatus()) - .contentType(result.getContentType()) - .body(BodyInserters.fromObject(result.getBody())); + .status(HttpStatus.OK) + .contentType(MediaType.APPLICATION_JSON_UTF8) + .body(BodyInserters.fromObject(result)); } /** diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/param/GatewayParamBuilder.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/param/GatewayParamBuilder.java deleted file mode 100644 index a1054f8d..00000000 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/param/GatewayParamBuilder.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.gitee.sop.gatewaycommon.gateway.param; - -import com.gitee.sop.gatewaycommon.gateway.ServerWebExchangeUtil; -import com.gitee.sop.gatewaycommon.param.ApiParam; -import com.gitee.sop.gatewaycommon.param.BaseParamBuilder; -import org.springframework.web.server.ServerWebExchange; - -/** - * @author tanghc - */ -public class GatewayParamBuilder extends BaseParamBuilder { - - @Override - public ApiParam buildRequestParams(ServerWebExchange exchange) { - return ServerWebExchangeUtil.getRequestParams(exchange); - } - - @Override - public String getIP(ServerWebExchange ctx) { - return ctx.getRequest().getRemoteAddress().getAddress().getHostAddress(); - } - - @Override - public void setVersionInHeader(ServerWebExchange ctx, String headerName, String version) { - ctx.getRequest().getHeaders().add(headerName, version); - } -} diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/result/GatewayResultExecutor.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/result/GatewayResultExecutor.java index 55f57a92..9554647a 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/result/GatewayResultExecutor.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/result/GatewayResultExecutor.java @@ -4,12 +4,13 @@ import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.gitee.sop.gatewaycommon.bean.SopConstants; import com.gitee.sop.gatewaycommon.exception.ApiException; +import com.gitee.sop.gatewaycommon.gateway.ServerWebExchangeUtil; import com.gitee.sop.gatewaycommon.message.Error; import com.gitee.sop.gatewaycommon.message.ErrorEnum; +import com.gitee.sop.gatewaycommon.param.ApiParam; import com.gitee.sop.gatewaycommon.result.BaseExecutorAdapter; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; import org.springframework.util.CollectionUtils; import org.springframework.web.server.ServerWebExchange; @@ -21,7 +22,7 @@ import java.util.Map; * @author tanghc */ @Slf4j -public class GatewayResultExecutor extends BaseExecutorAdapter { +public class GatewayResultExecutor extends BaseExecutorAdapter { @Override public int getResponseStatus(ServerWebExchange exchange) { @@ -46,12 +47,12 @@ public class GatewayResultExecutor extends BaseExecutorAdapter getApiParam(ServerWebExchange exchange) { - return exchange.getAttribute(SopConstants.CACHE_REQUEST_BODY_FOR_MAP); + public ApiParam getApiParam(ServerWebExchange exchange) { + return ServerWebExchangeUtil.getApiParam(exchange); } @Override - public GatewayResult buildErrorResult(ServerWebExchange exchange, Throwable ex) { + public String buildErrorResult(ServerWebExchange exchange, Throwable ex) { Error error; if (ex instanceof ApiException) { ApiException apiException = (ApiException) ex; @@ -59,11 +60,8 @@ public class GatewayResultExecutor extends BaseExecutorAdapter { path = path.replace('{', '?'); path = path.replace('}', '?'); } - targetRoute.setUri(URI.create(routeDefinition.getUri() + "#" + path)); + targetRoute.setUri(URI.create(routeDefinition.getUri() + "/" + path)); targetRoute.setOrder(routeDefinition.getOrder()); // 添加过滤器 List filterDefinitionList = routeDefinition.getFilters() @@ -43,40 +40,7 @@ public class GatewayRouteCache extends BaseRouteCache { return filterDefinition; }) .collect(Collectors.toList()); - - - LinkedList predicateDefinitionList = routeDefinition.getPredicates() - .stream() - .map(predicate -> { - PredicateDefinition predicateDefinition = new PredicateDefinition(); - BeanUtils.copyProperties(predicate, predicateDefinition); - return predicateDefinition; - }) - .collect(Collectors.toCollection(LinkedList::new)); - // 下面两个自定义的断言添加到顶部,注意:ReadBody需要放在最前面 - // 对应断言: - // NameVersion -> com.gitee.sop.gatewaycommon.gateway.route.NameVersionRoutePredicateFactory - // ReadBody -> com.gitee.sop.gatewaycommon.gateway.route.ReadBodyRoutePredicateFactory - predicateDefinitionList.addFirst(new PredicateDefinition("NameVersion=" + routeDefinition.getId())); - predicateDefinitionList.addFirst(new PredicateDefinition("ReadBody=")); - - targetRoute.setFilters(filterDefinitionList); - targetRoute.setPredicates(predicateDefinitionList); return new GatewayTargetRoute(serviceRouteInfo, routeDefinition, targetRoute); } - @Override - protected List getExtRouteDefinitionList(ServiceRouteInfo serviceRouteInfo) { - // 在第一个位置放一个没用的路由,SpringCloudGateway会从第二个路由开始找,原因不详 - RouteDefinition routeDefinition = new RouteDefinition(); - String name = "_first_route_"; - String version = String.valueOf(System.currentTimeMillis()); - routeDefinition.setId(name + version); - routeDefinition.setName(name); - routeDefinition.setVersion(version); - routeDefinition.setUri("lb://" + serviceRouteInfo.getServiceId()); - routeDefinition.setOrder(Integer.MIN_VALUE); - - return Collections.singletonList(routeDefinition); - } } 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 2a54578c..fa8c0f54 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,15 +1,19 @@ package com.gitee.sop.gatewaycommon.gateway.route; +import com.gitee.sop.gatewaycommon.bean.AbstractTargetRoute; import com.gitee.sop.gatewaycommon.bean.RouteDefinition; -import com.gitee.sop.gatewaycommon.bean.TargetRoute; import com.gitee.sop.gatewaycommon.manager.RouteRepository; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; -import org.springframework.cloud.gateway.route.RouteDefinitionRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cloud.gateway.event.RefreshRoutesEvent; +import org.springframework.cloud.gateway.route.Route; +import org.springframework.cloud.gateway.route.RouteLocator; +import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder; +import org.springframework.context.ApplicationContext; import org.springframework.util.AntPathMatcher; import org.springframework.util.PathMatcher; import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; import java.util.Collection; import java.util.LinkedHashMap; @@ -25,28 +29,37 @@ import static java.util.Collections.synchronizedMap; * @author tanghc */ @Slf4j -public class GatewayRouteRepository implements RouteDefinitionRepository, RouteRepository { +public class GatewayRouteRepository implements RouteRepository, RouteLocator { private PathMatcher pathMatcher = new AntPathMatcher(); private final Map routes = synchronizedMap(new LinkedHashMap<>()); - @Override - public Flux getRouteDefinitions() { - List list = routes.values().parallelStream() - .map(TargetRoute::getTargetRouteDefinition) - .collect(Collectors.toList()); - return Flux.fromIterable(list); - } + @Autowired + private RouteLocatorBuilder routeLocatorBuilder; + + @Autowired + private ApplicationContext applicationContext; + + private RouteLocator routeLocator; @Override - public Mono save(Mono route) { - return null; + public Flux getRoutes() { + return routeLocator.getRoutes(); } - @Override - public Mono delete(Mono routeId) { - return null; + public void refresh() { + RouteLocatorBuilder.Builder builder = routeLocatorBuilder.routes(); + List routeDefinitionList = this.routes.values() + .stream() + .map(AbstractTargetRoute::getRouteDefinition) + .collect(Collectors.toList()); + routeDefinitionList.forEach(routeDefinition -> builder.route(routeDefinition.getId(), + r -> r.path(routeDefinition.getPath()) + .uri(routeDefinition.getUri()))); + this.routeLocator = builder.build(); + // 触发 + applicationContext.publishEvent(new RefreshRoutesEvent(new Object())); } /** 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 deleted file mode 100644 index a3a61203..00000000 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/route/NameVersionRoutePredicateFactory.java +++ /dev/null @@ -1,105 +0,0 @@ -package com.gitee.sop.gatewaycommon.gateway.route; - -import com.gitee.sop.gatewaycommon.bean.SopConstants; -import com.gitee.sop.gatewaycommon.gateway.ServerWebExchangeUtil; -import com.gitee.sop.gatewaycommon.param.ParamNames; -import lombok.extern.slf4j.Slf4j; -import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory; -import org.springframework.util.AntPathMatcher; -import org.springframework.util.CollectionUtils; -import org.springframework.util.PathMatcher; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.server.ServerWebExchange; - -import javax.validation.constraints.NotEmpty; -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.function.Predicate; - -/** - * 此断言决定执行哪个路由 - * - * 使用地方: - * @see com.gitee.sop.gatewaycommon.gateway.route.GatewayRouteCache - * - * @author tanghc - */ -@Slf4j -public class NameVersionRoutePredicateFactory extends AbstractRoutePredicateFactory { - - private static final String PARAM_KEY = "param"; - private static final String REGEXP_KEY = "regexp"; - - private PathMatcher pathMatcher = new AntPathMatcher(); - - public NameVersionRoutePredicateFactory() { - super(Config.class); - } - - @Override - public List shortcutFieldOrder() { - return Arrays.asList(PARAM_KEY, REGEXP_KEY); - } - - /** - * config.param为nameVersion,即路由id - * - * @param config - * @return 返回断言 - */ - @Override - public Predicate apply(Config config) { - - return exchange -> { - Map params = ServerWebExchangeUtil.getRequestParams(exchange); - if (CollectionUtils.isEmpty(params)) { - return false; - } - String nameVersion = config.param; - Object name = params.get(ParamNames.API_NAME); - Object version = params.get(ParamNames.VERSION_NAME); - if (name == null || version == null) { - return false; - } - String key = name.toString() + version.toString(); - // 如果是通配符 - if (nameVersion.contains("{")) { - boolean match = pathMatcher.match(nameVersion, key); - if (match) { - Map attributes = exchange.getAttributes(); - attributes.put(SopConstants.REDIRECT_PATH_KEY, key); - } - return match; - } else { - return key.equals(nameVersion); - } - }; - } - - @Validated - public static class Config { - @NotEmpty - private String param; - - private String regexp; - - public String getParam() { - return param; - } - - public Config setParam(String param) { - this.param = param; - return this; - } - - public String getRegexp() { - return regexp; - } - - public Config setRegexp(String regexp) { - this.regexp = regexp; - return this; - } - } -} 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 deleted file mode 100644 index d8f48b1c..00000000 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/route/ReadBodyRoutePredicateFactory.java +++ /dev/null @@ -1,202 +0,0 @@ -package com.gitee.sop.gatewaycommon.gateway.route; - -import org.apache.commons.lang.StringUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.cloud.gateway.handler.AsyncPredicate; -import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory; -import org.springframework.cloud.gateway.handler.predicate.ReadBodyPredicateFactory; -import org.springframework.core.io.buffer.DataBuffer; -import org.springframework.core.io.buffer.DataBufferUtils; -import org.springframework.http.HttpMethod; -import org.springframework.http.codec.HttpMessageReader; -import org.springframework.http.server.reactive.ServerHttpRequest; -import org.springframework.http.server.reactive.ServerHttpRequestDecorator; -import org.springframework.util.MultiValueMap; -import org.springframework.web.reactive.function.server.HandlerStrategies; -import org.springframework.web.reactive.function.server.ServerRequest; -import org.springframework.web.server.ServerWebExchange; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.function.Predicate; - -import static org.springframework.cloud.gateway.filter.AdaptCachedBodyGlobalFilter.CACHED_REQUEST_BODY_KEY; - -/** - * 获取请求参数插件,兼容get,post,使用方式: - * @Bean - * ReadBodyRoutePredicateFactory readBodyRoutePredicateFactory() { - * return new ReadBodyRoutePredicateFactory(); - * } - * - * @see org.springframework.cloud.gateway.handler.predicate.ReadBodyPredicateFactory - * 详见:https://blog.51cto.com/thinklili/2329184 - * - * 使用地方: - * @see com.gitee.sop.gatewaycommon.gateway.route.GatewayRouteCache - * - * @author tanghc - */ -public class ReadBodyRoutePredicateFactory extends AbstractRoutePredicateFactory { - - protected static final Log LOGGER = LogFactory.getLog(ReadBodyPredicateFactory.class); - - private static final String TEST_ATTRIBUTE = "read_body_predicate_test_attribute"; - private static final String CACHE_REQUEST_BODY_OBJECT_KEY = "cachedRequestBodyObject"; - private static final List> HTTP_MESSAGE_READERS = HandlerStrategies.withDefaults().messageReaders(); - - - public ReadBodyRoutePredicateFactory() { - super(ReadBodyRoutePredicateFactory.Config.class); - } - - @Override - public AsyncPredicate applyAsync(Config config) { - return exchange -> { - HttpMethod method = exchange.getRequest().getMethod(); - if (method == HttpMethod.POST) { - return this.applyForPost(exchange, config); - } else { - return this.applyForGet(exchange, config); - } - }; - } - - /** - * 获取post表单参数 - * @param exchange - * @param config - * @return - */ - protected Mono applyForPost(ServerWebExchange exchange, Config config) { - Class inClass = config.getInClass(); - - Object cachedBody = exchange.getAttribute(CACHE_REQUEST_BODY_OBJECT_KEY); - // We can only read the body from the request once, once that happens if we try to read the body again an - // exception will be thrown. The below if/else caches the body object as a request attribute in the ServerWebExchange - // so if this filter is run more than once (due to more than one route using it) we do not try to read the - // request body multiple times - if (cachedBody != null) { - try { - boolean test = config.getPredicate().test(cachedBody); - exchange.getAttributes().put(TEST_ATTRIBUTE, test); - return Mono.just(test); - } catch (ClassCastException e) { - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("Predicate test failed because class in predicate does not canVisit the cached body object", - e); - } - } - return Mono.just(false); - } else { - //Join all the DataBuffers so we have a single DataBuffer for the body - return DataBufferUtils.join(exchange.getRequest().getBody()) - .flatMap(dataBuffer -> { - //Update the retain counts so we can read the body twice, once to parse into an object - //that we can test the predicate against and a second time when the HTTP client sends - //the request downstream - //Note: if we end up reading the body twice we will run into a problem, but as of right - //now there is no good use case for doing this - DataBufferUtils.retain(dataBuffer); - //Make a slice for each read so each read has its own read/write indexes - Flux cachedFlux = Flux.defer(() -> Flux.just(dataBuffer.slice(0, dataBuffer.readableByteCount()))); - - ServerHttpRequest mutatedRequest = new ServerHttpRequestDecorator(exchange.getRequest()) { - @Override - public Flux getBody() { - return cachedFlux; - } - }; - return ServerRequest.create(exchange.mutate().request(mutatedRequest).build(), HTTP_MESSAGE_READERS) - .bodyToMono(inClass) - .doOnNext(objectValue -> { - exchange.getAttributes().put(CACHE_REQUEST_BODY_OBJECT_KEY, objectValue); - exchange.getAttributes().put(CACHED_REQUEST_BODY_KEY, cachedFlux); - }) - .map(objectValue -> config.getPredicate().test(objectValue)); - }); - - } - } - - /** - * 获取GET请求参数 - * @param exchange - * @param config - * @return - */ - protected Mono applyForGet(ServerWebExchange exchange, Config config) { - // 处理get请求 - MultiValueMap queryParams = exchange.getRequest().getQueryParams(); - String objectValue = null; - if (queryParams != null && queryParams.size() > 0) { - List params = new ArrayList<>(queryParams.size()); - for (Map.Entry> entry : queryParams.entrySet()) { - params.add(entry.getKey() + "=" + entry.getValue().get(0)); - } - objectValue = StringUtils.join(params.toArray()); - exchange.getAttributes().put(CACHE_REQUEST_BODY_OBJECT_KEY, objectValue); - } - return Mono.just(config.getPredicate().test(objectValue)); - } - - @Override - public Config newConfig() { - Config config = super.newConfig(); - config.setInClass(String.class); - config.setPredicate(Objects::nonNull); - return config; - } - - @Override - @SuppressWarnings("unchecked") - public Predicate apply(Config config) { - throw new UnsupportedOperationException( - "ReadBodyPredicateFactory is only async."); - } - - public static class Config { - private Class inClass; - private Predicate predicate; - private Map hints; - - public Class getInClass() { - return inClass; - } - - public Config setInClass(Class inClass) { - this.inClass = inClass; - return this; - } - - public Predicate getPredicate() { - return predicate; - } - - public Config setPredicate(Class inClass, Predicate predicate) { - setInClass(inClass); - this.predicate = predicate; - return this; - } - - public Config setPredicate(Predicate predicate) { - this.predicate = predicate; - return this; - } - - public Map getHints() { - return hints; - } - - public Config setHints(Map hints) { - this.hints = hints; - return this; - } - } - -} diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/BaseRouteCache.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/BaseRouteCache.java index e2dbddd1..0c0ace23 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/BaseRouteCache.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/BaseRouteCache.java @@ -5,12 +5,9 @@ import com.gitee.sop.gatewaycommon.bean.RouteDefinition; import com.gitee.sop.gatewaycommon.bean.ServiceRouteInfo; import com.gitee.sop.gatewaycommon.bean.TargetRoute; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.collections.CollectionUtils; import org.springframework.util.DigestUtils; import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -55,21 +52,15 @@ public abstract class BaseRouteCache implements RouteLoad } serviceIdMd5Map.put(serviceId, newMd5); - List extRouteDefinitionList = this.getExtRouteDefinitionList(serviceRouteInfo); List routeDefinitionList = serviceRouteInfo.getRouteDefinitionList(); - int size = extRouteDefinitionList.size() + routeDefinitionList.size(); - List allRoutes = new ArrayList<>(size); - if (CollectionUtils.isNotEmpty(extRouteDefinitionList)) { - allRoutes.addAll(extRouteDefinitionList); - } - allRoutes.addAll(routeDefinitionList); - for (RouteDefinition routeDefinition : allRoutes) { + for (RouteDefinition routeDefinition : routeDefinitionList) { T targetRoute = this.buildTargetRoute(serviceRouteInfo, routeDefinition); routeRepository.add(targetRoute); if (log.isDebugEnabled()) { log.debug("新增路由:{}", JSON.toJSONString(routeDefinition)); } } + this.routeRepository.refresh(); callback.accept(null); } catch (Exception e) { log.error("加载路由信息失败,serviceRouteInfo:{}", serviceRouteInfo, e); @@ -91,14 +82,6 @@ public abstract class BaseRouteCache implements RouteLoad return DigestUtils.md5DigestAsHex(md5Source.getBytes(StandardCharsets.UTF_8)); } - /** - * 返回附加的路由选项 - * @return 返回附加的路由选项 - */ - protected List getExtRouteDefinitionList(ServiceRouteInfo serviceRouteInfo) { - return Collections.emptyList(); - } - @Override public void remove(String serviceId) { serviceIdMd5Map.remove(serviceId); 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 8976090f..b6435e07 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 @@ -45,4 +45,9 @@ public interface RouteRepository { * @param serviceId 服务id */ void deleteAll(String serviceId); + + /** + * 刷新 + */ + default void refresh() {} } diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/RouteRepositoryContext.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/RouteRepositoryContext.java index f103f55e..ec4eb090 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/RouteRepositoryContext.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/RouteRepositoryContext.java @@ -25,12 +25,14 @@ public class RouteRepositoryContext { * 检查路由是否存在,不存在报错 * @param routeId 路由id * @param errorEnum 报错信息 + * @return 返回TargetRoute */ - public static void checkExist(String routeId, ErrorEnum errorEnum) { + public static TargetRoute checkExist(String routeId, ErrorEnum errorEnum) { TargetRoute targetRoute = routeRepository.get(routeId); if (targetRoute == null) { throw errorEnum.getErrorMeta().getException(); } + return targetRoute; } } 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 ea5e43bd..e0a38f81 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 @@ -14,6 +14,8 @@ import java.util.Map; */ public class ApiParam extends JSONObject implements Param { + private static final String THROWABLE_KEY = "Throwable"; + public ApiParam() { } @@ -31,6 +33,14 @@ public class ApiParam extends JSONObject implements Param { private transient UploadContext uploadContext; + public void setThrowable(Throwable throwable) { + this.put(THROWABLE_KEY, throwable); + } + + public Throwable getThrowable() { + return (Throwable)get(THROWABLE_KEY); + } + public void fitNameVersion() { if (restName != null) { this.put(ParamNames.API_NAME, restName); 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 c986bd2f..7361b758 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 @@ -5,14 +5,15 @@ import com.alibaba.fastjson.JSONObject; import com.gitee.sop.gatewaycommon.bean.ApiConfig; import com.gitee.sop.gatewaycommon.bean.ApiContext; import com.gitee.sop.gatewaycommon.bean.ErrorDefinition; -import com.gitee.sop.gatewaycommon.bean.RouteDefinition; import com.gitee.sop.gatewaycommon.bean.Isv; +import com.gitee.sop.gatewaycommon.bean.RouteDefinition; import com.gitee.sop.gatewaycommon.bean.ServiceRouteInfo; import com.gitee.sop.gatewaycommon.bean.SopConstants; import com.gitee.sop.gatewaycommon.bean.TargetRoute; import com.gitee.sop.gatewaycommon.manager.RouteRepositoryContext; import com.gitee.sop.gatewaycommon.message.ErrorEnum; import com.gitee.sop.gatewaycommon.message.ErrorMeta; +import com.gitee.sop.gatewaycommon.param.ApiParam; import com.gitee.sop.gatewaycommon.param.ParamNames; import com.gitee.sop.gatewaycommon.secret.IsvManager; import com.gitee.sop.gatewaycommon.validate.alipay.AlipayConstants; @@ -69,7 +70,7 @@ public abstract class BaseExecutorAdapter implements ResultExecutor * @param t request * @return 返回api参数 */ - public abstract Map getApiParam(T t); + public abstract ApiParam getApiParam(T t); @Override public String mergeResult(T request, String serviceResult) { @@ -91,12 +92,12 @@ public abstract class BaseExecutorAdapter implements ResultExecutor responseData = JSON.parseObject(serviceResult); responseData.put(GATEWAY_CODE_NAME, ISP_BIZ_ERROR.getCode()); responseData.put(GATEWAY_MSG_NAME, ISP_BIZ_ERROR.getError().getMsg()); - } else if(responseStatus == HttpStatus.NOT_FOUND.value()) { + } else if (responseStatus == HttpStatus.NOT_FOUND.value()) { responseData = JSON.parseObject(serviceResult); responseData.put(GATEWAY_CODE_NAME, ISV_MISSING_METHOD_META.getCode()); responseData.put(GATEWAY_MSG_NAME, ISV_MISSING_METHOD_META.getError().getCode()); } else { - Map params = this.getApiParam(request); + ApiParam params = this.getApiParam(request); log.error("微服务端报错,params:{}, 微服务返回结果:{}", params, serviceResult); this.storeError(request, ErrorType.UNKNOWN); // 微服务端有可能返回500错误 @@ -140,8 +141,11 @@ public abstract class BaseExecutorAdapter implements ResultExecutor if (defaultSetting != null) { return defaultSetting; } - ApiInfo apiInfo = this.getApiInfo(request); - RouteDefinition baseRouteDefinition = apiInfo.gatewayRouteDefinition; + ApiParam params = this.getApiParam(request); + TargetRoute targetRoute = RouteRepositoryContext.getRouteRepository().get(params.fetchNameVersion()); + RouteDefinition baseRouteDefinition = Optional.ofNullable(targetRoute) + .map(TargetRoute::getRouteDefinition) + .orElse(null); return Optional.ofNullable(baseRouteDefinition) .map(routeDefinition -> { int mergeResult = baseRouteDefinition.getMergeResult(); @@ -151,11 +155,8 @@ public abstract class BaseExecutorAdapter implements ResultExecutor } protected ApiInfo getApiInfo(T request) { - Map params = this.getApiParam(request); - String name = this.getParamValue(params, ParamNames.API_NAME, SopConstants.UNKNOWN_METHOD); - String version = this.getParamValue(params, ParamNames.VERSION_NAME, SopConstants.UNKNOWN_VERSION); - - TargetRoute targetRoute = RouteRepositoryContext.getRouteRepository().get(name + version); + ApiParam params = this.getApiParam(request); + TargetRoute targetRoute = RouteRepositoryContext.getRouteRepository().get(params.fetchNameVersion()); String serviceId = Optional.ofNullable(targetRoute) .flatMap(route -> Optional.ofNullable(route.getServiceRouteInfo())) @@ -167,8 +168,8 @@ public abstract class BaseExecutorAdapter implements ResultExecutor .orElse(null); ApiInfo apiInfo = new ApiInfo(); - apiInfo.name = name; - apiInfo.version = version; + apiInfo.name = params.fetchName(); + apiInfo.version = params.fetchVersion(); apiInfo.serviceId = serviceId; apiInfo.gatewayRouteDefinition = baseRouteDefinition; return apiInfo; @@ -190,8 +191,8 @@ public abstract class BaseExecutorAdapter implements ResultExecutor public String merge(T exchange, JSONObject responseData) { JSONObject finalData = new JSONObject(true); - Map params = this.getApiParam(exchange); - String name = this.getParamValue(params, ParamNames.API_NAME, ERROR_METHOD); + ApiParam params = this.getApiParam(exchange); + String name = params.fetchName(); ApiConfig apiConfig = ApiConfig.getInstance(); // 点换成下划线 DataNameBuilder dataNameBuilder = apiConfig.getDataNameBuilder(); 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 8bdf8f24..bfca1c63 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 @@ -68,9 +68,10 @@ public class ApiValidator implements Validator { @Override public void validate(ApiParam param) { checkIP(param); - checkEnable(param); + TargetRoute targetRoute = checkEnable(param); ApiConfig apiConfig = ApiContext.getApiConfig(); - if (apiConfig.isIgnoreValidate() || param.fetchIgnoreValidate()) { + if (apiConfig.isIgnoreValidate() + || BooleanUtils.toBoolean(targetRoute.getRouteDefinition().getIgnoreValidate())) { if (log.isDebugEnabled()) { log.debug("忽略所有验证(ignoreValidate=true), name:{}, version:{}", param.fetchName(), param.fetchVersion()); } @@ -103,7 +104,7 @@ public class ApiValidator implements Validator { * * @param param 接口参数 */ - protected void checkEnable(ApiParam param) { + protected TargetRoute checkEnable(ApiParam param) { String name = param.fetchName(); if (name == null) { throw ErrorEnum.ISV_MISSING_METHOD.getErrorMeta().getException(); @@ -114,12 +115,13 @@ public class ApiValidator implements Validator { } String routeId = param.fetchNameVersion(); // 检查路由是否存在 - RouteRepositoryContext.checkExist(routeId, ErrorEnum.ISV_INVALID_METHOD); + TargetRoute targetRoute = RouteRepositoryContext.checkExist(routeId, ErrorEnum.ISV_INVALID_METHOD); // 检查路由是否启用 RouteConfig routeConfig = routeConfigManager.get(routeId); if (!routeConfig.enable()) { throw ErrorEnum.ISP_API_DISABLED.getErrorMeta().getException(); } + return targetRoute; } /** 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 3b6dbc9f..7156450b 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 @@ -169,8 +169,7 @@ public class BaseZuulConfiguration extends AbstractConfiguration { * 统一错误处理 */ @Bean - @ConditionalOnMissingBean - ZuulErrorController baseZuulController() { + ZuulErrorController sopZuulController() { return ApiContext.getApiConfig().getZuulErrorController(); } diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/configuration/ZuulErrorController.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/configuration/ZuulErrorController.java index cb20a6ae..dff2a294 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/configuration/ZuulErrorController.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/configuration/ZuulErrorController.java @@ -5,10 +5,8 @@ import com.gitee.sop.gatewaycommon.result.ResultExecutor; import com.gitee.sop.gatewaycommon.zuul.ZuulContext; import com.netflix.zuul.context.RequestContext; import lombok.extern.slf4j.Slf4j; -import org.springframework.boot.web.servlet.error.ErrorController; -import org.springframework.http.HttpStatus; -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; import javax.servlet.http.HttpServletRequest; @@ -19,16 +17,14 @@ import javax.servlet.http.HttpServletResponse; * * @author tanghc */ -@Controller +@ControllerAdvice @Slf4j -public class ZuulErrorController implements ErrorController { - - private static final String ERROR_PATH = "/error"; +public class ZuulErrorController { /** * 错误最终会到这里来 */ - @RequestMapping(ERROR_PATH) + @ExceptionHandler(Exception.class) @ResponseBody public Object error(HttpServletRequest request, HttpServletResponse response) { RequestContext ctx = RequestContext.getCurrentContext(); @@ -49,8 +45,4 @@ public class ZuulErrorController implements ErrorController { return resultExecutor.buildErrorResult(RequestContext.getCurrentContext(), throwable); } - @Override - public String getErrorPath() { - return ERROR_PATH; - } } diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/controller/ConfigChannelController.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/controller/ConfigChannelController.java index 2f1acd07..8cc23726 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/controller/ConfigChannelController.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/controller/ConfigChannelController.java @@ -16,6 +16,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpServletRequest; import java.io.IOException; @@ -26,7 +27,7 @@ import java.util.Map; * @author tanghc */ @Slf4j -@Controller +@RestController public class ConfigChannelController { private static Map> processorMap = new HashMap<>(16); @@ -40,7 +41,7 @@ public class ConfigChannelController { processorMap.put(NacosConfigs.GROUP_CHANNEL + NacosConfigs.DATA_ID_ROUTE_CONFIG, RouteConfigManager.class); } - @Value("${zuul.secret}") + @Value("${sop.secret}") private String secret; @PostMapping("/sop/configChannelMsg") diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/controller/ErrorLogController.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/controller/ErrorLogController.java index 3c773afb..c4907461 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/controller/ErrorLogController.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/controller/ErrorLogController.java @@ -1,72 +1,23 @@ package com.gitee.sop.gatewaycommon.zuul.controller; -import com.gitee.sop.gatewaycommon.bean.ApiConfig; -import com.gitee.sop.gatewaycommon.bean.ErrorEntity; -import com.gitee.sop.gatewaycommon.manager.ServiceErrorManager; +import com.gitee.sop.gatewaycommon.bean.BaseErrorLogController; import com.gitee.sop.gatewaycommon.param.ApiParam; -import com.gitee.sop.gatewaycommon.result.ApiResult; -import com.gitee.sop.gatewaycommon.result.JsonResult; import com.gitee.sop.gatewaycommon.util.RequestUtil; -import com.gitee.sop.gatewaycommon.validate.taobao.TaobaoSigner; -import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpServletRequest; -import java.util.Collection; import java.util.Map; /** * @author tanghc */ -@Controller -public class ErrorLogController { +@RestController +public class ErrorLogController extends BaseErrorLogController { - TaobaoSigner signer = new TaobaoSigner(); - - @Value("${zuul.secret}") - private String secret; - - @GetMapping("listErrors") - public ApiResult listErrors(HttpServletRequest request) { - try { - this.check(request); - ServiceErrorManager serviceErrorManager = ApiConfig.getInstance().getServiceErrorManager(); - Collection allErrors = serviceErrorManager.listAllErrors(); - JsonResult apiResult = new JsonResult(); - apiResult.setData(allErrors); - return apiResult; - } catch (Exception e) { - ApiResult apiResult = new ApiResult(); - apiResult.setCode("505050"); - apiResult.setMsg(e.getMessage()); - return apiResult; - } - } - - @GetMapping("clearErrors") - public ApiResult clearErrors(HttpServletRequest request) { - try { - this.check(request); - ServiceErrorManager serviceErrorManager = ApiConfig.getInstance().getServiceErrorManager(); - serviceErrorManager.clear(); - return new ApiResult(); - } catch (Exception e) { - ApiResult apiResult = new ApiResult(); - apiResult.setCode("505050"); - apiResult.setMsg(e.getMessage()); - return apiResult; - } - } - - private void check(HttpServletRequest request) { + @Override + protected ApiParam getApiParam(HttpServletRequest request) { Map params = RequestUtil.convertRequestParamsToMap(request); - ApiParam apiParam = ApiParam.build(params); - boolean right = signer.checkSign(apiParam, secret); - if (!right) { - throw new RuntimeException("签名校验失败"); - } + return ApiParam.build(params); } - } diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/controller/RestServlet.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/controller/RestServlet.java deleted file mode 100644 index 1a1a484e..00000000 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/controller/RestServlet.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.gitee.sop.gatewaycommon.zuul.controller; - -import com.gitee.sop.gatewaycommon.bean.SopConstants; -import org.springframework.beans.factory.annotation.Value; - -import javax.servlet.ServletException; -import javax.servlet.annotation.WebServlet; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; - -/** - * 传统web开发入口 - * @author tanghc - */ -//@WebServlet(urlPatterns = "/rest/*") -public class RestServlet extends HttpServlet { - - private static final String EMPTY_VERSION = ""; - - @Value("${zuul.servlet-path:/zuul}") - private String path; - - @Value("${sop.restful.path:/rest}") - private String restPath; - - @Override - protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { - doPost(request, response); - } - - @Override - protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { - String url = request.getRequestURL().toString(); - int index = url.indexOf(restPath); - // 取/rest的后面部分 - String path = url.substring(index + restPath.length()); - request.setAttribute(SopConstants.REDIRECT_METHOD_KEY, path); - request.setAttribute(SopConstants.REDIRECT_VERSION_KEY, EMPTY_VERSION); - request.setAttribute(SopConstants.SOP_NOT_MERGE, true); - request.getRequestDispatcher(this.path).forward(request, response); - } - -} \ No newline at end of file diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/result/ZuulResultExecutor.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/result/ZuulResultExecutor.java index 9cfd0cd7..fb428811 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/result/ZuulResultExecutor.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/result/ZuulResultExecutor.java @@ -6,6 +6,7 @@ import com.gitee.sop.gatewaycommon.bean.SopConstants; import com.gitee.sop.gatewaycommon.exception.ApiException; import com.gitee.sop.gatewaycommon.message.Error; import com.gitee.sop.gatewaycommon.message.ErrorEnum; +import com.gitee.sop.gatewaycommon.param.ApiParam; import com.gitee.sop.gatewaycommon.result.BaseExecutorAdapter; import com.gitee.sop.gatewaycommon.zuul.ZuulContext; import com.netflix.util.Pair; @@ -14,7 +15,6 @@ import com.netflix.zuul.exception.ZuulException; import lombok.extern.slf4j.Slf4j; import java.util.List; -import java.util.Map; /** * @author tanghc @@ -62,7 +62,7 @@ public class ZuulResultExecutor extends BaseExecutorAdapter getApiParam(RequestContext requestContext) { + public ApiParam getApiParam(RequestContext requestContext) { return ZuulContext.getApiParam(); } diff --git a/sop-common/sop-gateway-common/src/main/resources/META-INF/spring.factories b/sop-common/sop-gateway-common/src/main/resources/META-INF/spring.factories new file mode 100644 index 00000000..c0f0b43f --- /dev/null +++ b/sop-common/sop-gateway-common/src/main/resources/META-INF/spring.factories @@ -0,0 +1,3 @@ +org.springframework.boot.env.EnvironmentPostProcessor=com.gitee.sop.gatewaycommon.env.SopEnvironmentPostProcessor +# 自定义自动配置类,如果有多个类,使用逗号(,)分隔,\正斜杠标示换行还可以读取到指定的类 +org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.gitee.sop.bridge.SopGatewayAutoConfiguration diff --git a/sop-example/sop-story/sop-story-web/src/main/java/com/gitee/sop/storyweb/controller/AlipayController.java b/sop-example/sop-story/sop-story-web/src/main/java/com/gitee/sop/storyweb/controller/AlipayController.java index b0530de1..143e71a1 100644 --- a/sop-example/sop-story/sop-story-web/src/main/java/com/gitee/sop/storyweb/controller/AlipayController.java +++ b/sop-example/sop-story/sop-story-web/src/main/java/com/gitee/sop/storyweb/controller/AlipayController.java @@ -17,6 +17,8 @@ import io.swagger.annotations.ApiOperation; import lombok.Data; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.env.Environment; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; @@ -39,6 +41,9 @@ import java.util.List; @Api(tags = "故事接口") public class AlipayController { + @Autowired + private Environment environment; + // http://localhost:2222/story_get // 原生的接口,可正常调用 @RequestMapping("story_get") @@ -180,7 +185,7 @@ public class AlipayController { public StoryResult getStory(StoryParam param) { StoryResult story = new StoryResult(); story.setId(1L); - story.setName("海底小纵队(alipay.story.get1.0), param:" + param); + story.setName("海底小纵队(alipay.story.get1.0), port:" + environment.getProperty("server.port") + ", param:" + param); return story; } diff --git a/sop-example/sop-story/sop-story-web/src/main/java/com/gitee/sop/storyweb/controller/FileUploadDemoController.java b/sop-example/sop-story/sop-story-web/src/main/java/com/gitee/sop/storyweb/controller/FileUploadDemoController.java index ff57a354..e5854db1 100644 --- a/sop-example/sop-story/sop-story-web/src/main/java/com/gitee/sop/storyweb/controller/FileUploadDemoController.java +++ b/sop-example/sop-story/sop-story-web/src/main/java/com/gitee/sop/storyweb/controller/FileUploadDemoController.java @@ -34,7 +34,6 @@ public class FileUploadDemoController { @ApiOperation(value = "文件上传例1", notes = "上传文件demo") @ApiMapping(value = "demo.file.upload") public FileUploadResult file1(FileUploadParam param) { - System.out.println(param.getRemark()); // 获取上传的文件 MultipartFile file1 = param.getFile1(); MultipartFile file2 = param.getFile2(); @@ -43,6 +42,7 @@ public class FileUploadDemoController { FileUploadResult.FileMeta fileMeta1 = buildFileMeta(file1); FileUploadResult.FileMeta fileMeta2 = buildFileMeta(file2); + result.setRemark(param.getRemark()); result.getFiles().add(fileMeta1); result.getFiles().add(fileMeta2); return result; diff --git a/sop-example/sop-story/sop-story-web/src/main/java/com/gitee/sop/storyweb/controller/result/FileUploadResult.java b/sop-example/sop-story/sop-story-web/src/main/java/com/gitee/sop/storyweb/controller/result/FileUploadResult.java index 447292ad..11f20176 100644 --- a/sop-example/sop-story/sop-story-web/src/main/java/com/gitee/sop/storyweb/controller/result/FileUploadResult.java +++ b/sop-example/sop-story/sop-story-web/src/main/java/com/gitee/sop/storyweb/controller/result/FileUploadResult.java @@ -13,6 +13,7 @@ import java.util.List; public class FileUploadResult { private List files = new ArrayList(); + private String remark; @Data public static class FileMeta { diff --git a/sop-gateway/pom.xml b/sop-gateway/pom.xml index 79abd906..8352f1d3 100644 --- a/sop-gateway/pom.xml +++ b/sop-gateway/pom.xml @@ -26,23 +26,15 @@ - + com.gitee.sop - sop-gateway-common + + + + sop-bridge-gateway 2.5.10-SNAPSHOT - - - org.springframework.cloud - spring-cloud-starter-netflix-zuul - - - org.springframework.retry - spring-retry - - - net.oschina.durcframework fastmybatis-spring-boot-starter @@ -70,17 +62,6 @@ - - - com.alibaba.boot - nacos-config-spring-boot-starter - ${nacos-spring-boot-starter.version} - - - org.springframework.boot diff --git a/sop-gateway/src/main/java/com/gitee/sop/gateway/SopGatewayApplication.java b/sop-gateway/src/main/java/com/gitee/sop/gateway/SopGatewayApplication.java index 8b3fe901..20b6880a 100644 --- a/sop-gateway/src/main/java/com/gitee/sop/gateway/SopGatewayApplication.java +++ b/sop-gateway/src/main/java/com/gitee/sop/gateway/SopGatewayApplication.java @@ -2,13 +2,7 @@ package com.gitee.sop.gateway; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.web.servlet.ServletComponentScan; -import org.springframework.cloud.netflix.zuul.EnableZuulProxy; -// 开启网关功能 -@EnableZuulProxy -// 扫描自定义的servlet(类上标注@WebServle) -@ServletComponentScan @SpringBootApplication public class SopGatewayApplication { diff --git a/sop-gateway/src/main/java/com/gitee/sop/gateway/config/GatewayConfig.java b/sop-gateway/src/main/java/com/gitee/sop/gateway/config/GatewayConfig.java index 3345063d..56d66b9d 100644 --- a/sop-gateway/src/main/java/com/gitee/sop/gateway/config/GatewayConfig.java +++ b/sop-gateway/src/main/java/com/gitee/sop/gateway/config/GatewayConfig.java @@ -1,6 +1,7 @@ package com.gitee.sop.gateway.config; import com.gitee.sop.gatewaycommon.gateway.configuration.AlipayGatewayConfiguration; +import org.springframework.context.annotation.Configuration; /** 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 4f0863a1..a4e04211 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 @@ -13,7 +13,7 @@ import org.springframework.context.annotation.Configuration; * 开通支付宝开放平台能力 * @author tanghc */ -@Configuration +//@Configuration public class ZuulConfig extends AlipayZuulConfiguration { } diff --git a/sop-gateway/src/main/resources/application-dev.properties b/sop-gateway/src/main/resources/application-dev.properties index 21b95d95..8ee3879e 100644 --- a/sop-gateway/src/main/resources/application-dev.properties +++ b/sop-gateway/src/main/resources/application-dev.properties @@ -1,5 +1,5 @@ server.port=8081 -# 固定不变 +# 固定不变,不能改 spring.application.name=sop-gateway # ------- 需要改的配置 ------- @@ -10,56 +10,15 @@ mysql.password=root # nacos地址 nacos.url=127.0.0.1:8848 - -# zipkin服务监控地址,没有开启不用改 -zipkin.url=http://127.0.0.1:9411/ - -# 预发布网关域名 -pre.domain=localhost # ------- 需要改的配置end ------- -# 入口地址,不用改,默认是/zuul -zuul.servlet-path=/api -# 禁用默认的过滤器,不能删,不用改 -zuul.FormBodyWrapperFilter.pre.disable=true -zuul.Servlet30WrapperFilter.pre.disable=true -# 不用改,如果要改,请全局替换修改 -zuul.secret=MZZOUSTua6LzApIWXCwEgbBmxSzpzC -# 不用改 -zuul.rest-default-version=1.0 - -# https://blog.csdn.net/qq_36872046/article/details/81058045 -# 路由转发超时时间,毫秒,默认值1000,详见:RibbonClientConfiguration.DEFAULT_READ_TIMEOUT。 -# 如果微服务端 处理时间过长,会导致ribbon read超时,解决办法将这个值调大一点 -ribbon.ReadTimeout=2000 -# 设置为true(默认false),则所有请求都重试,默认只支持get请求重试 -# 请谨慎设置,因为post请求大多都是写入请求,如果要支持重试,确保服务的幂等性 -ribbon.OkToRetryOnAllOperations=false - # nacos cloud配置 spring.cloud.nacos.discovery.server-addr=${nacos.url} -nacos.config.server-addr=${nacos.url} +# 数据库配置 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.url=jdbc:mysql://${mysql.host}/sop?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&serverTimezone=Asia/Shanghai spring.datasource.username=${mysql.username} spring.datasource.password=${mysql.password} -# 不用改 -mybatis.fill.com.gitee.fastmybatis.core.support.DateFillInsert=gmt_create -mybatis.fill.com.gitee.fastmybatis.core.support.DateFillUpdate=gmt_modified - -# 文件上传配置 -spring.servlet.multipart.enabled=true -# 这里设置大一点没关系,真实大小由upload.max-file-size控制 -spring.servlet.multipart.max-file-size=50MB - -# 允许上传文件大小,不能超过这个值,单位:B,KB,MB -upload.max-file-size=2MB - -# zipkin服务跟踪 -spring.zipkin.base-url=${zipkin.url} -# 设置sleuth收集信息的比率,默认0.1,最大是1,数字越大越耗性能 -spring.sleuth.sampler.probability=1 - logging.level.com.gitee=debug \ No newline at end of file diff --git a/sop-sdk/sdk-java/src/main/java/com/gitee/sop/sdk/client/OpenRequest.java b/sop-sdk/sdk-java/src/main/java/com/gitee/sop/sdk/client/OpenRequest.java index c04f2792..6f55ddf5 100644 --- a/sop-sdk/sdk-java/src/main/java/com/gitee/sop/sdk/client/OpenRequest.java +++ b/sop-sdk/sdk-java/src/main/java/com/gitee/sop/sdk/client/OpenRequest.java @@ -42,7 +42,7 @@ public class OpenRequest { } return openHttp.get(url, header); } else { - return openHttp.requestJson(url, JSON.toJSONString(form), header); + return openHttp.request(url, form, header, requestMethod); } } } catch (IOException e) { From 8530867653b96b54d687e57b2172ffe9e3e7b074 Mon Sep 17 00:00:00 2001 From: tanghc Date: Fri, 10 Jan 2020 20:20:56 +0800 Subject: [PATCH 03/55] =?UTF-8?q?=E7=BD=91=E5=85=B3=E4=BA=8C=E5=90=88?= =?UTF-8?q?=E4=B8=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sop/gateway/config/GatewayConfig.java | 37 ---------------- .../gitee/sop/gateway/config/ZuulConfig.java | 43 ------------------- 2 files changed, 80 deletions(-) delete mode 100644 sop-gateway/src/main/java/com/gitee/sop/gateway/config/GatewayConfig.java delete mode 100644 sop-gateway/src/main/java/com/gitee/sop/gateway/config/ZuulConfig.java diff --git a/sop-gateway/src/main/java/com/gitee/sop/gateway/config/GatewayConfig.java b/sop-gateway/src/main/java/com/gitee/sop/gateway/config/GatewayConfig.java deleted file mode 100644 index 56d66b9d..00000000 --- a/sop-gateway/src/main/java/com/gitee/sop/gateway/config/GatewayConfig.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.gitee.sop.gateway.config; - -import com.gitee.sop.gatewaycommon.gateway.configuration.AlipayGatewayConfiguration; -import org.springframework.context.annotation.Configuration; - - -/** - * 使用Spring Cloud Gateway - * - * 注意:下面两个只能使用一个。 - * - * 使用前,前往启动类SopGatewayApplication.java 注释掉@EnableZuulProxy - */ - -/** - * 开通支付宝开放平台能力 - * @author tanghc - */ - -//@Configuration -public class GatewayConfig extends AlipayGatewayConfiguration { - -} - -/** - * 开通淘宝开放平能力 - */ -//@Configuration -//public class GatewayConfig extends TaobaoGatewayConfiguration { -// -// { -// Map appSecretStore = new HashMap(); -// appSecretStore.put("taobao_test", "G9w0BAQEFAAOCAQ8AMIIBCgKCA"); -// ApiContext.getApiConfig().addAppSecret(appSecretStore); -// } -//} - 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 deleted file mode 100644 index a4e04211..00000000 --- a/sop-gateway/src/main/java/com/gitee/sop/gateway/config/ZuulConfig.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.gitee.sop.gateway.config; - -/** - * 使用Spring Cloud Zuul,推荐使用 - * - * 注意:下面两个只能使用一个 - */ - -import com.gitee.sop.gatewaycommon.zuul.configuration.AlipayZuulConfiguration; -import org.springframework.context.annotation.Configuration; - -/** - * 开通支付宝开放平台能力 - * @author tanghc - */ -//@Configuration -public class ZuulConfig extends AlipayZuulConfiguration { - -} - -/** - * 开通淘宝开放平台能力 - * @author tanghc - */ -//@Configuration -//public class ZuulConfig extends TaobaoZuulConfiguration { -// static { -// new ManagerInitializer(); -// } -//} - -/** - * 对接easyopen - */ -//@Configuration -//public class ZuulConfig extends EasyopenZuulConfiguration { -// static { -// Map appSecretMap = new HashMap<>(); -// appSecretMap.put("easyopen_test", "G9w0BAQEFAAOCAQ8AMIIBCgKCA"); -// ApiConfig.getInstance().addAppSecret(appSecretMap); -// } -// -//} From e995a2a64fef594e5dc1e98856e4c9fa59689539 Mon Sep 17 00:00:00 2001 From: tanghc Date: Fri, 10 Jan 2020 20:38:38 +0800 Subject: [PATCH 04/55] =?UTF-8?q?=E7=BD=91=E5=85=B3=E4=BA=8C=E5=90=88?= =?UTF-8?q?=E4=B8=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1 - changelog.md | 6 ++++++ doc/docs/files/10096_使用SpringCloudGateway.md | 2 +- sop-auth/pom.xml | 2 +- sop-common/pom.xml | 2 +- sop-common/sop-bridge-gateway/pom.xml | 6 +++--- sop-common/sop-bridge-zuul/pom.xml | 6 +++--- sop-common/sop-gateway-common/pom.xml | 4 ++-- sop-common/sop-service-common/pom.xml | 4 ++-- sop-example/sop-book/sop-book-web/pom.xml | 2 +- sop-example/sop-easyopen/pom.xml | 2 +- sop-example/sop-springmvc/pom.xml | 2 +- sop-example/sop-story/sop-story-web/pom.xml | 2 +- sop-gateway/pom.xml | 2 +- sop-website/pom.xml | 2 +- 15 files changed, 25 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index ab343d4e..406774fb 100644 --- a/README.md +++ b/README.md @@ -80,7 +80,6 @@ SOP封装了开放平台大部分功能包括:签名验证、统一异常处 ## 分支说明 - master:发版分支 -- spring-cloud-gateway:Spring Cloud Gateway作为网关(不推荐) - develop:日常开发分支 - eureka:使用eureka注册中心 - 1.x:老的1.x版本代码 diff --git a/changelog.md b/changelog.md index d7202a97..249a7b9f 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,11 @@ # changelog +## 2.6.0 + +- 重构spring cloud gateway网关 +- zuul和gateway网关二合一 +- 代码优化 + ## 2.5.10 - 优化签名认证,优化校验日志打印 diff --git a/doc/docs/files/10096_使用SpringCloudGateway.md b/doc/docs/files/10096_使用SpringCloudGateway.md index cdad27e0..68d59c37 100644 --- a/doc/docs/files/10096_使用SpringCloudGateway.md +++ b/doc/docs/files/10096_使用SpringCloudGateway.md @@ -9,7 +9,7 @@ sop-bridge-gateway - 2.5.10-SNAPSHOT + 对应版本 ``` diff --git a/sop-auth/pom.xml b/sop-auth/pom.xml index a17fdc20..06a0fc2c 100644 --- a/sop-auth/pom.xml +++ b/sop-auth/pom.xml @@ -26,7 +26,7 @@ com.gitee.sop sop-service-common - 2.5.10-SNAPSHOT + 2.6.0-SNAPSHOT diff --git a/sop-common/pom.xml b/sop-common/pom.xml index 09743364..6a26af74 100644 --- a/sop-common/pom.xml +++ b/sop-common/pom.xml @@ -5,7 +5,7 @@ 4.0.0 com.gitee.sop sop-common - 2.5.10-SNAPSHOT + 2.6.0-SNAPSHOT pom diff --git a/sop-common/sop-bridge-gateway/pom.xml b/sop-common/sop-bridge-gateway/pom.xml index 328eaf22..04766774 100644 --- a/sop-common/sop-bridge-gateway/pom.xml +++ b/sop-common/sop-bridge-gateway/pom.xml @@ -5,10 +5,10 @@ sop-common com.gitee.sop - 2.5.10-SNAPSHOT + 2.6.0-SNAPSHOT 4.0.0 - 2.5.10-SNAPSHOT + 2.6.0-SNAPSHOT sop-bridge-gateway @@ -16,7 +16,7 @@ com.gitee.sop sop-gateway-common - 2.5.10-SNAPSHOT + 2.6.0-SNAPSHOT diff --git a/sop-common/sop-bridge-zuul/pom.xml b/sop-common/sop-bridge-zuul/pom.xml index 1fa813b4..2b2f483e 100644 --- a/sop-common/sop-bridge-zuul/pom.xml +++ b/sop-common/sop-bridge-zuul/pom.xml @@ -5,10 +5,10 @@ sop-common com.gitee.sop - 2.5.10-SNAPSHOT + 2.6.0-SNAPSHOT 4.0.0 - 2.5.10-SNAPSHOT + 2.6.0-SNAPSHOT sop-bridge-zuul @@ -16,7 +16,7 @@ com.gitee.sop sop-gateway-common - 2.5.10-SNAPSHOT + 2.6.0-SNAPSHOT diff --git a/sop-common/sop-gateway-common/pom.xml b/sop-common/sop-gateway-common/pom.xml index 1486cd9f..7c3e9b7f 100644 --- a/sop-common/sop-gateway-common/pom.xml +++ b/sop-common/sop-gateway-common/pom.xml @@ -5,11 +5,11 @@ com.gitee.sop sop-common - 2.5.10-SNAPSHOT + 2.6.0-SNAPSHOT ../pom.xml sop-gateway-common - 2.5.10-SNAPSHOT + 2.6.0-SNAPSHOT jar sop-gateway-common diff --git a/sop-common/sop-service-common/pom.xml b/sop-common/sop-service-common/pom.xml index 3abf6f8c..01a6fff7 100644 --- a/sop-common/sop-service-common/pom.xml +++ b/sop-common/sop-service-common/pom.xml @@ -6,11 +6,11 @@ com.gitee.sop sop-common - 2.5.10-SNAPSHOT + 2.6.0-SNAPSHOT ../pom.xml sop-service-common - 2.5.10-SNAPSHOT + 2.6.0-SNAPSHOT jar sop-service-common diff --git a/sop-example/sop-book/sop-book-web/pom.xml b/sop-example/sop-book/sop-book-web/pom.xml index 68c3dfe5..335b4762 100644 --- a/sop-example/sop-book/sop-book-web/pom.xml +++ b/sop-example/sop-book/sop-book-web/pom.xml @@ -28,7 +28,7 @@ com.gitee.sop sop-service-common - 2.5.10-SNAPSHOT + 2.6.0-SNAPSHOT com.gitee.sop diff --git a/sop-example/sop-easyopen/pom.xml b/sop-example/sop-easyopen/pom.xml index 02829e7f..b998dc17 100644 --- a/sop-example/sop-easyopen/pom.xml +++ b/sop-example/sop-easyopen/pom.xml @@ -29,7 +29,7 @@ com.gitee.sop sop-service-common - 2.5.10-SNAPSHOT + 2.6.0-SNAPSHOT diff --git a/sop-example/sop-story/sop-story-web/pom.xml b/sop-example/sop-story/sop-story-web/pom.xml index 1df94a82..0943327a 100644 --- a/sop-example/sop-story/sop-story-web/pom.xml +++ b/sop-example/sop-story/sop-story-web/pom.xml @@ -28,7 +28,7 @@ com.gitee.sop sop-service-common - 2.5.10-SNAPSHOT + 2.6.0-SNAPSHOT com.gitee.sop diff --git a/sop-gateway/pom.xml b/sop-gateway/pom.xml index 8352f1d3..0778cc65 100644 --- a/sop-gateway/pom.xml +++ b/sop-gateway/pom.xml @@ -32,7 +32,7 @@ sop-bridge-gateway - 2.5.10-SNAPSHOT + 2.6.0-SNAPSHOT diff --git a/sop-website/pom.xml b/sop-website/pom.xml index 1e4d8251..2bf3e40f 100644 --- a/sop-website/pom.xml +++ b/sop-website/pom.xml @@ -35,7 +35,7 @@ com.gitee.sop sop-gateway-common - 2.5.10-SNAPSHOT + 2.6.0-SNAPSHOT From 59289cb1704a8c2cbb680c11f4e5b8ffe8b45801 Mon Sep 17 00:00:00 2001 From: tanghc Date: Fri, 10 Jan 2020 20:41:17 +0800 Subject: [PATCH 05/55] 2.6.0 --- changelog.md | 6 ++++++ doc/docs/files/10096_使用SpringCloudGateway.md | 2 +- sop-auth/pom.xml | 2 +- sop-common/pom.xml | 2 +- sop-common/sop-bridge-gateway/pom.xml | 6 +++--- sop-common/sop-bridge-zuul/pom.xml | 6 +++--- sop-common/sop-gateway-common/pom.xml | 4 ++-- sop-common/sop-service-common/pom.xml | 4 ++-- sop-example/sop-book/sop-book-web/pom.xml | 2 +- sop-example/sop-easyopen/pom.xml | 2 +- sop-example/sop-springmvc/pom.xml | 2 +- sop-example/sop-story/sop-story-web/pom.xml | 2 +- sop-gateway/pom.xml | 2 +- sop-website/pom.xml | 2 +- 14 files changed, 25 insertions(+), 19 deletions(-) diff --git a/changelog.md b/changelog.md index d7202a97..249a7b9f 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,11 @@ # changelog +## 2.6.0 + +- 重构spring cloud gateway网关 +- zuul和gateway网关二合一 +- 代码优化 + ## 2.5.10 - 优化签名认证,优化校验日志打印 diff --git a/doc/docs/files/10096_使用SpringCloudGateway.md b/doc/docs/files/10096_使用SpringCloudGateway.md index cdad27e0..870d58a7 100644 --- a/doc/docs/files/10096_使用SpringCloudGateway.md +++ b/doc/docs/files/10096_使用SpringCloudGateway.md @@ -9,7 +9,7 @@ sop-bridge-gateway - 2.5.10-SNAPSHOT + 2.6.0-SNAPSHOT ``` diff --git a/sop-auth/pom.xml b/sop-auth/pom.xml index a17fdc20..06a0fc2c 100644 --- a/sop-auth/pom.xml +++ b/sop-auth/pom.xml @@ -26,7 +26,7 @@ com.gitee.sop sop-service-common - 2.5.10-SNAPSHOT + 2.6.0-SNAPSHOT diff --git a/sop-common/pom.xml b/sop-common/pom.xml index 09743364..6a26af74 100644 --- a/sop-common/pom.xml +++ b/sop-common/pom.xml @@ -5,7 +5,7 @@ 4.0.0 com.gitee.sop sop-common - 2.5.10-SNAPSHOT + 2.6.0-SNAPSHOT pom diff --git a/sop-common/sop-bridge-gateway/pom.xml b/sop-common/sop-bridge-gateway/pom.xml index 328eaf22..04766774 100644 --- a/sop-common/sop-bridge-gateway/pom.xml +++ b/sop-common/sop-bridge-gateway/pom.xml @@ -5,10 +5,10 @@ sop-common com.gitee.sop - 2.5.10-SNAPSHOT + 2.6.0-SNAPSHOT 4.0.0 - 2.5.10-SNAPSHOT + 2.6.0-SNAPSHOT sop-bridge-gateway @@ -16,7 +16,7 @@ com.gitee.sop sop-gateway-common - 2.5.10-SNAPSHOT + 2.6.0-SNAPSHOT diff --git a/sop-common/sop-bridge-zuul/pom.xml b/sop-common/sop-bridge-zuul/pom.xml index 1fa813b4..2b2f483e 100644 --- a/sop-common/sop-bridge-zuul/pom.xml +++ b/sop-common/sop-bridge-zuul/pom.xml @@ -5,10 +5,10 @@ sop-common com.gitee.sop - 2.5.10-SNAPSHOT + 2.6.0-SNAPSHOT 4.0.0 - 2.5.10-SNAPSHOT + 2.6.0-SNAPSHOT sop-bridge-zuul @@ -16,7 +16,7 @@ com.gitee.sop sop-gateway-common - 2.5.10-SNAPSHOT + 2.6.0-SNAPSHOT diff --git a/sop-common/sop-gateway-common/pom.xml b/sop-common/sop-gateway-common/pom.xml index 1486cd9f..7c3e9b7f 100644 --- a/sop-common/sop-gateway-common/pom.xml +++ b/sop-common/sop-gateway-common/pom.xml @@ -5,11 +5,11 @@ com.gitee.sop sop-common - 2.5.10-SNAPSHOT + 2.6.0-SNAPSHOT ../pom.xml sop-gateway-common - 2.5.10-SNAPSHOT + 2.6.0-SNAPSHOT jar sop-gateway-common diff --git a/sop-common/sop-service-common/pom.xml b/sop-common/sop-service-common/pom.xml index 3abf6f8c..01a6fff7 100644 --- a/sop-common/sop-service-common/pom.xml +++ b/sop-common/sop-service-common/pom.xml @@ -6,11 +6,11 @@ com.gitee.sop sop-common - 2.5.10-SNAPSHOT + 2.6.0-SNAPSHOT ../pom.xml sop-service-common - 2.5.10-SNAPSHOT + 2.6.0-SNAPSHOT jar sop-service-common diff --git a/sop-example/sop-book/sop-book-web/pom.xml b/sop-example/sop-book/sop-book-web/pom.xml index 68c3dfe5..335b4762 100644 --- a/sop-example/sop-book/sop-book-web/pom.xml +++ b/sop-example/sop-book/sop-book-web/pom.xml @@ -28,7 +28,7 @@ com.gitee.sop sop-service-common - 2.5.10-SNAPSHOT + 2.6.0-SNAPSHOT com.gitee.sop diff --git a/sop-example/sop-easyopen/pom.xml b/sop-example/sop-easyopen/pom.xml index 02829e7f..b998dc17 100644 --- a/sop-example/sop-easyopen/pom.xml +++ b/sop-example/sop-easyopen/pom.xml @@ -29,7 +29,7 @@ com.gitee.sop sop-service-common - 2.5.10-SNAPSHOT + 2.6.0-SNAPSHOT diff --git a/sop-example/sop-story/sop-story-web/pom.xml b/sop-example/sop-story/sop-story-web/pom.xml index 1df94a82..0943327a 100644 --- a/sop-example/sop-story/sop-story-web/pom.xml +++ b/sop-example/sop-story/sop-story-web/pom.xml @@ -28,7 +28,7 @@ com.gitee.sop sop-service-common - 2.5.10-SNAPSHOT + 2.6.0-SNAPSHOT com.gitee.sop diff --git a/sop-gateway/pom.xml b/sop-gateway/pom.xml index 8352f1d3..0778cc65 100644 --- a/sop-gateway/pom.xml +++ b/sop-gateway/pom.xml @@ -32,7 +32,7 @@ sop-bridge-gateway - 2.5.10-SNAPSHOT + 2.6.0-SNAPSHOT diff --git a/sop-website/pom.xml b/sop-website/pom.xml index 1e4d8251..2bf3e40f 100644 --- a/sop-website/pom.xml +++ b/sop-website/pom.xml @@ -35,7 +35,7 @@ com.gitee.sop sop-gateway-common - 2.5.10-SNAPSHOT + 2.6.0-SNAPSHOT From b107886ed9b46bbfdd7cdf624c4c84eed81e1b48 Mon Sep 17 00:00:00 2001 From: tanghc Date: Fri, 10 Jan 2020 20:46:12 +0800 Subject: [PATCH 06/55] 2.6.0 --- sop-common/pom.xml | 8 ++++++++ sop-common/sop-bridge-gateway/pom.xml | 1 + sop-common/sop-bridge-zuul/pom.xml | 1 + 3 files changed, 10 insertions(+) diff --git a/sop-common/pom.xml b/sop-common/pom.xml index 6a26af74..7878108f 100644 --- a/sop-common/pom.xml +++ b/sop-common/pom.xml @@ -134,6 +134,14 @@ + + + spring-milestones + Spring Milestones + https://repo.spring.io/milestone + + + diff --git a/sop-common/sop-bridge-gateway/pom.xml b/sop-common/sop-bridge-gateway/pom.xml index 04766774..95217036 100644 --- a/sop-common/sop-bridge-gateway/pom.xml +++ b/sop-common/sop-bridge-gateway/pom.xml @@ -6,6 +6,7 @@ sop-common com.gitee.sop 2.6.0-SNAPSHOT + ../pom.xml 4.0.0 2.6.0-SNAPSHOT diff --git a/sop-common/sop-bridge-zuul/pom.xml b/sop-common/sop-bridge-zuul/pom.xml index 2b2f483e..9ed09852 100644 --- a/sop-common/sop-bridge-zuul/pom.xml +++ b/sop-common/sop-bridge-zuul/pom.xml @@ -6,6 +6,7 @@ sop-common com.gitee.sop 2.6.0-SNAPSHOT + ../pom.xml 4.0.0 2.6.0-SNAPSHOT From 06c800cbdd559346366fb38e945dba3bb4386508 Mon Sep 17 00:00:00 2001 From: tanghc Date: Fri, 10 Jan 2020 20:55:34 +0800 Subject: [PATCH 07/55] 2.6.0 --- sop-gateway/pom.xml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sop-gateway/pom.xml b/sop-gateway/pom.xml index 0778cc65..c35c96c8 100644 --- a/sop-gateway/pom.xml +++ b/sop-gateway/pom.xml @@ -26,11 +26,13 @@ + com.gitee.sop - - sop-bridge-gateway 2.6.0-SNAPSHOT From 1a787c182abf4b0aa9d46ab487c391051331d95f Mon Sep 17 00:00:00 2001 From: tanghc Date: Fri, 10 Jan 2020 21:31:41 +0800 Subject: [PATCH 08/55] 2.6.0 --- sop-gateway/pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sop-gateway/pom.xml b/sop-gateway/pom.xml index c35c96c8..fb2d5b50 100644 --- a/sop-gateway/pom.xml +++ b/sop-gateway/pom.xml @@ -27,13 +27,13 @@ com.gitee.sop - sop-bridge-gateway + 2.6.0-SNAPSHOT From 0935a185fa75a8105e75a161360f32745aa9dc27 Mon Sep 17 00:00:00 2001 From: tanghc Date: Fri, 10 Jan 2020 21:32:18 +0800 Subject: [PATCH 09/55] 2.6.0 --- doc/docs/_sidebar.md | 66 ++++++++++++++++++++++---------------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/doc/docs/_sidebar.md b/doc/docs/_sidebar.md index d72faede..f62469f7 100644 --- a/doc/docs/_sidebar.md +++ b/doc/docs/_sidebar.md @@ -1,35 +1,35 @@ -* [首页](/?t=1574408534264) +* [首页](/?t=1578663129148) * 开发文档 - * [快速体验](files/10010_快速体验.md?t=1574408534265) - * [项目接入到SOP](files/10011_项目接入到SOP.md?t=1574408534281) - * [新增接口](files/10020_新增接口.md?t=1574408534281) - * [开发流程](files/10021_开发流程.md?t=1574408534281) - * [业务参数校验](files/10030_业务参数校验.md?t=1574408534281) - * [错误处理](files/10040_错误处理.md?t=1574408534281) - * [编写文档](files/10041_编写文档.md?t=1574408534282) - * [接口交互详解](files/10050_接口交互详解.md?t=1574408534282) - * [easyopen支持](files/10070_easyopen支持.md?t=1574408534282) - * [使用签名校验工具](files/10080_使用签名校验工具.md?t=1574408534282) - * [ISV管理](files/10085_ISV管理.md?t=1574408534282) - * [自定义返回结果](files/10087_自定义返回结果.md?t=1574408534282) - * [自定义过滤器](files/10088_自定义过滤器.md?t=1574408534282) - * [自定义校验token](files/10089_自定义校验token.md?t=1574408534282) - * [路由授权](files/10090_路由授权.md?t=1574408534282) - * [接口限流](files/10092_接口限流.md?t=1574408534282) - * [监控日志](files/10093_监控日志.md?t=1574408534282) - * [SDK开发](files/10095_SDK开发.md?t=1574408534283) - * [使用SpringCloudGateway](files/10096_使用SpringCloudGateway.md?t=1574408534283) - * [应用授权](files/10097_应用授权.md?t=1574408534283) - * [提供restful接口](files/10100_提供restful接口.md?t=1574408534283) - * [文件上传](files/10104_文件上传.md?t=1574408534283) - * [配置Sleuth链路追踪](files/10109_配置Sleuth链路追踪.md?t=1574408534283) - * [预发布灰度发布](files/10110_预发布灰度发布.md?t=1574408534283) - * [动态修改请求参数](files/10111_动态修改请求参数.md?t=1574408534283) - * [使用eureka](files/10112_使用eureka.md?t=1574408534283) - * [扩展其它注册中心](files/10113_扩展其它注册中心.md?t=1574408534283) + * [快速体验](files/10010_快速体验.md?t=1578663129153) + * [项目接入到SOP](files/10011_项目接入到SOP.md?t=1578663129189) + * [新增接口](files/10020_新增接口.md?t=1578663129189) + * [开发流程](files/10021_开发流程.md?t=1578663129189) + * [业务参数校验](files/10030_业务参数校验.md?t=1578663129189) + * [错误处理](files/10040_错误处理.md?t=1578663129190) + * [编写文档](files/10041_编写文档.md?t=1578663129190) + * [接口交互详解](files/10050_接口交互详解.md?t=1578663129190) + * [easyopen支持](files/10070_easyopen支持.md?t=1578663129191) + * [使用签名校验工具](files/10080_使用签名校验工具.md?t=1578663129191) + * [ISV管理](files/10085_ISV管理.md?t=1578663129191) + * [自定义返回结果](files/10087_自定义返回结果.md?t=1578663129191) + * [自定义过滤器](files/10088_自定义过滤器.md?t=1578663129191) + * [自定义校验token](files/10089_自定义校验token.md?t=1578663129191) + * [路由授权](files/10090_路由授权.md?t=1578663129191) + * [接口限流](files/10092_接口限流.md?t=1578663129192) + * [监控日志](files/10093_监控日志.md?t=1578663129192) + * [SDK开发](files/10095_SDK开发.md?t=1578663129192) + * [使用SpringCloudGateway](files/10096_使用SpringCloudGateway.md?t=1578663129192) + * [应用授权](files/10097_应用授权.md?t=1578663129192) + * [提供restful接口](files/10100_提供restful接口.md?t=1578663129192) + * [文件上传](files/10104_文件上传.md?t=1578663129192) + * [配置Sleuth链路追踪](files/10109_配置Sleuth链路追踪.md?t=1578663129193) + * [预发布灰度发布](files/10110_预发布灰度发布.md?t=1578663129193) + * [动态修改请求参数](files/10111_动态修改请求参数.md?t=1578663129193) + * [使用eureka](files/10112_使用eureka.md?t=1578663129193) + * [扩展其它注册中心](files/10113_扩展其它注册中心.md?t=1578663129193) * 原理分析 - * [原理分析之@ApiMapping](files/90010_原理分析之@ApiMapping.md?t=1574408534283) - * [原理分析之如何存储路由](files/90011_原理分析之如何存储路由.md?t=1574408534283) - * [原理分析之如何路由](files/90012_原理分析之如何路由.md?t=1574408534283) - * [原理分析之文档归纳](files/90013_原理分析之文档归纳.md?t=1574408534284) - * [常见问题](files/90100_常见问题.md?t=1574408534284) + * [原理分析之@ApiMapping](files/90010_原理分析之@ApiMapping.md?t=1578663129194) + * [原理分析之如何存储路由](files/90011_原理分析之如何存储路由.md?t=1578663129194) + * [原理分析之如何路由](files/90012_原理分析之如何路由.md?t=1578663129194) + * [原理分析之文档归纳](files/90013_原理分析之文档归纳.md?t=1578663129194) + * [常见问题](files/90100_常见问题.md?t=1578663129194) From 7d759024b7c24ef33524338e07c2901222d4c46e Mon Sep 17 00:00:00 2001 From: tanghc Date: Sat, 11 Jan 2020 10:53:27 +0800 Subject: [PATCH 10/55] 2.6.0 --- sop-2.2.0.sql | 23 - sop-2.4.0.sql | 1 - sop-2.5.0.sql | 1 - .../sop/adminserver/api/service/LogApi.java | 2 +- sop-mysql5.6以下版本.sql | 396 ++++++++++++++++++ sop.sql | 4 +- 6 files changed, 400 insertions(+), 27 deletions(-) delete mode 100644 sop-2.2.0.sql delete mode 100644 sop-2.4.0.sql delete mode 100644 sop-2.5.0.sql create mode 100644 sop-mysql5.6以下版本.sql diff --git a/sop-2.2.0.sql b/sop-2.2.0.sql deleted file mode 100644 index 8a01be97..00000000 --- a/sop-2.2.0.sql +++ /dev/null @@ -1,23 +0,0 @@ -use sop; - -DROP TABLE IF EXISTS `config_service_route`; - -CREATE TABLE `config_service_route` ( - `id` varchar(128) NOT NULL DEFAULT '' COMMENT '路由id', - `service_id` varchar(128) NOT NULL DEFAULT '', - `name` varchar(128) NOT NULL DEFAULT '' COMMENT '接口名', - `version` varchar(64) NOT NULL DEFAULT '' COMMENT '版本号', - `predicates` varchar(256) DEFAULT NULL COMMENT '路由断言(SpringCloudGateway专用)', - `filters` varchar(256) DEFAULT NULL COMMENT '路由过滤器(SpringCloudGateway专用)', - `uri` varchar(128) NOT NULL DEFAULT '' COMMENT '路由规则转发的目标uri', - `path` varchar(128) NOT NULL DEFAULT '' COMMENT 'uri后面跟的path', - `order` int(11) NOT NULL DEFAULT '0' COMMENT '路由执行的顺序', - `ignore_validate` tinyint(4) NOT NULL DEFAULT '0' COMMENT '是否忽略验证,业务参数验证除外', - `status` tinyint(4) NOT NULL DEFAULT '1' COMMENT '状态,0:待审核,1:启用,2:禁用', - `merge_result` tinyint(4) NOT NULL DEFAULT '0' COMMENT '是否合并结果', - `permission` tinyint(4) NOT NULL DEFAULT '0' COMMENT '是否需要授权才能访问', - `gmt_create` datetime DEFAULT CURRENT_TIMESTAMP, - `gmt_modified` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - PRIMARY KEY (`id`), - KEY `idx_serviceid` (`service_id`) USING BTREE -) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='路由配置'; diff --git a/sop-2.4.0.sql b/sop-2.4.0.sql deleted file mode 100644 index 6f5243f7..00000000 --- a/sop-2.4.0.sql +++ /dev/null @@ -1 +0,0 @@ -ALTER TABLE `sop`.`config_limit` ADD COLUMN `duration_seconds` INT NOT NULL DEFAULT 1 COMMENT '限流持续时间,默认1秒,即每durationSeconds秒允许多少请求(当limit_type=1时有效)' AFTER `exec_count_per_second`; \ No newline at end of file diff --git a/sop-2.5.0.sql b/sop-2.5.0.sql deleted file mode 100644 index 5743cdad..00000000 --- a/sop-2.5.0.sql +++ /dev/null @@ -1 +0,0 @@ -ALTER TABLE `sop`.`config_service_route` ADD COLUMN `need_token` TINYINT NOT NULL DEFAULT 0 COMMENT '是否需要token' AFTER `permission`; diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/LogApi.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/LogApi.java index e59d49c7..72ef5e55 100644 --- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/LogApi.java +++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/LogApi.java @@ -136,7 +136,7 @@ public class LogApi { private void checkInstance(String ipPort) { try { - String json = this.requestLogServer(ipPort, "listErrors"); + String json = this.requestLogServer(ipPort, SOP_LIST_ERRORS_PATH); JSONObject jsonObject = JSON.parseObject(json); if (!CODE_SUCCESS.equals(jsonObject.getString(CODE_KEY))) { log.error("请求结果:{}", json); diff --git a/sop-mysql5.6以下版本.sql b/sop-mysql5.6以下版本.sql new file mode 100644 index 00000000..7d0cd7fa --- /dev/null +++ b/sop-mysql5.6以下版本.sql @@ -0,0 +1,396 @@ + +CREATE DATABASE IF NOT EXISTS `sop` DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci; +USE `sop`; + + + + +SET @PREVIOUS_FOREIGN_KEY_CHECKS = @@FOREIGN_KEY_CHECKS; +SET FOREIGN_KEY_CHECKS = 0; + + +DROP TABLE IF EXISTS `user_info`; +DROP TABLE IF EXISTS `perm_role_permission`; +DROP TABLE IF EXISTS `perm_role`; +DROP TABLE IF EXISTS `perm_isv_role`; +DROP TABLE IF EXISTS `isv_keys`; +DROP TABLE IF EXISTS `isv_info`; +DROP TABLE IF EXISTS `config_route_limit`; +DROP TABLE IF EXISTS `config_route_base`; +DROP TABLE IF EXISTS `config_limit`; +DROP TABLE IF EXISTS `config_ip_blacklist`; +DROP TABLE IF EXISTS `config_gray_instance`; +DROP TABLE IF EXISTS `config_gray`; +DROP TABLE IF EXISTS `config_common`; +DROP TABLE IF EXISTS `admin_user_info`; +DROP TABLE IF EXISTS `config_service_route`; + + +CREATE TABLE `admin_user_info` ( + `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, + `username` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '用户名', + `password` VARCHAR(128) NOT NULL DEFAULT '' COMMENT '密码', + `status` TINYINT(3) UNSIGNED NOT NULL DEFAULT '1' COMMENT '状态,1:启用,2:禁用', + `gmt_create` DATETIME DEFAULT NULL, + `gmt_modified` DATETIME DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `uk_username` (`username`) USING BTREE +) ENGINE=INNODB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COMMENT='后台用户表'; + + +CREATE TABLE `config_common` ( + `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, + `config_group` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '配置分组', + `config_key` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '配置key', + `content` VARCHAR(128) NOT NULL DEFAULT '' COMMENT '内容', + `remark` VARCHAR(128) DEFAULT NULL COMMENT '备注', + `gmt_create` DATETIME DEFAULT NULL, + `gmt_modified` DATETIME DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `uk_groupkey` (`config_group`,`config_key`) USING BTREE +) ENGINE=INNODB DEFAULT CHARSET=utf8 COMMENT='通用配置表'; + + +CREATE TABLE `config_gray` ( + `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, + `service_id` VARCHAR(64) NOT NULL DEFAULT '', + `user_key_content` TEXT COMMENT '用户key,多个用引文逗号隔开', + `name_version_content` TEXT COMMENT '需要灰度的接口,goods.get1.0=1.2,多个用英文逗号隔开', + `gmt_create` DATETIME DEFAULT NULL, + `gmt_modified` DATETIME DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `uk_serviceid` (`service_id`) USING BTREE +) ENGINE=INNODB DEFAULT CHARSET=utf8 COMMENT='服务灰度配置'; + + +CREATE TABLE `config_gray_instance` ( + `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, + `instance_id` VARCHAR(128) NOT NULL DEFAULT '' COMMENT 'instance_id', + `service_id` VARCHAR(64) NOT NULL DEFAULT '' COMMENT 'service_id', + `status` TINYINT(4) NOT NULL DEFAULT '0' COMMENT '0:禁用,1:启用', + `gmt_create` DATETIME DEFAULT NULL, + `gmt_modified` DATETIME DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `uk_instanceid` (`instance_id`) USING BTREE, + KEY `idx_serviceid` (`service_id`) USING BTREE +) ENGINE=INNODB DEFAULT CHARSET=utf8 COMMENT='开启灰度服务器实例'; + + +CREATE TABLE `config_ip_blacklist` ( + `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, + `ip` VARCHAR(64) NOT NULL DEFAULT '' COMMENT 'ip', + `remark` VARCHAR(128) DEFAULT NULL COMMENT '备注', + `gmt_create` DATETIME DEFAULT NULL, + `gmt_modified` DATETIME DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `uk_ip` (`ip`) USING BTREE +) ENGINE=INNODB DEFAULT CHARSET=utf8 COMMENT='IP黑名单'; + + +CREATE TABLE `config_limit` ( + `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, + `route_id` VARCHAR(128) DEFAULT NULL COMMENT '路由id', + `app_key` VARCHAR(128) DEFAULT NULL, + `limit_ip` VARCHAR(300) DEFAULT NULL COMMENT '限流ip,多个用英文逗号隔开', + `service_id` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '服务id', + `limit_type` TINYINT(4) NOT NULL DEFAULT '1' COMMENT '限流策略,1:漏桶策略,2:令牌桶策略', + `exec_count_per_second` INT(11) DEFAULT NULL COMMENT '每秒可处理请求数', + `duration_seconds` INT(11) NOT NULL DEFAULT '1' COMMENT '限流持续时间,默认1秒,即每durationSeconds秒允许多少请求(当limit_type=1时有效)', + `limit_code` VARCHAR(64) DEFAULT NULL COMMENT '返回的错误码', + `limit_msg` VARCHAR(100) DEFAULT NULL COMMENT '返回的错误信息', + `token_bucket_count` INT(11) DEFAULT NULL COMMENT '令牌桶容量', + `limit_status` TINYINT(4) NOT NULL DEFAULT '0' COMMENT '限流开启状态,1:开启,0关闭', + `order_index` INT(11) NOT NULL DEFAULT '0' COMMENT '顺序,值小的优先执行', + `remark` VARCHAR(128) DEFAULT NULL COMMENT '备注', + `gmt_create` DATETIME DEFAULT NULL, + `gmt_modified` DATETIME DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=INNODB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8 COMMENT='限流配置'; + + +CREATE TABLE `config_route_base` ( + `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, + `route_id` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '路由id', + `status` TINYINT(4) NOT NULL DEFAULT '1' COMMENT '状态,1:启用,2:禁用', + `gmt_create` DATETIME DEFAULT NULL, + `gmt_modified` DATETIME DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `uk_routeid` (`route_id`) USING BTREE +) ENGINE=INNODB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8 COMMENT='路由配置表'; + + +CREATE TABLE `config_route_limit` ( + `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT, + `route_id` VARCHAR(64) NOT NULL COMMENT '路由id', + `service_id` VARCHAR(64) NOT NULL DEFAULT '', + `limit_type` TINYINT(4) NOT NULL DEFAULT '1' COMMENT '限流策略,1:漏桶策略,2:令牌桶策略', + `exec_count_per_second` INT(11) DEFAULT NULL COMMENT '每秒可处理请求数', + `limit_code` VARCHAR(64) DEFAULT NULL COMMENT '返回的错误码', + `limit_msg` VARCHAR(100) DEFAULT NULL COMMENT '返回的错误信息', + `token_bucket_count` INT(11) DEFAULT NULL COMMENT '令牌桶容量', + `limit_status` TINYINT(4) NOT NULL DEFAULT '0' COMMENT '限流开启状态,1:开启,0关闭', + `gmt_create` DATETIME DEFAULT NULL, + `gmt_modified` DATETIME DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `uk_routeid` (`route_id`) USING BTREE +) ENGINE=INNODB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8 COMMENT='路由限流配置'; + + +CREATE TABLE `isv_info` ( + `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, + `app_key` VARCHAR(100) NOT NULL COMMENT 'appKey', + `secret` VARCHAR(200) DEFAULT NULL COMMENT 'secret', + `pub_key` TEXT COMMENT '公钥', + `pri_key` TEXT COMMENT '私钥', + `status` TINYINT(4) UNSIGNED NOT NULL DEFAULT '0' COMMENT '1启用,2禁用', + `sign_type` TINYINT(4) NOT NULL DEFAULT '1' COMMENT '1:RSA2,2:MD5', + `remark` VARCHAR(128) DEFAULT NULL COMMENT '备注', + `gmt_create` DATETIME DEFAULT NULL, + `gmt_modified` DATETIME DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `uk_app_key` (`app_key`) +) ENGINE=INNODB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8 COMMENT='isv信息表'; + + +CREATE TABLE `isv_keys` ( + `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, + `app_key` VARCHAR(128) NOT NULL DEFAULT '', + `sign_type` TINYINT(4) NOT NULL DEFAULT '1' COMMENT '1:RSA2,2:MD5', + `secret` VARCHAR(200) NOT NULL DEFAULT '' COMMENT 'sign_type=2时使用', + `key_format` TINYINT(4) NOT NULL DEFAULT '1' COMMENT '秘钥格式,1:PKCS8(JAVA适用),2:PKCS1(非JAVA适用)', + `public_key_isv` TEXT NOT NULL COMMENT '开发者生成的公钥', + `private_key_isv` TEXT NOT NULL COMMENT '开发者生成的私钥(交给开发者)', + `public_key_platform` TEXT NOT NULL COMMENT '平台生成的公钥(交给开发者)', + `private_key_platform` TEXT NOT NULL COMMENT '平台生成的私钥', + `gmt_create` DATETIME DEFAULT NULL, + `gmt_modified` DATETIME DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `uk_appkey` (`app_key`) USING BTREE +) ENGINE=INNODB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8 COMMENT='ISV秘钥'; + + +CREATE TABLE `perm_isv_role` ( + `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, + `isv_id` BIGINT(20) NOT NULL COMMENT 'isv_info表id', + `role_code` VARCHAR(64) NOT NULL COMMENT '角色code', + `gmt_create` DATETIME DEFAULT NULL, + `gmt_modified` DATETIME DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `uk_user_role` (`isv_id`,`role_code`) +) ENGINE=INNODB AUTO_INCREMENT=59 DEFAULT CHARSET=utf8 COMMENT='isv角色'; + + +CREATE TABLE `perm_role` ( + `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, + `role_code` VARCHAR(64) NOT NULL COMMENT '角色代码', + `description` VARCHAR(64) NOT NULL COMMENT '角色描述', + `gmt_create` DATETIME DEFAULT NULL, + `gmt_modified` DATETIME DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `uk_code` (`role_code`) +) ENGINE=INNODB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 COMMENT='角色表'; + + +CREATE TABLE `perm_role_permission` ( + `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, + `role_code` VARCHAR(64) NOT NULL COMMENT '角色表code', + `route_id` VARCHAR(64) NOT NULL COMMENT 'api_id', + `gmt_create` DATETIME DEFAULT NULL, + `gmt_modified` DATETIME DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `uk_role_perm` (`role_code`,`route_id`) USING BTREE +) ENGINE=INNODB AUTO_INCREMENT=30 DEFAULT CHARSET=utf8 COMMENT='角色权限表'; + + +CREATE TABLE `user_info` ( + `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, + `username` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '用户名', + `password` VARCHAR(128) NOT NULL DEFAULT '' COMMENT '密码', + `nickname` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '昵称', + `gmt_create` DATETIME DEFAULT NULL, + `gmt_modified` DATETIME DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `idx_unamepwd` (`username`,`password`) USING BTREE +) ENGINE=INNODB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COMMENT='用户信息表'; + +CREATE TABLE `config_service_route` ( + `id` VARCHAR(128) NOT NULL DEFAULT '' COMMENT '路由id', + `service_id` VARCHAR(128) NOT NULL DEFAULT '', + `name` VARCHAR(128) NOT NULL DEFAULT '' COMMENT '接口名', + `version` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '版本号', + `predicates` VARCHAR(256) DEFAULT NULL COMMENT '路由断言(SpringCloudGateway专用)', + `filters` VARCHAR(256) DEFAULT NULL COMMENT '路由过滤器(SpringCloudGateway专用)', + `uri` VARCHAR(128) NOT NULL DEFAULT '' COMMENT '路由规则转发的目标uri', + `path` VARCHAR(128) NOT NULL DEFAULT '' COMMENT 'uri后面跟的path', + `order` INT(11) NOT NULL DEFAULT '0' COMMENT '路由执行的顺序', + `ignore_validate` TINYINT(4) NOT NULL DEFAULT '0' COMMENT '是否忽略验证,业务参数验证除外', + `status` TINYINT(4) NOT NULL DEFAULT '1' COMMENT '状态,0:待审核,1:启用,2:禁用', + `merge_result` TINYINT(4) NOT NULL DEFAULT '0' COMMENT '是否合并结果', + `permission` TINYINT(4) NOT NULL DEFAULT '0' COMMENT '是否需要授权才能访问', + `need_token` TINYINT(4) NOT NULL DEFAULT '0' COMMENT '是否需要token', + `gmt_create` DATETIME DEFAULT NULL, + `gmt_modified` DATETIME DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `idx_serviceid` (`service_id`) USING BTREE +) ENGINE=INNODB DEFAULT CHARSET=utf8 COMMENT='路由配置'; + + +SET FOREIGN_KEY_CHECKS = @PREVIOUS_FOREIGN_KEY_CHECKS; + + +SET @PREVIOUS_FOREIGN_KEY_CHECKS = @@FOREIGN_KEY_CHECKS; +SET FOREIGN_KEY_CHECKS = 0; + + +LOCK TABLES `admin_user_info` WRITE; +ALTER TABLE `admin_user_info` DISABLE KEYS; +INSERT INTO `admin_user_info` (`id`, `username`, `password`, `status`, `gmt_create`, `gmt_modified`) VALUES + (1,'admin','14e1b600b1fd579f47433b88e8d85291',1,'2019-04-02 19:55:26','2019-04-02 19:55:26'); +ALTER TABLE `admin_user_info` ENABLE KEYS; +UNLOCK TABLES; + + +LOCK TABLES `config_common` WRITE; +ALTER TABLE `config_common` DISABLE KEYS; +ALTER TABLE `config_common` ENABLE KEYS; +UNLOCK TABLES; + + +LOCK TABLES `config_gray` WRITE; +ALTER TABLE `config_gray` DISABLE KEYS; +ALTER TABLE `config_gray` ENABLE KEYS; +UNLOCK TABLES; + + +LOCK TABLES `config_gray_instance` WRITE; +ALTER TABLE `config_gray_instance` DISABLE KEYS; +ALTER TABLE `config_gray_instance` ENABLE KEYS; +UNLOCK TABLES; + + +LOCK TABLES `config_ip_blacklist` WRITE; +ALTER TABLE `config_ip_blacklist` DISABLE KEYS; +ALTER TABLE `config_ip_blacklist` ENABLE KEYS; +UNLOCK TABLES; + + +LOCK TABLES `config_limit` WRITE; +ALTER TABLE `config_limit` DISABLE KEYS; +INSERT INTO `config_limit` (`id`, `route_id`, `app_key`, `limit_ip`, `service_id`, `limit_type`, `exec_count_per_second`, `limit_code`, `limit_msg`, `token_bucket_count`, `limit_status`, `order_index`, `remark`, `gmt_create`, `gmt_modified`) VALUES + (1,'alipay.story.get1.0','','192.168.1.1,172.2.2.3','story-service',2,5,'','',6,1,3,NULL,'2019-05-17 19:21:35','2019-05-21 09:12:15'), + (2,'alipay.story.get1.0','2019032617262200001','','story-service',2,5,'service-budy','服务器忙',10,1,0,'','2019-05-17 19:39:30','2019-05-21 15:36:52'), + (3,'alipay.story.find1.0','20190331562013861008375808','','story-service',1,3,'service-busy','服务器忙',5,1,1,NULL,'2019-05-17 20:20:32','2019-05-20 17:40:17'), + (4,'alipay.story.get1.2','','','story-service',1,5,'service-busy','服务器忙',3,1,1,'','2019-05-20 16:27:21','2019-05-21 15:53:10'), + (5,'','20190401562373796095328256','','story-service',1,5,'service-busy','服务器忙',5,1,0,'这个appKey调用很频繁,重点照顾','2019-05-21 15:48:08','2019-05-21 18:45:32'), + (6,'','','10.1.30.54','story-service',1,5,'service-busy','服务器忙',5,1,0,'这个ip在攻击我们','2019-05-21 15:55:33','2019-05-21 18:17:29'), + (7,'story.get1.1','','10.1.30.54','story-service',1,5,'service-busy','服务器忙',5,1,0,NULL,'2019-05-21 16:30:48','2019-05-21 16:30:48'), + (8,'','20190513577548661718777857','10.1.30.54','story-service',1,5,'service-busy','服务器忙',5,1,0,NULL,'2019-05-21 17:10:45','2019-05-21 17:10:52'); +ALTER TABLE `config_limit` ENABLE KEYS; +UNLOCK TABLES; + + +LOCK TABLES `config_route_base` WRITE; +ALTER TABLE `config_route_base` DISABLE KEYS; +INSERT INTO `config_route_base` (`id`, `route_id`, `status`, `gmt_create`, `gmt_modified`) VALUES + (1,'story.get1.1',1,'2019-04-09 19:15:58','2019-04-09 19:16:54'), + (2,'alipay.story.get1.0',1,'2019-04-09 19:19:57','2019-04-19 14:45:33'), + (3,'alipay.story.find1.0',1,'2019-04-11 09:29:55','2019-04-11 09:35:02'), + (4,'alipay.book.story.get1.0',1,'2019-04-16 10:23:44','2019-04-16 10:23:44'), + (5,'spirngmvc.goods.get1.0',2,'2019-04-16 10:24:08','2019-04-16 10:24:08'), + (6,'alipay.category.get1.0',1,'2019-05-06 16:50:39','2019-05-20 17:01:48'), + (7,'permission.story.get1.0',1,'2019-05-06 20:03:17','2019-05-06 20:03:21'), + (8,'goods.add1.0',1,'2019-05-13 17:23:00','2019-05-13 17:23:11'); +ALTER TABLE `config_route_base` ENABLE KEYS; +UNLOCK TABLES; + + +LOCK TABLES `config_route_limit` WRITE; +ALTER TABLE `config_route_limit` DISABLE KEYS; +INSERT INTO `config_route_limit` (`id`, `route_id`, `service_id`, `limit_type`, `exec_count_per_second`, `limit_code`, `limit_msg`, `token_bucket_count`, `limit_status`, `gmt_create`, `gmt_modified`) VALUES + (1,'alipay.story.find1.0','story-service',1,10,'isp.service-busy','服务器正忙',NULL,1,'2019-04-10 20:55:08','2019-04-10 21:04:35'), + (2,'alipay.story.get1.0','story-service',2,5,'isp.service-busy','服务器正忙',5,0,'2019-04-10 21:05:51','2019-04-11 18:18:03'), + (3,'alipay.story.get1.2','story-service',2,10,'isp.service-busy','服务器正忙',3,1,'2019-04-11 17:26:04','2019-04-11 18:19:33'), + (4,'alipay.category.get1.0','story-service',1,5,'error-code','服务器忙',5,1,'2019-05-07 12:22:04','2019-05-07 12:25:06'); +ALTER TABLE `config_route_limit` ENABLE KEYS; +UNLOCK TABLES; + + +LOCK TABLES `isv_info` WRITE; +ALTER TABLE `isv_info` DISABLE KEYS; +INSERT INTO `isv_info` (`id`, `app_key`, `secret`, `pub_key`, `pri_key`, `status`, `sign_type`, `remark`, `gmt_create`, `gmt_modified`) VALUES + (1,'2019032617262200001','','MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlyb9aUBaljQP/vjmBFe1mF8HsWSvyfC2NTlpT/V9E+sBxTr8TSkbzJCeeeOEm4LCaVXL0Qz63MZoT24v7AIXTuMdj4jyiM/WJ4tjrWAgnmohNOegfntTto16C3l234vXz4ryWZMR/7W+MXy5B92wPGQEJ0LKFwNEoLspDEWZ7RdE53VH7w6y6sIZUfK+YkXWSwehfKPKlx+lDw3zRJ3/yvMF+U+BAdW/MfECe1GuBnCFKnlMRh3UKczWyXWkL6ItOpYHHJi/jx85op5BWDje2pY9QowzfN94+0DB3T7UvZeweu3zlP6diwAJDzLaFQX8ULfWhY+wfKxIRgs9NoiSAQIDAQAB','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=',1,1,NULL,'2019-03-27 10:10:34','2019-05-09 11:10:38'), + (3,'asdfasdf','','MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOJTAsGoAsNGJdzaWm835mtpcY2YxGr4NPjnhQmfUrPdT+Zgi6jmm+olYuygNeB8cOSALmTzgXlef+6SdwfRJVEMYVAO7hqF0Ood9zTOc+kolgnWJtqX54CoodfABt0SNS/bsr6hCAWu17RGnbgBaK+ZaJD3NVqXVXE8E30cYHiQIDAQAB','MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAM4lMCwagCw0Yl3Npabzfma2lxjZjEavg0+OeFCZ9Ss91P5mCLqOab6iVi7KA14Hxw5IAuZPOBeV5/7pJ3B9ElUQxhUA7uGoXQ6h33NM5z6SiWCdYm2pfngKih18AG3RI1L9uyvqEIBa7XtEaduAFor5lokPc1WpdVcTwTfRxgeJAgMBAAECgYAM3XFGL1k0aQiChiUCaEvJKTgAywLgHm/5dRC5JwKP8knqnn+I9P5QcV0jimPvaFjZ4VCdAvCjOC3EUNSvRn7wR2Lb1+BGZZePTdxtHWE2aqJ1W1SvgQTqMsLlPBRPnXo5XH/ng3WEH15ynd5NR035xAluaI0X/y+PsRxE6TlfIQJBAPSYUyXa2yaEqmvIN+ECKALCLLeDdi2YW3Kjahgz0X9V4Y4aTdrHh8y603zXC0Wy8HeOhwGoyciaS8SmjxCMn4UCQQDXweW8xsUreLH8hfVUtyiY/KgUz+R5foJDNXD7TLE9CDoPSHy09qBe99HyVCZg/gNJH4O+tNr6C4916dYaVk01AkBYZ2HOEc8ZmeOaty/zJHtfm9zbqykgi6upwISNINV8Z4bxfHJdO7bKeVANFBBf7a/aFmqXX/EmjxYJioW03o6dAkEAp7ViXJCtJpNU1pNSFZ2hgvmxtSu7zuyVWKSrw8rjYiuI5eRUe13RXsCHgzQB+Ra5exdyEsUGCaL+yosPD73RmQJBALGuM8EQUcBgrpgpeLZ39Ni1DYXYG9aj+u+ar/UL6kI1mCNFgwroO4EVIvXPVxikMxUgiE2tVaBML5nm8VDNJ7s=',2,1,NULL,'2019-03-27 11:01:11','2019-05-11 10:45:01'), + (5,'20190331562013861008375808','29864b93427447f5ac6c44df746f84ef','MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC4aMIx2q8rCVu5z6dgNQQSX2vwhvIcRb7FaqSk0ZK8AV9qQeE1TvfFVlAzOHlysE1yTRb0Mb6W2aw7IAS7Bkc3onYBQR4zNQYjYoDBzLukjF8o84hoVFRnh7sV8zszid2vb5H/YQr3M+5sYhlXY8KfILk3vhdbWpHM/umplcrxlwIDAQAB','MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBALhowjHarysJW7nPp2A1BBJfa/CG8hxFvsVqpKTRkrwBX2pB4TVO98VWUDM4eXKwTXJNFvQxvpbZrDsgBLsGRzeidgFBHjM1BiNigMHMu6SMXyjziGhUVGeHuxXzOzOJ3a9vkf9hCvcz7mxiGVdjwp8guTe+F1takcz+6amVyvGXAgMBAAECgYBj40LFVGoryp7n0CYeg7kX5p4GJGKCk/jY4IIcUPTFZ4zydorxoDuvpag9hmqqh/r7XeyAC23sMi4LvLUzRRxPh+7PuwL6nLce7vytsMCZQTPpBgz7dUfbi2HAxsuMOLjH3sVGycutARJsz6bT+9PyBEuVtUqwBrDGpFvwT0z6yQJBAOANC8nysb+O4rn/fbJtHIhtQoV74yu00mLnfwv8/J1+WyAEc32WZ4KYINqCe8ft1UknhPQx9UV6JaPCnlpF6w0CQQDStJhd38uQ7dVUQZHGP24xS/K38AYiSheEr7uewhkJfC2cKqE/lBk3oEG4s7asjhwlFLWLWSBLVM/Ta9Yj0hYzAkBe82hxl1bY9bcEWFBu02rqLlOouk4V8bXPkIf5DqgIHsqDkR9Ys+r+H3ac4/uNSS/ApuzjiGCHpzJYalwtqb/pAkEAvAKlSm5dCC8QAaSYXJtQyfAI3hPwhTwzjBP6iAiNqqcBU62+QCr37Wiz/Alv4LzVZEj8TSDz7gP5hZ9dbo0RfQJBALJ7NhTaeMN4jxBJ6Xg4rNZPb4yhAXuFxCp+a+FyXTsbWnW/ar8KJ3LHox0GOao6wne4qN3h7eqLOrYnnvOSFl0=',1,2,NULL,'2019-03-31 20:34:12','2019-04-19 17:30:09'), + (6,'20190331562037310372184064','d6b2a6603236491f87eed958292be136','','',2,2,NULL,'2019-03-31 22:07:20','2019-05-07 18:14:53'), + (7,'20190401562373672858288128','','MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCOgSo6GfwM8a+rUT4m61nZa7q5cJpjL7luxQKuJvkMl/QydVrzRPinCh6zqgBJDa7YY2X6z5TyTkjYuDkYMrdyHcYvCDuJ0NpRPZMR+QDE70yp9wJ+kOqTa8bepJtxzuCYLxFz+wRsIFt0nIxC6ttCaM9OEw/Bflhws3xczw4uqQIDAQAB','MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAI6BKjoZ/Azxr6tRPibrWdlrurlwmmMvuW7FAq4m+QyX9DJ1WvNE+KcKHrOqAEkNrthjZfrPlPJOSNi4ORgyt3Idxi8IO4nQ2lE9kxH5AMTvTKn3An6Q6pNrxt6km3HO4JgvEXP7BGwgW3ScjELq20Joz04TD8F+WHCzfFzPDi6pAgMBAAECgYA/zuQ6ieILZbjUDBe5U46yxQMh/6KRoQ/14m81zauckPm+EkA8R3jTSru+lPN1wpO0vqUuLf6ylI0XxT2DcUokOgY07ZdE54pu5XAsyY0eanFwt6C1LrHYpORV3Mp9XuI3fXrxYqVlxLuj1N7MGinXUuW7aZCHaEuSnZ55OL9dkQJBANKOeFiYDISSuIFHSrndSgr+a8E44jS/2/7lE49p5l3WVOFTHh0IZQNTs/IKsKJkUnYDE4W/Ab7NTnWZpXYeM30CQQCtQrtxPEzLl4dtupPOBJJoApj2lq7Q6tIGx178K6wS9Rz3GEvkA7fz1Tpm+nmPZflWZ9mVmEaVuMTMpl3HN/edAkBylyzx8lYltIALg5QskT1hvFNChkW9tYjyMROzIkxIV4Q8WPLzlAT9iYlOOfkld/nU1hnC2VAG2k9P+z2sigU1AkBAl1AptsEqZSMn1RalBy9NdypvQ12IpQIHZOwUNnO/3YEe3P/t0TUSwbs0CMyomOuLOsvy6QHnbypu4Na1HjhBAkAWjtdhuvU15HAa5jMgiUVfQM3YFuz2k3QkRagtZZ33bqnYs4wNxEZqB5t+vEj+8r3fmSN0BpNR1VW71j53Ir0H',1,1,NULL,'2019-04-01 20:24:01','2019-04-01 20:27:33'), + (8,'20190401562373796095328256','','MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCbxn0En2cj29t8i+m1dT7seF9XQx3cEaoClXFTlmc78Y1ZuQFbyY99VSwv8JbtpGxPvBSVD9SPmXWNBRBbSHT+gxStcdXD9QeD3knGFy/1V+z3E2Rj/6LIlFmgTlGh1fmEgttPjsUW1Dj704/ydyIrw+CAyAMKQyrFg0wYmNW+UQIDAQAB','MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAJvGfQSfZyPb23yL6bV1Pux4X1dDHdwRqgKVcVOWZzvxjVm5AVvJj31VLC/wlu2kbE+8FJUP1I+ZdY0FEFtIdP6DFK1x1cP1B4PeScYXL/VX7PcTZGP/osiUWaBOUaHV+YSC20+OxRbUOPvTj/J3IivD4IDIAwpDKsWDTBiY1b5RAgMBAAECgYAE27/ycPZKjATgcYyseCeqQGbY1eMMhhCDXB3YuYwmtnXuInMEZdjv08Q5CovqhYJLSlZp/8BlaifcahgEgNIFQXmxAF0U0HsNC6W4Dk1gGgQaVmYaZv5ex7uIcFB1qFvlO60kWf82YeRnO5KsFBODOJ1XSNwqjL2GeLSHBSVyQQJBAOsvDmClBsETSdiNSFMz+D9WCnCh1Ip4AoCzA/yG+PRSwYjZDdceP2DXieiZXPlxTFZ7MIXxAafgeyeQA2hpkQUCQQCpkCUSbrZ+nd4BYdnxZOSf0//cUT0o6+3kROX7gsXV7zRAWWxojT6DkGVlduDLZM/hjWeHRjWUxKC/jgbzvundAkBckhUSrWJPNQxoFJRXS6l3JKLPWqOSLVKu3ce/6lCrurc66lSsS9eegrhhuZwDAzmNAMhEsGx6a72OAP2WZ5cRAkBd8cT4X2qw4BpePa6YdcPNYZHCqSfvgje9XwbkwGGH1A3pESJlEsxt7BShkKmfRu1+E/AmHJoXIJHHT5M+fKnpAkA+VfyAAviKeCwUSq+5oUa0B+ozEA3frp/40cKQP7k02aamocAQCDRaC1ZlWffeQqYMnYe1/Mjr/SdX/Ut3X0CC',1,1,NULL,'2019-04-01 20:24:25','2019-04-01 20:24:48'), + (9,'201904035630907729292csharp','','MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5+OvJxeSzf44NxQ/cl7Ii+BzPg2k6sRcvH4ffOtU5Dzq1/oEvg02nxIhmwOHBZmjbmuUu0aLsfglUTAwqfXftfAKZidshsgj9NNh0/kxk0avRZ1UoljWGz/FxVZA0ogbxxhohPZ9jWcD+eBQcIwF2DtHfAJqWWZrYFnCMeHD8mPzxo2kwXSvDzi0vf9I2tKiYvNG26a9FqeYtPOoi81sdS3+70HOMdxP8ejXtyfnKpKz7Dx506LCIRS5moWS3Q5eTLV3NGX/1CSJ8wpQA2DAQTjVhX5eVu7Yqz12t8W+sjWM/tHUR6cgwYYR10p7tSCeCPzkigjGxKm4cYXWtATQJQIDAQAB','MIIEowIBAAKCAQEA5+OvJxeSzf44NxQ/cl7Ii+BzPg2k6sRcvH4ffOtU5Dzq1/oEvg02nxIhmwOHBZmjbmuUu0aLsfglUTAwqfXftfAKZidshsgj9NNh0/kxk0avRZ1UoljWGz/FxVZA0ogbxxhohPZ9jWcD+eBQcIwF2DtHfAJqWWZrYFnCMeHD8mPzxo2kwXSvDzi0vf9I2tKiYvNG26a9FqeYtPOoi81sdS3+70HOMdxP8ejXtyfnKpKz7Dx506LCIRS5moWS3Q5eTLV3NGX/1CSJ8wpQA2DAQTjVhX5eVu7Yqz12t8W+sjWM/tHUR6cgwYYR10p7tSCeCPzkigjGxKm4cYXWtATQJQIDAQABAoIBAHFDsgrrJca+NKEan77ycwx3jnKx4WrWjOF4zVKL9AQjiSYDNgvKknJyPb3kpC/lEoHdxGERHSzJoxib7DkoIqRQYhPxj73pxj5QfYk3P7LLJNNg/LTrpXDb3nL8JV9wIflGf87qQvstZTDJEyFWE4jBs7Hr0BxovWvri8InnzkmERJ1cbGJgNHe1Y3Zo2tw0yaHxQCxLuajP+notRZhD9bEp7uKeI0w9AvlW6k8m/7y10F0BK/TlyW8rQiEC391yOiRYoMcUh4hd2Q9bMx3jngZgX8PXIvZZcup4/pvWlv1alwhB2tsnLdazP62r1MO80vLyLunzGO+7WwCjEYlVaECgYEA+lQRFmbhKaPuAuXMtY31Fbga8nedka5TjnEV7+/kX+yowE2OlNujF+ZG8UTddTxAGv56yVNi/mjRlgD74j8z0eOsgvOq9mwbCrgLhLo51H9O/wAxtb+hBKtC5l50pBr4gER6d8W6EQNTSGojnMIaLXTkAZ5Qf6Z8e2HFVdOn0X0CgYEA7SSrTokwzukt5KldNu5ukyyd+C3D1i6orbg6qD73EP9CfNMfGSBn7dDv9wMSJH01+Ty+RgTROgtjGRDbMJWnfbdt/61NePr9ar5sb6Nbsf7/I0w7cZF5dsaFYgzaOfQYquzXPbLQHkpMT64bqpv/Mwy4F2lFvaYWY5fA4pC2uckCgYEAg75Ym9ybJaoTqky8ttQ2Jy8UZ4VSVQhVC0My02sCWwWXLlXi8y7An+Rec73Ve0yxREOn5WrQT6pkmzh7V/ABWrYi5WxODpCIjtSbo0fLBa3Wqle00b0/hdCITetqIa/cFs1zUrOqICgK3bKWeXqiAkhhcwSZwwSgwOKM04Wn7ZUCgYBvhHX2mbdVJfyJ8kc+hMOE/E9RHRxiBVEXWHJlGi8PVCqNDq8qHr4g7Mdbzprig+s0yKblwHAvrpkseWvKHiZEjVTyDipHgShY4TGXEigVvUd37uppTrLi8xpYcJjS9gH/px7VCdiq1d+q/MJP6coJ1KphgATm2UrgDMYNBWaYWQKBgEHRxrmER7btUF60/YgcqPHFc8RpYQB2ZZE0kyKGDqk2Data1XYUY6vsPAU28yRLAaWr/D2H17iyLkxP80VLm6QhifxCadv90Q/Wl1DFfOJQMW6avyQ0so6G0wFq/LJxaFK4iLXQn1RJnmTp6BYiJMmK2BhFbRzw8ssMoF6ad2rr',1,1,NULL,'2019-04-03 19:54:05','2019-04-03 20:11:58'), + (10,'easyopen_test','G9w0BAQEFAAOCAQ8AMIIBCgKCA','','',1,2,NULL,'2019-04-19 17:19:34','2019-04-19 17:30:09'), + (11,'20190513577548661718777856','','MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCdGjz3IE2VQteDjQaFacXLCAIqdEIIVcf7LW7f142V55Q0xtcjDTOHjBHExZsG64/Y5WKz4oQVWGnXwtrled8Qg0YAA7ueat8mE8NzJSm9txbfU9hwXB77nJxVkFyaSG1p0IZFrNQpbbUxTX9755deP7DdcSF148LLr091V++S3QIDAQAB','MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAJ0aPPcgTZVC14ONBoVpxcsIAip0QghVx/stbt/XjZXnlDTG1yMNM4eMEcTFmwbrj9jlYrPihBVYadfC2uV53xCDRgADu55q3yYTw3MlKb23Ft9T2HBcHvucnFWQXJpIbWnQhkWs1ClttTFNf3vnl14/sN1xIXXjwsuvT3VX75LdAgMBAAECgYB68z/nQDa3q/oykDocS21qujfHtfi/wTKjVylAsdezC+wnab6RRhGf8XUuhGARiGWpn8whcBNjCTC8lVju4vQ5IIx4Hb74vwDDMtNXeqwkLmARLYu2ELibauezSeqom8/J8cR3ho7Hr4VHPTiC8qvePRmu8AvXVQz2T7SOhEjDGQJBAOm8XOivr+atiknLbQhmo508ON3sjoN9VMwK9cmnup+ZPCsurJTHRja0MJQNdOXObUVJ6wJhs1PHWT+vITfXGJ8CQQCsESzxOYTkZaqBUFjbWVf1rSwjOOsylweTuq44YIJkHhwMjHf3kN/UTXbxsBPUGeT7/+2K5UwQ9snUPr0yTBcDAkA0FMezBWqxgNu+g7iA1bYBVCjrskkzHVsmuA56Z4hbBZ71lEnaQOjxSYdFhhYVGsEYXlciSbjWoyXM3e4N7jzLAkB0ejv+H33CTsAZQZalBdnxSQTz4vf0CyDp9BkzuMELnQZHyF79i2i5gqbd/N+vWMgVfq4CtC3F3gnKT54rii6ZAkAMBIvHriT5Zbs1fW+oxBP1rHqdsRvqs1zEyIadvJgKAFwFEisryfdw2mWm3vxQQ22RlOquBiZEDIlyM0z2m9PJ',1,1,NULL,'2019-05-13 17:24:17','2019-05-13 17:24:17'), + (12,'20190513577548661718777857','','MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCdGjz3IE2VQteDjQaFacXLCAIqdEIIVcf7LW7f142V55Q0xtcjDTOHjBHExZsG64/Y5WKz4oQVWGnXwtrled8Qg0YAA7ueat8mE8NzJSm9txbfU9hwXB77nJxVkFyaSG1p0IZFrNQpbbUxTX9755deP7DdcSF148LLr091V++S3QIDAQAB','MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAJ0aPPcgTZVC14ONBoVpxcsIAip0QghVx/stbt/XjZXnlDTG1yMNM4eMEcTFmwbrj9jlYrPihBVYadfC2uV53xCDRgADu55q3yYTw3MlKb23Ft9T2HBcHvucnFWQXJpIbWnQhkWs1ClttTFNf3vnl14/sN1xIXXjwsuvT3VX75LdAgMBAAECgYB68z/nQDa3q/oykDocS21qujfHtfi/wTKjVylAsdezC+wnab6RRhGf8XUuhGARiGWpn8whcBNjCTC8lVju4vQ5IIx4Hb74vwDDMtNXeqwkLmARLYu2ELibauezSeqom8/J8cR3ho7Hr4VHPTiC8qvePRmu8AvXVQz2T7SOhEjDGQJBAOm8XOivr+atiknLbQhmo508ON3sjoN9VMwK9cmnup+ZPCsurJTHRja0MJQNdOXObUVJ6wJhs1PHWT+vITfXGJ8CQQCsESzxOYTkZaqBUFjbWVf1rSwjOOsylweTuq44YIJkHhwMjHf3kN/UTXbxsBPUGeT7/+2K5UwQ9snUPr0yTBcDAkA0FMezBWqxgNu+g7iA1bYBVCjrskkzHVsmuA56Z4hbBZ71lEnaQOjxSYdFhhYVGsEYXlciSbjWoyXM3e4N7jzLAkB0ejv+H33CTsAZQZalBdnxSQTz4vf0CyDp9BkzuMELnQZHyF79i2i5gqbd/N+vWMgVfq4CtC3F3gnKT54rii6ZAkAMBIvHriT5Zbs1fW+oxBP1rHqdsRvqs1zEyIadvJgKAFwFEisryfdw2mWm3vxQQ22RlOquBiZEDIlyM0z2m9PJ',1,1,NULL,'2019-05-13 17:24:17','2019-05-13 17:24:17'); +ALTER TABLE `isv_info` ENABLE KEYS; +UNLOCK TABLES; + + +LOCK TABLES `isv_keys` WRITE; +ALTER TABLE `isv_keys` DISABLE KEYS; +INSERT INTO `isv_keys` (`id`, `app_key`, `sign_type`, `secret`, `key_format`, `public_key_isv`, `private_key_isv`, `public_key_platform`, `private_key_platform`, `gmt_create`, `gmt_modified`) VALUES + (1,'2019032617262200001',1,'',1,'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlyb9aUBaljQP/vjmBFe1mF8HsWSvyfC2NTlpT/V9E+sBxTr8TSkbzJCeeeOEm4LCaVXL0Qz63MZoT24v7AIXTuMdj4jyiM/WJ4tjrWAgnmohNOegfntTto16C3l234vXz4ryWZMR/7W+MXy5B92wPGQEJ0LKFwNEoLspDEWZ7RdE53VH7w6y6sIZUfK+YkXWSwehfKPKlx+lDw3zRJ3/yvMF+U+BAdW/MfECe1GuBnCFKnlMRh3UKczWyXWkL6ItOpYHHJi/jx85op5BWDje2pY9QowzfN94+0DB3T7UvZeweu3zlP6diwAJDzLaFQX8ULfWhY+wfKxIRgs9NoiSAQIDAQAB','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=','','','2019-08-13 15:18:39','2019-08-13 15:18:39'), + (2,'asdfasdf',1,'',1,'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOJTAsGoAsNGJdzaWm835mtpcY2YxGr4NPjnhQmfUrPdT+Zgi6jmm+olYuygNeB8cOSALmTzgXlef+6SdwfRJVEMYVAO7hqF0Ood9zTOc+kolgnWJtqX54CoodfABt0SNS/bsr6hCAWu17RGnbgBaK+ZaJD3NVqXVXE8E30cYHiQIDAQAB','MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAM4lMCwagCw0Yl3Npabzfma2lxjZjEavg0+OeFCZ9Ss91P5mCLqOab6iVi7KA14Hxw5IAuZPOBeV5/7pJ3B9ElUQxhUA7uGoXQ6h33NM5z6SiWCdYm2pfngKih18AG3RI1L9uyvqEIBa7XtEaduAFor5lokPc1WpdVcTwTfRxgeJAgMBAAECgYAM3XFGL1k0aQiChiUCaEvJKTgAywLgHm/5dRC5JwKP8knqnn+I9P5QcV0jimPvaFjZ4VCdAvCjOC3EUNSvRn7wR2Lb1+BGZZePTdxtHWE2aqJ1W1SvgQTqMsLlPBRPnXo5XH/ng3WEH15ynd5NR035xAluaI0X/y+PsRxE6TlfIQJBAPSYUyXa2yaEqmvIN+ECKALCLLeDdi2YW3Kjahgz0X9V4Y4aTdrHh8y603zXC0Wy8HeOhwGoyciaS8SmjxCMn4UCQQDXweW8xsUreLH8hfVUtyiY/KgUz+R5foJDNXD7TLE9CDoPSHy09qBe99HyVCZg/gNJH4O+tNr6C4916dYaVk01AkBYZ2HOEc8ZmeOaty/zJHtfm9zbqykgi6upwISNINV8Z4bxfHJdO7bKeVANFBBf7a/aFmqXX/EmjxYJioW03o6dAkEAp7ViXJCtJpNU1pNSFZ2hgvmxtSu7zuyVWKSrw8rjYiuI5eRUe13RXsCHgzQB+Ra5exdyEsUGCaL+yosPD73RmQJBALGuM8EQUcBgrpgpeLZ39Ni1DYXYG9aj+u+ar/UL6kI1mCNFgwroO4EVIvXPVxikMxUgiE2tVaBML5nm8VDNJ7s=','','','2019-08-13 15:18:39','2019-08-13 15:18:39'), + (3,'20190331562013861008375808',2,'29864b93427447f5ac6c44df746f84ef',1,'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC4aMIx2q8rCVu5z6dgNQQSX2vwhvIcRb7FaqSk0ZK8AV9qQeE1TvfFVlAzOHlysE1yTRb0Mb6W2aw7IAS7Bkc3onYBQR4zNQYjYoDBzLukjF8o84hoVFRnh7sV8zszid2vb5H/YQr3M+5sYhlXY8KfILk3vhdbWpHM/umplcrxlwIDAQAB','MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBALhowjHarysJW7nPp2A1BBJfa/CG8hxFvsVqpKTRkrwBX2pB4TVO98VWUDM4eXKwTXJNFvQxvpbZrDsgBLsGRzeidgFBHjM1BiNigMHMu6SMXyjziGhUVGeHuxXzOzOJ3a9vkf9hCvcz7mxiGVdjwp8guTe+F1takcz+6amVyvGXAgMBAAECgYBj40LFVGoryp7n0CYeg7kX5p4GJGKCk/jY4IIcUPTFZ4zydorxoDuvpag9hmqqh/r7XeyAC23sMi4LvLUzRRxPh+7PuwL6nLce7vytsMCZQTPpBgz7dUfbi2HAxsuMOLjH3sVGycutARJsz6bT+9PyBEuVtUqwBrDGpFvwT0z6yQJBAOANC8nysb+O4rn/fbJtHIhtQoV74yu00mLnfwv8/J1+WyAEc32WZ4KYINqCe8ft1UknhPQx9UV6JaPCnlpF6w0CQQDStJhd38uQ7dVUQZHGP24xS/K38AYiSheEr7uewhkJfC2cKqE/lBk3oEG4s7asjhwlFLWLWSBLVM/Ta9Yj0hYzAkBe82hxl1bY9bcEWFBu02rqLlOouk4V8bXPkIf5DqgIHsqDkR9Ys+r+H3ac4/uNSS/ApuzjiGCHpzJYalwtqb/pAkEAvAKlSm5dCC8QAaSYXJtQyfAI3hPwhTwzjBP6iAiNqqcBU62+QCr37Wiz/Alv4LzVZEj8TSDz7gP5hZ9dbo0RfQJBALJ7NhTaeMN4jxBJ6Xg4rNZPb4yhAXuFxCp+a+FyXTsbWnW/ar8KJ3LHox0GOao6wne4qN3h7eqLOrYnnvOSFl0=','','','2019-08-13 15:18:39','2019-08-13 15:18:39'), + (4,'20190331562037310372184064',2,'d6b2a6603236491f87eed958292be136',1,'','','','','2019-08-13 15:18:39','2019-08-13 15:18:39'), + (5,'20190401562373672858288128',1,'',1,'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCOgSo6GfwM8a+rUT4m61nZa7q5cJpjL7luxQKuJvkMl/QydVrzRPinCh6zqgBJDa7YY2X6z5TyTkjYuDkYMrdyHcYvCDuJ0NpRPZMR+QDE70yp9wJ+kOqTa8bepJtxzuCYLxFz+wRsIFt0nIxC6ttCaM9OEw/Bflhws3xczw4uqQIDAQAB','MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAI6BKjoZ/Azxr6tRPibrWdlrurlwmmMvuW7FAq4m+QyX9DJ1WvNE+KcKHrOqAEkNrthjZfrPlPJOSNi4ORgyt3Idxi8IO4nQ2lE9kxH5AMTvTKn3An6Q6pNrxt6km3HO4JgvEXP7BGwgW3ScjELq20Joz04TD8F+WHCzfFzPDi6pAgMBAAECgYA/zuQ6ieILZbjUDBe5U46yxQMh/6KRoQ/14m81zauckPm+EkA8R3jTSru+lPN1wpO0vqUuLf6ylI0XxT2DcUokOgY07ZdE54pu5XAsyY0eanFwt6C1LrHYpORV3Mp9XuI3fXrxYqVlxLuj1N7MGinXUuW7aZCHaEuSnZ55OL9dkQJBANKOeFiYDISSuIFHSrndSgr+a8E44jS/2/7lE49p5l3WVOFTHh0IZQNTs/IKsKJkUnYDE4W/Ab7NTnWZpXYeM30CQQCtQrtxPEzLl4dtupPOBJJoApj2lq7Q6tIGx178K6wS9Rz3GEvkA7fz1Tpm+nmPZflWZ9mVmEaVuMTMpl3HN/edAkBylyzx8lYltIALg5QskT1hvFNChkW9tYjyMROzIkxIV4Q8WPLzlAT9iYlOOfkld/nU1hnC2VAG2k9P+z2sigU1AkBAl1AptsEqZSMn1RalBy9NdypvQ12IpQIHZOwUNnO/3YEe3P/t0TUSwbs0CMyomOuLOsvy6QHnbypu4Na1HjhBAkAWjtdhuvU15HAa5jMgiUVfQM3YFuz2k3QkRagtZZ33bqnYs4wNxEZqB5t+vEj+8r3fmSN0BpNR1VW71j53Ir0H','','','2019-08-13 15:18:39','2019-08-13 15:18:39'), + (6,'20190401562373796095328256',1,'',1,'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCbxn0En2cj29t8i+m1dT7seF9XQx3cEaoClXFTlmc78Y1ZuQFbyY99VSwv8JbtpGxPvBSVD9SPmXWNBRBbSHT+gxStcdXD9QeD3knGFy/1V+z3E2Rj/6LIlFmgTlGh1fmEgttPjsUW1Dj704/ydyIrw+CAyAMKQyrFg0wYmNW+UQIDAQAB','MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAJvGfQSfZyPb23yL6bV1Pux4X1dDHdwRqgKVcVOWZzvxjVm5AVvJj31VLC/wlu2kbE+8FJUP1I+ZdY0FEFtIdP6DFK1x1cP1B4PeScYXL/VX7PcTZGP/osiUWaBOUaHV+YSC20+OxRbUOPvTj/J3IivD4IDIAwpDKsWDTBiY1b5RAgMBAAECgYAE27/ycPZKjATgcYyseCeqQGbY1eMMhhCDXB3YuYwmtnXuInMEZdjv08Q5CovqhYJLSlZp/8BlaifcahgEgNIFQXmxAF0U0HsNC6W4Dk1gGgQaVmYaZv5ex7uIcFB1qFvlO60kWf82YeRnO5KsFBODOJ1XSNwqjL2GeLSHBSVyQQJBAOsvDmClBsETSdiNSFMz+D9WCnCh1Ip4AoCzA/yG+PRSwYjZDdceP2DXieiZXPlxTFZ7MIXxAafgeyeQA2hpkQUCQQCpkCUSbrZ+nd4BYdnxZOSf0//cUT0o6+3kROX7gsXV7zRAWWxojT6DkGVlduDLZM/hjWeHRjWUxKC/jgbzvundAkBckhUSrWJPNQxoFJRXS6l3JKLPWqOSLVKu3ce/6lCrurc66lSsS9eegrhhuZwDAzmNAMhEsGx6a72OAP2WZ5cRAkBd8cT4X2qw4BpePa6YdcPNYZHCqSfvgje9XwbkwGGH1A3pESJlEsxt7BShkKmfRu1+E/AmHJoXIJHHT5M+fKnpAkA+VfyAAviKeCwUSq+5oUa0B+ozEA3frp/40cKQP7k02aamocAQCDRaC1ZlWffeQqYMnYe1/Mjr/SdX/Ut3X0CC','','','2019-08-13 15:18:39','2019-08-13 15:18:39'), + (7,'201904035630907729292csharp',1,'',1,'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5+OvJxeSzf44NxQ/cl7Ii+BzPg2k6sRcvH4ffOtU5Dzq1/oEvg02nxIhmwOHBZmjbmuUu0aLsfglUTAwqfXftfAKZidshsgj9NNh0/kxk0avRZ1UoljWGz/FxVZA0ogbxxhohPZ9jWcD+eBQcIwF2DtHfAJqWWZrYFnCMeHD8mPzxo2kwXSvDzi0vf9I2tKiYvNG26a9FqeYtPOoi81sdS3+70HOMdxP8ejXtyfnKpKz7Dx506LCIRS5moWS3Q5eTLV3NGX/1CSJ8wpQA2DAQTjVhX5eVu7Yqz12t8W+sjWM/tHUR6cgwYYR10p7tSCeCPzkigjGxKm4cYXWtATQJQIDAQAB','MIIEowIBAAKCAQEA5+OvJxeSzf44NxQ/cl7Ii+BzPg2k6sRcvH4ffOtU5Dzq1/oEvg02nxIhmwOHBZmjbmuUu0aLsfglUTAwqfXftfAKZidshsgj9NNh0/kxk0avRZ1UoljWGz/FxVZA0ogbxxhohPZ9jWcD+eBQcIwF2DtHfAJqWWZrYFnCMeHD8mPzxo2kwXSvDzi0vf9I2tKiYvNG26a9FqeYtPOoi81sdS3+70HOMdxP8ejXtyfnKpKz7Dx506LCIRS5moWS3Q5eTLV3NGX/1CSJ8wpQA2DAQTjVhX5eVu7Yqz12t8W+sjWM/tHUR6cgwYYR10p7tSCeCPzkigjGxKm4cYXWtATQJQIDAQABAoIBAHFDsgrrJca+NKEan77ycwx3jnKx4WrWjOF4zVKL9AQjiSYDNgvKknJyPb3kpC/lEoHdxGERHSzJoxib7DkoIqRQYhPxj73pxj5QfYk3P7LLJNNg/LTrpXDb3nL8JV9wIflGf87qQvstZTDJEyFWE4jBs7Hr0BxovWvri8InnzkmERJ1cbGJgNHe1Y3Zo2tw0yaHxQCxLuajP+notRZhD9bEp7uKeI0w9AvlW6k8m/7y10F0BK/TlyW8rQiEC391yOiRYoMcUh4hd2Q9bMx3jngZgX8PXIvZZcup4/pvWlv1alwhB2tsnLdazP62r1MO80vLyLunzGO+7WwCjEYlVaECgYEA+lQRFmbhKaPuAuXMtY31Fbga8nedka5TjnEV7+/kX+yowE2OlNujF+ZG8UTddTxAGv56yVNi/mjRlgD74j8z0eOsgvOq9mwbCrgLhLo51H9O/wAxtb+hBKtC5l50pBr4gER6d8W6EQNTSGojnMIaLXTkAZ5Qf6Z8e2HFVdOn0X0CgYEA7SSrTokwzukt5KldNu5ukyyd+C3D1i6orbg6qD73EP9CfNMfGSBn7dDv9wMSJH01+Ty+RgTROgtjGRDbMJWnfbdt/61NePr9ar5sb6Nbsf7/I0w7cZF5dsaFYgzaOfQYquzXPbLQHkpMT64bqpv/Mwy4F2lFvaYWY5fA4pC2uckCgYEAg75Ym9ybJaoTqky8ttQ2Jy8UZ4VSVQhVC0My02sCWwWXLlXi8y7An+Rec73Ve0yxREOn5WrQT6pkmzh7V/ABWrYi5WxODpCIjtSbo0fLBa3Wqle00b0/hdCITetqIa/cFs1zUrOqICgK3bKWeXqiAkhhcwSZwwSgwOKM04Wn7ZUCgYBvhHX2mbdVJfyJ8kc+hMOE/E9RHRxiBVEXWHJlGi8PVCqNDq8qHr4g7Mdbzprig+s0yKblwHAvrpkseWvKHiZEjVTyDipHgShY4TGXEigVvUd37uppTrLi8xpYcJjS9gH/px7VCdiq1d+q/MJP6coJ1KphgATm2UrgDMYNBWaYWQKBgEHRxrmER7btUF60/YgcqPHFc8RpYQB2ZZE0kyKGDqk2Data1XYUY6vsPAU28yRLAaWr/D2H17iyLkxP80VLm6QhifxCadv90Q/Wl1DFfOJQMW6avyQ0so6G0wFq/LJxaFK4iLXQn1RJnmTp6BYiJMmK2BhFbRzw8ssMoF6ad2rr','','','2019-08-13 15:18:39','2019-08-13 15:18:39'), + (8,'easyopen_test',2,'G9w0BAQEFAAOCAQ8AMIIBCgKCA',1,'','','','','2019-08-13 15:18:39','2019-08-13 15:18:39'), + (9,'20190513577548661718777856',1,'',1,'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCdGjz3IE2VQteDjQaFacXLCAIqdEIIVcf7LW7f142V55Q0xtcjDTOHjBHExZsG64/Y5WKz4oQVWGnXwtrled8Qg0YAA7ueat8mE8NzJSm9txbfU9hwXB77nJxVkFyaSG1p0IZFrNQpbbUxTX9755deP7DdcSF148LLr091V++S3QIDAQAB','MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAJ0aPPcgTZVC14ONBoVpxcsIAip0QghVx/stbt/XjZXnlDTG1yMNM4eMEcTFmwbrj9jlYrPihBVYadfC2uV53xCDRgADu55q3yYTw3MlKb23Ft9T2HBcHvucnFWQXJpIbWnQhkWs1ClttTFNf3vnl14/sN1xIXXjwsuvT3VX75LdAgMBAAECgYB68z/nQDa3q/oykDocS21qujfHtfi/wTKjVylAsdezC+wnab6RRhGf8XUuhGARiGWpn8whcBNjCTC8lVju4vQ5IIx4Hb74vwDDMtNXeqwkLmARLYu2ELibauezSeqom8/J8cR3ho7Hr4VHPTiC8qvePRmu8AvXVQz2T7SOhEjDGQJBAOm8XOivr+atiknLbQhmo508ON3sjoN9VMwK9cmnup+ZPCsurJTHRja0MJQNdOXObUVJ6wJhs1PHWT+vITfXGJ8CQQCsESzxOYTkZaqBUFjbWVf1rSwjOOsylweTuq44YIJkHhwMjHf3kN/UTXbxsBPUGeT7/+2K5UwQ9snUPr0yTBcDAkA0FMezBWqxgNu+g7iA1bYBVCjrskkzHVsmuA56Z4hbBZ71lEnaQOjxSYdFhhYVGsEYXlciSbjWoyXM3e4N7jzLAkB0ejv+H33CTsAZQZalBdnxSQTz4vf0CyDp9BkzuMELnQZHyF79i2i5gqbd/N+vWMgVfq4CtC3F3gnKT54rii6ZAkAMBIvHriT5Zbs1fW+oxBP1rHqdsRvqs1zEyIadvJgKAFwFEisryfdw2mWm3vxQQ22RlOquBiZEDIlyM0z2m9PJ','','','2019-08-13 15:18:39','2019-08-13 15:18:39'), + (10,'20190513577548661718777857',1,'',1,'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCdGjz3IE2VQteDjQaFacXLCAIqdEIIVcf7LW7f142V55Q0xtcjDTOHjBHExZsG64/Y5WKz4oQVWGnXwtrled8Qg0YAA7ueat8mE8NzJSm9txbfU9hwXB77nJxVkFyaSG1p0IZFrNQpbbUxTX9755deP7DdcSF148LLr091V++S3QIDAQAB','MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAJ0aPPcgTZVC14ONBoVpxcsIAip0QghVx/stbt/XjZXnlDTG1yMNM4eMEcTFmwbrj9jlYrPihBVYadfC2uV53xCDRgADu55q3yYTw3MlKb23Ft9T2HBcHvucnFWQXJpIbWnQhkWs1ClttTFNf3vnl14/sN1xIXXjwsuvT3VX75LdAgMBAAECgYB68z/nQDa3q/oykDocS21qujfHtfi/wTKjVylAsdezC+wnab6RRhGf8XUuhGARiGWpn8whcBNjCTC8lVju4vQ5IIx4Hb74vwDDMtNXeqwkLmARLYu2ELibauezSeqom8/J8cR3ho7Hr4VHPTiC8qvePRmu8AvXVQz2T7SOhEjDGQJBAOm8XOivr+atiknLbQhmo508ON3sjoN9VMwK9cmnup+ZPCsurJTHRja0MJQNdOXObUVJ6wJhs1PHWT+vITfXGJ8CQQCsESzxOYTkZaqBUFjbWVf1rSwjOOsylweTuq44YIJkHhwMjHf3kN/UTXbxsBPUGeT7/+2K5UwQ9snUPr0yTBcDAkA0FMezBWqxgNu+g7iA1bYBVCjrskkzHVsmuA56Z4hbBZ71lEnaQOjxSYdFhhYVGsEYXlciSbjWoyXM3e4N7jzLAkB0ejv+H33CTsAZQZalBdnxSQTz4vf0CyDp9BkzuMELnQZHyF79i2i5gqbd/N+vWMgVfq4CtC3F3gnKT54rii6ZAkAMBIvHriT5Zbs1fW+oxBP1rHqdsRvqs1zEyIadvJgKAFwFEisryfdw2mWm3vxQQ22RlOquBiZEDIlyM0z2m9PJ','','','2019-08-13 15:18:39','2019-08-13 15:18:39'); +ALTER TABLE `isv_keys` ENABLE KEYS; +UNLOCK TABLES; + + +LOCK TABLES `perm_isv_role` WRITE; +ALTER TABLE `perm_isv_role` DISABLE KEYS; +INSERT INTO `perm_isv_role` (`id`, `isv_id`, `role_code`, `gmt_create`, `gmt_modified`) VALUES + (18,5,'normal','2019-03-31 22:07:50','2019-03-31 22:07:50'), + (32,7,'normal','2019-04-01 20:27:33','2019-04-01 20:27:33'), + (36,9,'normal','2019-04-03 20:11:58','2019-04-03 20:11:58'), + (37,10,'normal','2019-04-19 17:19:34','2019-04-19 17:19:34'), + (38,10,'vip','2019-04-19 17:19:34','2019-04-19 17:19:34'), + (52,6,'normal','2019-05-07 18:14:53','2019-05-07 18:14:53'), + (57,1,'normal','2019-05-09 11:10:38','2019-05-09 11:10:38'), + (58,11,'normal','2019-05-13 17:24:17','2019-05-13 17:24:17'); +ALTER TABLE `perm_isv_role` ENABLE KEYS; +UNLOCK TABLES; + + +LOCK TABLES `perm_role` WRITE; +ALTER TABLE `perm_role` DISABLE KEYS; +INSERT INTO `perm_role` (`id`, `role_code`, `description`, `gmt_create`, `gmt_modified`) VALUES + (1,'normal','普通权限','2019-03-29 15:00:10','2019-03-29 15:00:10'), + (2,'vip','VIP权限','2019-03-29 15:00:27','2019-03-29 15:00:27'); +ALTER TABLE `perm_role` ENABLE KEYS; +UNLOCK TABLES; + + +LOCK TABLES `perm_role_permission` WRITE; +ALTER TABLE `perm_role_permission` DISABLE KEYS; +INSERT INTO `perm_role_permission` (`id`, `role_code`, `route_id`, `gmt_create`, `gmt_modified`) VALUES + (29,'normal','permission.story.get1.0','2019-05-06 18:29:16','2019-05-06 18:29:16'); +ALTER TABLE `perm_role_permission` ENABLE KEYS; +UNLOCK TABLES; + + +LOCK TABLES `user_info` WRITE; +ALTER TABLE `user_info` DISABLE KEYS; +INSERT INTO `user_info` (`id`, `username`, `password`, `nickname`, `gmt_create`, `gmt_modified`) VALUES + (1,'zhangsan','123456','张三','2019-04-27 08:32:57','2019-04-27 08:32:57'); +ALTER TABLE `user_info` ENABLE KEYS; +UNLOCK TABLES; + + + + +SET FOREIGN_KEY_CHECKS = @PREVIOUS_FOREIGN_KEY_CHECKS; + + diff --git a/sop.sql b/sop.sql index 06acf0b0..4df5d424 100644 --- a/sop.sql +++ b/sop.sql @@ -1,4 +1,6 @@ - +/** +适用于MYSQL 5.6+版本 +**/ CREATE DATABASE IF NOT EXISTS `sop` DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci; USE `sop`; From c12eac02e6a26ea15321efe5d4d4c9c29c9933ff Mon Sep 17 00:00:00 2001 From: tanghc Date: Sun, 12 Jan 2020 09:11:57 +0800 Subject: [PATCH 11/55] 2.6.0 --- doc/docs/files/10010_快速体验.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/doc/docs/files/10010_快速体验.md b/doc/docs/files/10010_快速体验.md index 5f374f39..1f7acca0 100644 --- a/doc/docs/files/10010_快速体验.md +++ b/doc/docs/files/10010_快速体验.md @@ -3,7 +3,7 @@ > 运行环境:JDK8,Maven3,[Nacos](https://nacos.io/zh-cn/docs/what-is-nacos.html),Mysql - 安装并启动Nacos,[安装教程](https://nacos.io/zh-cn/docs/quick-start.html) -- 执行Mysql脚本`sop.sql` +- 执行Mysql脚本`sop.sql`(Mysql版本5.6+),5.6以下运行`sop-mysql5.6以下版本.sql` - IDE安装lombok插件,然后打开项目(IDEA下可以打开根pom.xml,然后open as project) - 启动网关:打开sop-gateway下的`application-dev.properties` 1. 修改数据库`username/password` @@ -22,4 +22,12 @@ 登录账号:admin/123456 +## 启动文档中心 + +文档中心代码在sop-website工程中 + +- 确保注册中心、网关、微服务正常启动 +- 修改sop-website下的application-dev.properties相关配置 +- 运行WebsiteServerApplication.java +- 访问http://localhost:8083 From 5a773745f99a6eaffdf04b56819dfad6e7f25674 Mon Sep 17 00:00:00 2001 From: tanghc Date: Mon, 13 Jan 2020 15:55:44 +0800 Subject: [PATCH 12/55] 3.0.0 --- changelog.md | 5 +- .../src/main/resources/sop-bridge.properties | 11 ++++ .../src/main/resources/sop-bridge.properties | 11 ++++ .../gatewaycommon/bean/RouteDefinition.java | 5 ++ .../gateway/ServerWebExchangeUtil.java | 30 +++-------- .../BaseGatewayConfiguration.java | 8 ++- .../gateway/filter/EnvGrayFilter.java | 3 ++ .../gateway/filter/IndexFilter.java | 25 +++++---- .../gateway/route/GatewayForwardChooser.java | 16 ++++++ .../route/BaseForwardChooser.java | 54 +++++++++++++++++++ .../gatewaycommon/route/ForwardChooser.java | 16 ++++++ .../sop/gatewaycommon/route/ForwardInfo.java | 13 +++++ .../configuration/BaseZuulConfiguration.java | 30 ++++++----- .../zuul/filter/PreEnvGrayFilter.java | 3 ++ .../zuul/route/SopRouteLocator.java | 18 +++++-- .../zuul/route/ZuulForwardChooser.java | 18 +++++++ .../sop/servercommon/bean/ServiceApiInfo.java | 2 + .../servercommon/manager/ApiMetaBuilder.java | 1 + .../mapping/ApiMappingHandlerMapping.java | 12 ++++- .../servercommon/mapping/ApiMappingInfo.java | 2 + .../mapping/ApiMappingRequestCondition.java | 5 ++ .../ApiMappingStringValueResolverVersion.java | 25 +++++++++ .../servercommon/route/RouteDefinition.java | 5 ++ .../storyweb/controller/AlipayController.java | 3 +- .../main/resources/META-INF/spring.factories | 0 .../main/resources/application-dev.properties | 15 +----- .../main/resources/public/pages/doc/doc.html | 26 +++++++-- .../main/resources/public/pages/doc/doc.js | 2 +- .../public/pages/sandbox/sandbox.html | 27 ++++++++-- 29 files changed, 305 insertions(+), 86 deletions(-) create mode 100644 sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/route/GatewayForwardChooser.java create mode 100644 sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/route/BaseForwardChooser.java create mode 100644 sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/route/ForwardChooser.java create mode 100644 sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/route/ForwardInfo.java create mode 100644 sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/route/ZuulForwardChooser.java create mode 100644 sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/mapping/ApiMappingStringValueResolverVersion.java rename {sop-common/sop-gateway-common => sop-gateway}/src/main/resources/META-INF/spring.factories (100%) diff --git a/changelog.md b/changelog.md index 249a7b9f..8a15f21a 100644 --- a/changelog.md +++ b/changelog.md @@ -1,10 +1,11 @@ # changelog -## 2.6.0 +## 3.0.0 - 重构spring cloud gateway网关 - zuul和gateway网关二合一 -- 代码优化 +- 精简配置文件 +- 优化文档中心页面 ## 2.5.10 diff --git a/sop-common/sop-bridge-gateway/src/main/resources/sop-bridge.properties b/sop-common/sop-bridge-gateway/src/main/resources/sop-bridge.properties index c3106eb8..b5c2e2e3 100644 --- a/sop-common/sop-bridge-gateway/src/main/resources/sop-bridge.properties +++ b/sop-common/sop-bridge-gateway/src/main/resources/sop-bridge.properties @@ -1,6 +1,17 @@ +# 固定不变,不能改 +spring.application.name=sop-gateway # 不用改,如果要改,请全局替换修改 sop.secret=MZZOUSTua6LzApIWXCwEgbBmxSzpzC +# nacos cloud配置 +spring.cloud.nacos.discovery.server-addr=${nacos.url} + +# 数据库配置 +spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver +spring.datasource.url=jdbc:mysql://${mysql.host}/sop?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&serverTimezone=Asia/Shanghai +spring.datasource.username=${mysql.username} +spring.datasource.password=${mysql.password} + # https://blog.csdn.net/qq_36872046/article/details/81058045 # 路由转发超时时间,毫秒,默认值1000,详见:RibbonClientConfiguration.DEFAULT_READ_TIMEOUT。 # 如果微服务端 处理时间过长,会导致ribbon read超时,解决办法将这个值调大一点 diff --git a/sop-common/sop-bridge-zuul/src/main/resources/sop-bridge.properties b/sop-common/sop-bridge-zuul/src/main/resources/sop-bridge.properties index 3a83a34f..4f0c045e 100644 --- a/sop-common/sop-bridge-zuul/src/main/resources/sop-bridge.properties +++ b/sop-common/sop-bridge-zuul/src/main/resources/sop-bridge.properties @@ -1,3 +1,5 @@ +# 固定不变,不能改 +spring.application.name=sop-gateway # 入口地址,不用改,默认是/zuul zuul.servlet-path=/api # 禁用默认的过滤器,不能删,不用改 @@ -6,6 +8,15 @@ zuul.Servlet30WrapperFilter.pre.disable=true # 不用改,如果要改,请全局替换修改 sop.secret=MZZOUSTua6LzApIWXCwEgbBmxSzpzC +# nacos cloud配置 +spring.cloud.nacos.discovery.server-addr=${nacos.url} + +# 数据库配置 +spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver +spring.datasource.url=jdbc:mysql://${mysql.host}/sop?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&serverTimezone=Asia/Shanghai +spring.datasource.username=${mysql.username} +spring.datasource.password=${mysql.password} + # https://blog.csdn.net/qq_36872046/article/details/81058045 # 路由转发超时时间,毫秒,默认值1000,详见:RibbonClientConfiguration.DEFAULT_READ_TIMEOUT。 # 如果微服务端 处理时间过长,会导致ribbon read超时,解决办法将这个值调大一点 diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/RouteDefinition.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/RouteDefinition.java index eb6fba9f..c8d239ef 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/RouteDefinition.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/RouteDefinition.java @@ -75,4 +75,9 @@ public class RouteDefinition { * 是否需要token */ private int needToken; + + /** + * 是否是兼容模式,即使用了@ApiAbility注解 + */ + private int compatibleMode; } \ No newline at end of file diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/ServerWebExchangeUtil.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/ServerWebExchangeUtil.java index 631fe2b4..e76ec24a 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/ServerWebExchangeUtil.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/ServerWebExchangeUtil.java @@ -8,6 +8,8 @@ import com.gitee.sop.gatewaycommon.gateway.common.RequestContentDataExtractor; import com.gitee.sop.gatewaycommon.gateway.common.SopServerHttpRequestDecorator; import com.gitee.sop.gatewaycommon.param.ApiParam; import com.gitee.sop.gatewaycommon.param.FormHttpOutputMessage; +import com.gitee.sop.gatewaycommon.route.ForwardInfo; +import com.gitee.sop.gatewaycommon.param.ParamNames; import com.gitee.sop.gatewaycommon.util.RequestUtil; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; @@ -57,20 +59,17 @@ public class ServerWebExchangeUtil { * 重定向 * * @param exchange exchange - * @param apiParam apiParam + * @param forwardInfo forwardInfo * @return 返回新的ServerWebExchange,配合chain.filter(newExchange);使用 */ - public static ServerWebExchange getForwardExchange(ServerWebExchange exchange, ApiParam apiParam) { - ServerHttpRequest newRequest = getForwardRequest(exchange.getRequest(), apiParam); + public static ServerWebExchange getForwardExchange(ServerWebExchange exchange, ForwardInfo forwardInfo) { + ServerHttpRequest newRequest = exchange.getRequest() + .mutate() + .header(ParamNames.HEADER_VERSION_NAME, forwardInfo.getVersion()) + .path(forwardInfo.getPath()).build(); return exchange.mutate().request(newRequest).build(); } - public static ServerHttpRequest getForwardRequest(ServerHttpRequest request, ApiParam apiParam) { - return request - .mutate() - .header(SopConstants.REDIRECT_VERSION_KEY, apiParam.fetchVersion()) - .path(getForwardPath(apiParam)).build(); - } /** * 构建一个接受请求体的request @@ -113,19 +112,6 @@ public class ServerWebExchangeUtil { return chain.filter(newExchange); } - private static String getForwardPath(ApiParam apiParam) { - // 如果有异常,则重定向到这个path - if (apiParam.getThrowable() != null) { - return VALIDATE_ERROR_PATH; - } - String forwardPath = UNKNOWN_PATH; - String method = apiParam.fetchName(); - if (org.springframework.util.StringUtils.hasText(method)) { - forwardPath = "/" + method + "/"; - } - return forwardPath; - } - public static ApiParam getApiParam(ServerWebExchange exchange, String body) { MediaType contentType = exchange.getRequest().getHeaders().getContentType(); if (contentType == null) { 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 d5d2375f..c191985d 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 @@ -4,12 +4,12 @@ import com.gitee.sop.gatewaycommon.bean.ApiConfig; import com.gitee.sop.gatewaycommon.gateway.controller.ConfigChannelController; import com.gitee.sop.gatewaycommon.gateway.controller.ErrorLogController; import com.gitee.sop.gatewaycommon.gateway.controller.GatewayController; -import com.gitee.sop.gatewaycommon.gateway.filter.EnvGrayFilter; import com.gitee.sop.gatewaycommon.gateway.filter.GatewayModifyResponseGatewayFilter; import com.gitee.sop.gatewaycommon.gateway.filter.IndexFilter; import com.gitee.sop.gatewaycommon.gateway.filter.LimitFilter; import com.gitee.sop.gatewaycommon.gateway.filter.ParameterFormatterFilter; import com.gitee.sop.gatewaycommon.gateway.handler.GatewayExceptionHandler; +import com.gitee.sop.gatewaycommon.gateway.route.GatewayForwardChooser; import com.gitee.sop.gatewaycommon.gateway.route.GatewayRouteCache; import com.gitee.sop.gatewaycommon.gateway.route.GatewayRouteRepository; import com.gitee.sop.gatewaycommon.manager.AbstractConfiguration; @@ -107,10 +107,8 @@ public class BaseGatewayConfiguration extends AbstractConfiguration { return gatewayRouteRepository; } - @Bean - EnvGrayFilter envGrayFilter() { - return new EnvGrayFilter(); + GatewayForwardChooser gatewayForwardChooser() { + return new GatewayForwardChooser(); } - } diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/EnvGrayFilter.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/EnvGrayFilter.java index 9c0f9fd0..84dbbed6 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/EnvGrayFilter.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/EnvGrayFilter.java @@ -15,7 +15,10 @@ import reactor.core.publisher.Mono; /** * @author tanghc + * @deprecated + * @see com.gitee.sop.gatewaycommon.gateway.route.GatewayForwardChooser */ +@Deprecated public class EnvGrayFilter implements GlobalFilter, Ordered { @Autowired diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/IndexFilter.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/IndexFilter.java index 9b380231..3019bf2b 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/IndexFilter.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/IndexFilter.java @@ -1,11 +1,11 @@ package com.gitee.sop.gatewaycommon.gateway.filter; -import com.gitee.sop.gatewaycommon.bean.SopConstants; import com.gitee.sop.gatewaycommon.exception.ApiException; import com.gitee.sop.gatewaycommon.gateway.ServerWebExchangeUtil; -import com.gitee.sop.gatewaycommon.manager.EnvironmentContext; +import com.gitee.sop.gatewaycommon.gateway.route.GatewayForwardChooser; import com.gitee.sop.gatewaycommon.manager.EnvironmentKeys; import com.gitee.sop.gatewaycommon.param.ApiParam; +import com.gitee.sop.gatewaycommon.route.ForwardInfo; import com.gitee.sop.gatewaycommon.validate.Validator; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; @@ -16,12 +16,10 @@ import org.springframework.core.annotation.Order; import org.springframework.core.io.buffer.DataBuffer; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; -import org.springframework.http.codec.HttpMessageReader; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.http.server.reactive.ServerHttpRequestDecorator; import org.springframework.web.reactive.function.BodyInserter; import org.springframework.web.reactive.function.BodyInserters; -import org.springframework.web.reactive.function.server.HandlerStrategies; import org.springframework.web.reactive.function.server.ServerRequest; import org.springframework.web.server.ServerWebExchange; import org.springframework.web.server.WebFilter; @@ -30,8 +28,6 @@ import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import java.net.URI; -import java.util.Arrays; -import java.util.List; import java.util.Objects; /** @@ -50,6 +46,9 @@ public class IndexFilter implements WebFilter { @Autowired private Validator validator; + @Autowired + private GatewayForwardChooser gatewayForwardChooser; + @Override public Mono filter(ServerWebExchange exchange, WebFilterChain chain) { ServerHttpRequest request = exchange.getRequest(); @@ -92,9 +91,11 @@ public class IndexFilter implements WebFilter { exchange, headers); return bodyInserter.insert(outputMessage, new BodyInserterContext()) .then(Mono.defer(() -> { + ForwardInfo forwardInfo = gatewayForwardChooser.getForwardInfo(exchange); ServerHttpRequest decorator = decorate(exchange, headers, outputMessage); ServerWebExchange newExchange = exchange.mutate().request(decorator).build(); - return chain.filter(newExchange); + ServerWebExchange forwardExchange = ServerWebExchangeUtil.getForwardExchange(newExchange, forwardInfo); + return chain.filter(forwardExchange); })); } else { @@ -105,8 +106,9 @@ public class IndexFilter implements WebFilter { ApiParam apiParam = ServerWebExchangeUtil.getApiParam(exchange, originalQuery); // 签名验证 doValidate(apiParam); - ServerWebExchange newExchange = ServerWebExchangeUtil.getForwardExchange(exchange, apiParam); - return chain.filter(newExchange); + ForwardInfo forwardInfo = gatewayForwardChooser.getForwardInfo(exchange); + ServerWebExchange forwardExchange = ServerWebExchangeUtil.getForwardExchange(exchange, forwardInfo); + return chain.filter(forwardExchange); } } else { return ServerWebExchangeUtil.forwardUnknown(exchange, chain); @@ -127,9 +129,7 @@ public class IndexFilter implements WebFilter { , HttpHeaders headers , CachedBodyOutputMessage outputMessage ) { - ApiParam apiParam = ServerWebExchangeUtil.getApiParam(exchange); - ServerHttpRequest newRequest = ServerWebExchangeUtil.getForwardRequest(exchange.getRequest(), apiParam); - return new ServerHttpRequestDecorator(newRequest) { + return new ServerHttpRequestDecorator(exchange.getRequest()) { @Override public HttpHeaders getHeaders() { long contentLength = headers.getContentLength(); @@ -140,7 +140,6 @@ public class IndexFilter implements WebFilter { } else { httpHeaders.set(HttpHeaders.TRANSFER_ENCODING, "chunked"); } - httpHeaders.set(SopConstants.REDIRECT_VERSION_KEY, apiParam.fetchVersion()); return httpHeaders; } diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/route/GatewayForwardChooser.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/route/GatewayForwardChooser.java new file mode 100644 index 00000000..5f2f73c3 --- /dev/null +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/route/GatewayForwardChooser.java @@ -0,0 +1,16 @@ +package com.gitee.sop.gatewaycommon.gateway.route; + +import com.gitee.sop.gatewaycommon.gateway.ServerWebExchangeUtil; +import com.gitee.sop.gatewaycommon.param.ApiParam; +import com.gitee.sop.gatewaycommon.route.BaseForwardChooser; +import org.springframework.web.server.ServerWebExchange; + +/** + * @author tanghc + */ +public class GatewayForwardChooser extends BaseForwardChooser { + @Override + protected ApiParam getApiParam(ServerWebExchange exchange) { + return ServerWebExchangeUtil.getApiParam(exchange); + } +} diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/route/BaseForwardChooser.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/route/BaseForwardChooser.java new file mode 100644 index 00000000..bfebdd77 --- /dev/null +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/route/BaseForwardChooser.java @@ -0,0 +1,54 @@ +package com.gitee.sop.gatewaycommon.route; + +import com.gitee.sop.gatewaycommon.bean.RouteDefinition; +import com.gitee.sop.gatewaycommon.bean.TargetRoute; +import com.gitee.sop.gatewaycommon.manager.EnvGrayManager; +import com.gitee.sop.gatewaycommon.manager.RouteRepositoryContext; +import com.gitee.sop.gatewaycommon.param.ApiParam; +import org.apache.commons.lang3.BooleanUtils; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * @author tanghc + */ +public abstract class BaseForwardChooser implements ForwardChooser { + + @Autowired + private EnvGrayManager envGrayManager; + + protected abstract ApiParam getApiParam(T t); + + @Override + public ForwardInfo getForwardInfo(T t) { + ApiParam apiParam = getApiParam(t); + ForwardInfo forwardInfo = new ForwardInfo(); + String nameVersion = apiParam.fetchNameVersion(); + TargetRoute targetRoute = RouteRepositoryContext.getRouteRepository().get(nameVersion); + RouteDefinition routeDefinitionOrig = targetRoute.getRouteDefinition(); + String path = routeDefinitionOrig.getPath(); + String versionInHead = apiParam.fetchVersion(); + String serviceId = targetRoute.getServiceRouteInfo().fetchServiceIdLowerCase(); + // 如果服务在灰度阶段,返回一个灰度版本号 + String grayVersion = envGrayManager.getVersion(serviceId, nameVersion); + // 如果是灰度环境 + if (grayVersion != null && envGrayManager.containsKey(serviceId, apiParam.fetchAppKey())) { + String newNameVersion = apiParam.fetchName() + grayVersion; + TargetRoute targetRouteDest = RouteRepositoryContext.getRouteRepository().get(newNameVersion); + if (targetRouteDest != null) { + if (BooleanUtils.toBoolean(routeDefinitionOrig.getCompatibleMode())) { + versionInHead = grayVersion; + } else { + // 获取灰度接口 + RouteDefinition routeDefinition = targetRouteDest.getRouteDefinition(); + path = routeDefinition.getPath(); + } + } + } + + forwardInfo.setPath(path); + forwardInfo.setVersion(versionInHead); + + return forwardInfo; + } + +} diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/route/ForwardChooser.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/route/ForwardChooser.java new file mode 100644 index 00000000..346ac33d --- /dev/null +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/route/ForwardChooser.java @@ -0,0 +1,16 @@ +package com.gitee.sop.gatewaycommon.route; + +/** + * 转发选择 + * @author tanghc + */ +public interface ForwardChooser { + + /** + * 返回转发信息 + * @param t 上下文 + * @return 返回转发信息 + */ + ForwardInfo getForwardInfo(T t); + +} diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/route/ForwardInfo.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/route/ForwardInfo.java new file mode 100644 index 00000000..f36932c1 --- /dev/null +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/route/ForwardInfo.java @@ -0,0 +1,13 @@ +package com.gitee.sop.gatewaycommon.route; + +import lombok.Data; + +/** + * @author tanghc + */ +@Data +public class ForwardInfo { + private String path; + private String version; + private String domain; +} 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 7156450b..54b0a5b7 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 @@ -12,13 +12,13 @@ import com.gitee.sop.gatewaycommon.zuul.controller.ZuulIndexController; import com.gitee.sop.gatewaycommon.zuul.filter.ErrorFilter; import com.gitee.sop.gatewaycommon.zuul.filter.FormBodyWrapperFilterExt; import com.gitee.sop.gatewaycommon.zuul.filter.PostResultFilter; -import com.gitee.sop.gatewaycommon.zuul.filter.PreEnvGrayFilter; import com.gitee.sop.gatewaycommon.zuul.filter.PreHttpServletRequestWrapperFilter; import com.gitee.sop.gatewaycommon.zuul.filter.PreLimitFilter; import com.gitee.sop.gatewaycommon.zuul.filter.PreParameterFormatterFilter; import com.gitee.sop.gatewaycommon.zuul.filter.PreValidateFilter; import com.gitee.sop.gatewaycommon.zuul.filter.Servlet30WrapperFilterExt; import com.gitee.sop.gatewaycommon.zuul.route.SopRouteLocator; +import com.gitee.sop.gatewaycommon.zuul.route.ZuulForwardChooser; import com.gitee.sop.gatewaycommon.zuul.route.ZuulRouteCache; import com.gitee.sop.gatewaycommon.zuul.route.ZuulRouteRepository; import com.netflix.zuul.context.RequestContext; @@ -26,7 +26,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.web.ServerProperties; import org.springframework.cloud.netflix.zuul.filters.ProxyRequestHelper; -import org.springframework.cloud.netflix.zuul.filters.RouteLocator; import org.springframework.cloud.netflix.zuul.filters.ZuulProperties; import org.springframework.cloud.netflix.zuul.filters.pre.PreDecorationFilter; import org.springframework.context.annotation.Bean; @@ -89,22 +88,28 @@ public class BaseZuulConfiguration extends AbstractConfiguration { return new Servlet30WrapperFilterExt(); } + @Bean + SopRouteLocator sopRouteLocator() { + return new SopRouteLocator(); + } + /** * 选取路由 - * @param zuulRouteRepository + * @param sopRouteLocator * @param proxyRequestHelper * @return */ @Bean - PreDecorationFilter preDecorationFilter(ZuulRouteRepository zuulRouteRepository, ProxyRequestHelper proxyRequestHelper) { + PreDecorationFilter preDecorationFilter(SopRouteLocator sopRouteLocator, ProxyRequestHelper proxyRequestHelper) { // 自定义路由 - RouteLocator routeLocator = new SopRouteLocator(zuulRouteRepository); - return new PreDecorationFilter(routeLocator, + return new PreDecorationFilter(sopRouteLocator, this.server.getServlet().getContextPath(), this.zuulProperties, proxyRequestHelper); } + + /** * 路由管理 * @param zuulRouteRepository 路由仓库 @@ -140,14 +145,6 @@ public class BaseZuulConfiguration extends AbstractConfiguration { return new PreLimitFilter(); } - /** - * 决定版本号 - */ - @Bean - PreEnvGrayFilter preEnvGrayFilter() { - return new PreEnvGrayFilter(); - } - /** * 错误处理扩展 */ @@ -173,4 +170,9 @@ public class BaseZuulConfiguration extends AbstractConfiguration { return ApiContext.getApiConfig().getZuulErrorController(); } + @Bean + ZuulForwardChooser zuulForwardChooser() { + return new ZuulForwardChooser(); + } + } diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/filter/PreEnvGrayFilter.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/filter/PreEnvGrayFilter.java index 7245cb74..dd5f4de7 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/filter/PreEnvGrayFilter.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/filter/PreEnvGrayFilter.java @@ -14,7 +14,10 @@ import org.springframework.beans.factory.annotation.Autowired; * 灰度发布判断,改变版本号 * * @author tanghc + * @deprecated + * @see com.gitee.sop.gatewaycommon.zuul.route.ZuulForwardChooser */ +@Deprecated public class PreEnvGrayFilter extends BaseZuulFilter { @Autowired 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 ce07b1ca..edb41374 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 @@ -2,7 +2,11 @@ package com.gitee.sop.gatewaycommon.zuul.route; import com.gitee.sop.gatewaycommon.bean.AbstractTargetRoute; import com.gitee.sop.gatewaycommon.param.ApiParam; +import com.gitee.sop.gatewaycommon.route.ForwardInfo; +import com.gitee.sop.gatewaycommon.param.ParamNames; import com.gitee.sop.gatewaycommon.zuul.ZuulContext; +import com.netflix.zuul.context.RequestContext; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.netflix.zuul.filters.Route; import org.springframework.cloud.netflix.zuul.filters.RouteLocator; import org.springframework.core.Ordered; @@ -19,11 +23,11 @@ import java.util.stream.Collectors; */ public class SopRouteLocator implements RouteLocator, Ordered { + @Autowired private ZuulRouteRepository zuulRouteRepository; - public SopRouteLocator(ZuulRouteRepository zuulRouteRepository) { - this.zuulRouteRepository = zuulRouteRepository; - } + @Autowired + private ZuulForwardChooser zuulForwardChooser; @Override public Collection getIgnoredPaths() { @@ -52,7 +56,13 @@ public class SopRouteLocator implements RouteLocator, Ordered { if (zuulTargetRoute == null) { return null; } - return zuulTargetRoute.getTargetRouteDefinition(); + Route targetRouteDefinition = zuulTargetRoute.getTargetRouteDefinition(); + ForwardInfo forwardInfo = zuulForwardChooser.getForwardInfo(RequestContext.getCurrentContext()); + String forwardPath = forwardInfo.getPath(); + targetRouteDefinition.setPath(forwardPath); + String versionInHead = forwardInfo.getVersion(); + RequestContext.getCurrentContext().addZuulRequestHeader(ParamNames.HEADER_VERSION_NAME, versionInHead); + return targetRouteDefinition; } @Override diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/route/ZuulForwardChooser.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/route/ZuulForwardChooser.java new file mode 100644 index 00000000..cea835d5 --- /dev/null +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/route/ZuulForwardChooser.java @@ -0,0 +1,18 @@ +package com.gitee.sop.gatewaycommon.zuul.route; + +import com.gitee.sop.gatewaycommon.param.ApiParam; +import com.gitee.sop.gatewaycommon.route.BaseForwardChooser; +import com.gitee.sop.gatewaycommon.zuul.ZuulContext; +import com.netflix.zuul.context.RequestContext; + +/** + * @author tanghc + */ +public class ZuulForwardChooser extends BaseForwardChooser { + + @Override + protected ApiParam getApiParam(RequestContext requestContext) { + return ZuulContext.getApiParam(); + } + +} diff --git a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/bean/ServiceApiInfo.java b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/bean/ServiceApiInfo.java index 85d1f9a3..d200c4b4 100644 --- a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/bean/ServiceApiInfo.java +++ b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/bean/ServiceApiInfo.java @@ -34,6 +34,8 @@ public class ServiceApiInfo { private int permission; /** 是否需要token */ private int needToken; + /** 是否是兼容模式,即使用了@ApiAbility注解 */ + private int compatibleMode; /** 是否是原始Mapping */ private boolean originalMapping; diff --git a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/manager/ApiMetaBuilder.java b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/manager/ApiMetaBuilder.java index 8f3ecb17..55c2bf58 100644 --- a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/manager/ApiMetaBuilder.java +++ b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/manager/ApiMetaBuilder.java @@ -95,6 +95,7 @@ public class ApiMetaBuilder { apiMeta.setMergeResult(BooleanUtils.toInteger(apiMappingInfo.isMergeResult())); apiMeta.setPermission(BooleanUtils.toInteger(apiMappingInfo.isPermission())); apiMeta.setNeedToken(BooleanUtils.toInteger(apiMappingInfo.isNeedToken())); + apiMeta.setCompatibleMode(BooleanUtils.toInteger(apiMappingInfo.isCompatibleMode())); return apiMeta; } else { if (!ServiceContext.getCurrentContext().getBoolean(ServiceContext.RESTFUL_KEY, false)) { diff --git a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/mapping/ApiMappingHandlerMapping.java b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/mapping/ApiMappingHandlerMapping.java index 9f6467fd..8185d7f7 100644 --- a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/mapping/ApiMappingHandlerMapping.java +++ b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/mapping/ApiMappingHandlerMapping.java @@ -5,6 +5,7 @@ import com.gitee.sop.servercommon.annotation.ApiMapping; import com.gitee.sop.servercommon.bean.ServiceConfig; import com.gitee.sop.servercommon.bean.ServiceContext; import com.gitee.sop.servercommon.util.OpenUtil; +import org.apache.commons.lang.StringUtils; import org.springframework.core.PriorityOrdered; import org.springframework.util.StringValueResolver; import org.springframework.web.servlet.mvc.condition.RequestCondition; @@ -29,7 +30,11 @@ public class ApiMappingHandlerMapping extends RequestMappingHandlerMapping imple ApiAbility apiAbility = OpenUtil.getAnnotationFromMethodOrClass(method, ApiAbility.class); StringValueResolver valueResolver = null; if (apiMapping != null) { - valueResolver = stringValueResolver; + String version = apiMapping.version(); + if (StringUtils.isBlank(version)) { + version = ServiceConfig.getInstance().getDefaultVersion(); + } + valueResolver = new ApiMappingStringValueResolverVersion(version); } if (isMvc || apiAbility != null) { valueResolver = stringValueResolverMVC; @@ -46,7 +51,8 @@ public class ApiMappingHandlerMapping extends RequestMappingHandlerMapping imple boolean ignoreValidate; boolean mergeResult; boolean permission; - boolean needToken = false; + boolean needToken; + boolean compatibleMode = false; ApiMapping apiMapping = method.getAnnotation(ApiMapping.class); if (apiMapping != null) { name = apiMapping.value()[0]; @@ -63,6 +69,7 @@ public class ApiMappingHandlerMapping extends RequestMappingHandlerMapping imple mergeResult = apiAbility.mergeResult(); permission = apiAbility.permission(); needToken = apiAbility.needToken(); + compatibleMode = true; } else { return super.getCustomMethodCondition(method); } @@ -87,6 +94,7 @@ public class ApiMappingHandlerMapping extends RequestMappingHandlerMapping imple apiMappingInfo.setMergeResult(mergeResult); apiMappingInfo.setPermission(permission); apiMappingInfo.setNeedToken(needToken); + apiMappingInfo.setCompatibleMode(compatibleMode); logger.info("注册接口,name:" + method + ", version:" + version); return new ApiMappingRequestCondition(apiMappingInfo); } diff --git a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/mapping/ApiMappingInfo.java b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/mapping/ApiMappingInfo.java index cc2dfb3d..765de153 100644 --- a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/mapping/ApiMappingInfo.java +++ b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/mapping/ApiMappingInfo.java @@ -13,6 +13,8 @@ public class ApiMappingInfo { private boolean mergeResult; private boolean permission; private boolean needToken; + private boolean compatibleMode; + public ApiMappingInfo(String name, String version) { this.name = name; diff --git a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/mapping/ApiMappingRequestCondition.java b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/mapping/ApiMappingRequestCondition.java index c64ecadf..6ef894ea 100644 --- a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/mapping/ApiMappingRequestCondition.java +++ b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/mapping/ApiMappingRequestCondition.java @@ -37,6 +37,11 @@ public class ApiMappingRequestCondition implements RequestCondition

-

() +

+

-
-
+
+ + + + + + + + + +
接口名版本号
+
+ +
+
+ 接口描述 +
+
+ +
diff --git a/sop-website/src/main/resources/public/pages/doc/doc.js b/sop-website/src/main/resources/public/pages/doc/doc.js index f7b0db2b..18c66694 100644 --- a/sop-website/src/main/resources/public/pages/doc/doc.js +++ b/sop-website/src/main/resources/public/pages/doc/doc.js @@ -61,7 +61,7 @@ layui.config({ */ html.push('
  • '); - html.push('' + docItem['summary'] + '') + html.push('' + docItem['summary'] + ' ' + docItem.version + '') } } diff --git a/sop-website/src/main/resources/public/pages/sandbox/sandbox.html b/sop-website/src/main/resources/public/pages/sandbox/sandbox.html index db969c7d..3514d938 100644 --- a/sop-website/src/main/resources/public/pages/sandbox/sandbox.html +++ b/sop-website/src/main/resources/public/pages/sandbox/sandbox.html @@ -77,11 +77,30 @@
  • -

    () +

    +

    -
    -
    + +
    + + + + + + + + + +
    接口名版本号
    +
    + +
    +
    + 接口描述 +
    +
    + +
    From 8b72108a580b7da77e1f7ee6163809313fba6655 Mon Sep 17 00:00:00 2001 From: tanghc Date: Mon, 13 Jan 2020 16:12:40 +0800 Subject: [PATCH 13/55] UPDATE --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ab343d4e..fc0279ad 100644 --- a/README.md +++ b/README.md @@ -91,4 +91,4 @@ SOP封装了开放平台大部分功能包括:签名验证、统一异常处 ## 沟通交流 -Q群:328419269 +Q群:50212229 From d704d6770f1ad2e7e31c76c616a986dd12449fa3 Mon Sep 17 00:00:00 2001 From: tanghc Date: Mon, 13 Jan 2020 16:14:09 +0800 Subject: [PATCH 14/55] UPDATE --- doc/docs/README.md | 2 +- doc/docs/files/10050_接口交互详解.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/docs/README.md b/doc/docs/README.md index c7f3bcb5..f32b1393 100644 --- a/doc/docs/README.md +++ b/doc/docs/README.md @@ -2,4 +2,4 @@ Git地址:[SOP](https://gitee.com/durcframework/SOP) -Q群:328419269 \ No newline at end of file +Q群:50212229 \ No newline at end of file diff --git a/doc/docs/files/10050_接口交互详解.md b/doc/docs/files/10050_接口交互详解.md index 9140a145..c83a04f5 100644 --- a/doc/docs/files/10050_接口交互详解.md +++ b/doc/docs/files/10050_接口交互详解.md @@ -47,7 +47,7 @@ member.register.total.get 会员服务.注册模块.注册总数.获取 整个SOP的架构如下图所示: -![架构图](https://images.gitee.com/uploads/images/2019/0821/201531_0f605f7c_332975.png "sop2.png") +![架构图](https://images.gitee.com/uploads/images/2019/1227/145216_c9b45109_332975.png "sop2.png") - 完整请求路线 From 0e686ef88884eb783e4d2bf2257d90497f3f4bf1 Mon Sep 17 00:00:00 2001 From: tanghc Date: Mon, 13 Jan 2020 16:29:38 +0800 Subject: [PATCH 15/55] 3.0.0 --- .../gitee/sop/storyweb/controller/AlipayController.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sop-example/sop-story/sop-story-web/src/main/java/com/gitee/sop/storyweb/controller/AlipayController.java b/sop-example/sop-story/sop-story-web/src/main/java/com/gitee/sop/storyweb/controller/AlipayController.java index 26f751dd..f7510610 100644 --- a/sop-example/sop-story/sop-story-web/src/main/java/com/gitee/sop/storyweb/controller/AlipayController.java +++ b/sop-example/sop-story/sop-story-web/src/main/java/com/gitee/sop/storyweb/controller/AlipayController.java @@ -54,7 +54,7 @@ public class AlipayController { return result; } - // http://localhost:2222/story.get/ + // http://localhost:2222/story.get/1.0/ // 接口名,使用默认版本号 @ApiMapping(value = "story.get") public StoryResult storyget() { @@ -67,7 +67,7 @@ public class AlipayController { return result; } - // http://localhost:2222/story.get/?version=1.1 + // http://localhost:2222/story.get/1.1/ // 接口名 + 版本号 @ApiMapping(value = "story.get", version = "1.1") public StoryResult getStory2() { @@ -77,7 +77,7 @@ public class AlipayController { return result; } - // http://localhost:2222/story.get/?name=111&version=2.0 + // http://localhost:2222/story.get/2.0/?name=111 // 接口名 + 版本号 // StoryParam对应biz_content内容 @ApiMapping(value = "story.get", version = "2.0") @@ -179,7 +179,7 @@ public class AlipayController { return story; } - // http://localhost:2222/alipay.story.get/ + // http://localhost:2222/alipay.story.get/1.0/?name=Jim @ApiOperation(value="获取故事信息", notes = "获取故事信息的详细信息") @ApiMapping(value = "alipay.story.get") public StoryResult getStory(StoryParam param) { From 7d682587f22699e0dbfb7031d20a5bb66a8b9686 Mon Sep 17 00:00:00 2001 From: tanghc Date: Mon, 13 Jan 2020 17:58:40 +0800 Subject: [PATCH 16/55] 3.0.0 --- sop-common/readme.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sop-common/readme.md b/sop-common/readme.md index aa8b9864..d5109565 100644 --- a/sop-common/readme.md +++ b/sop-common/readme.md @@ -1,5 +1,7 @@ # sop-common +- sop-bridge-gateway:网关桥接器,供sop-gateway依赖,依赖后使用spring cloud gateway网关 +- sop-bridge-zuul:网关桥接器,供sop-gateway依赖,依赖后使用spring cloud zuul网关 - sop-gateway-common:提供给网关使用 - sop-service-common:提供给微服务端使用,需要打成jar From e1cd5c2298378b2334a8d0bdd4059b26deacd997 Mon Sep 17 00:00:00 2001 From: tanghc Date: Mon, 13 Jan 2020 18:12:31 +0800 Subject: [PATCH 17/55] 3.0.0 --- doc/docs/_sidebar.md | 67 ++++++++++++------------ doc/docs/files/90014_2.x升3.x注意事项.md | 23 ++++++++ 2 files changed, 57 insertions(+), 33 deletions(-) create mode 100644 doc/docs/files/90014_2.x升3.x注意事项.md diff --git a/doc/docs/_sidebar.md b/doc/docs/_sidebar.md index f62469f7..b0701362 100644 --- a/doc/docs/_sidebar.md +++ b/doc/docs/_sidebar.md @@ -1,35 +1,36 @@ -* [首页](/?t=1578663129148) +* [首页](/?t=1578910309712) * 开发文档 - * [快速体验](files/10010_快速体验.md?t=1578663129153) - * [项目接入到SOP](files/10011_项目接入到SOP.md?t=1578663129189) - * [新增接口](files/10020_新增接口.md?t=1578663129189) - * [开发流程](files/10021_开发流程.md?t=1578663129189) - * [业务参数校验](files/10030_业务参数校验.md?t=1578663129189) - * [错误处理](files/10040_错误处理.md?t=1578663129190) - * [编写文档](files/10041_编写文档.md?t=1578663129190) - * [接口交互详解](files/10050_接口交互详解.md?t=1578663129190) - * [easyopen支持](files/10070_easyopen支持.md?t=1578663129191) - * [使用签名校验工具](files/10080_使用签名校验工具.md?t=1578663129191) - * [ISV管理](files/10085_ISV管理.md?t=1578663129191) - * [自定义返回结果](files/10087_自定义返回结果.md?t=1578663129191) - * [自定义过滤器](files/10088_自定义过滤器.md?t=1578663129191) - * [自定义校验token](files/10089_自定义校验token.md?t=1578663129191) - * [路由授权](files/10090_路由授权.md?t=1578663129191) - * [接口限流](files/10092_接口限流.md?t=1578663129192) - * [监控日志](files/10093_监控日志.md?t=1578663129192) - * [SDK开发](files/10095_SDK开发.md?t=1578663129192) - * [使用SpringCloudGateway](files/10096_使用SpringCloudGateway.md?t=1578663129192) - * [应用授权](files/10097_应用授权.md?t=1578663129192) - * [提供restful接口](files/10100_提供restful接口.md?t=1578663129192) - * [文件上传](files/10104_文件上传.md?t=1578663129192) - * [配置Sleuth链路追踪](files/10109_配置Sleuth链路追踪.md?t=1578663129193) - * [预发布灰度发布](files/10110_预发布灰度发布.md?t=1578663129193) - * [动态修改请求参数](files/10111_动态修改请求参数.md?t=1578663129193) - * [使用eureka](files/10112_使用eureka.md?t=1578663129193) - * [扩展其它注册中心](files/10113_扩展其它注册中心.md?t=1578663129193) + * [快速体验](files/10010_快速体验.md?t=1578910309714) + * [项目接入到SOP](files/10011_项目接入到SOP.md?t=1578910309731) + * [新增接口](files/10020_新增接口.md?t=1578910309732) + * [开发流程](files/10021_开发流程.md?t=1578910309732) + * [业务参数校验](files/10030_业务参数校验.md?t=1578910309732) + * [错误处理](files/10040_错误处理.md?t=1578910309732) + * [编写文档](files/10041_编写文档.md?t=1578910309732) + * [接口交互详解](files/10050_接口交互详解.md?t=1578910309732) + * [easyopen支持](files/10070_easyopen支持.md?t=1578910309732) + * [使用签名校验工具](files/10080_使用签名校验工具.md?t=1578910309732) + * [ISV管理](files/10085_ISV管理.md?t=1578910309732) + * [自定义返回结果](files/10087_自定义返回结果.md?t=1578910309733) + * [自定义过滤器](files/10088_自定义过滤器.md?t=1578910309733) + * [自定义校验token](files/10089_自定义校验token.md?t=1578910309733) + * [路由授权](files/10090_路由授权.md?t=1578910309733) + * [接口限流](files/10092_接口限流.md?t=1578910309733) + * [监控日志](files/10093_监控日志.md?t=1578910309733) + * [SDK开发](files/10095_SDK开发.md?t=1578910309733) + * [使用SpringCloudGateway](files/10096_使用SpringCloudGateway.md?t=1578910309733) + * [应用授权](files/10097_应用授权.md?t=1578910309733) + * [提供restful接口](files/10100_提供restful接口.md?t=1578910309733) + * [文件上传](files/10104_文件上传.md?t=1578910309734) + * [配置Sleuth链路追踪](files/10109_配置Sleuth链路追踪.md?t=1578910309734) + * [预发布灰度发布](files/10110_预发布灰度发布.md?t=1578910309734) + * [动态修改请求参数](files/10111_动态修改请求参数.md?t=1578910309734) + * [使用eureka](files/10112_使用eureka.md?t=1578910309734) + * [扩展其它注册中心](files/10113_扩展其它注册中心.md?t=1578910309734) * 原理分析 - * [原理分析之@ApiMapping](files/90010_原理分析之@ApiMapping.md?t=1578663129194) - * [原理分析之如何存储路由](files/90011_原理分析之如何存储路由.md?t=1578663129194) - * [原理分析之如何路由](files/90012_原理分析之如何路由.md?t=1578663129194) - * [原理分析之文档归纳](files/90013_原理分析之文档归纳.md?t=1578663129194) - * [常见问题](files/90100_常见问题.md?t=1578663129194) + * [原理分析之@ApiMapping](files/90010_原理分析之@ApiMapping.md?t=1578910309734) + * [原理分析之如何存储路由](files/90011_原理分析之如何存储路由.md?t=1578910309734) + * [原理分析之如何路由](files/90012_原理分析之如何路由.md?t=1578910309734) + * [原理分析之文档归纳](files/90013_原理分析之文档归纳.md?t=1578910309734) + * [2.x升3.x注意事项](files/90014_2.x升3.x注意事项.md?t=1578910309734) + * [常见问题](files/90100_常见问题.md?t=1578910309734) diff --git a/doc/docs/files/90014_2.x升3.x注意事项.md b/doc/docs/files/90014_2.x升3.x注意事项.md new file mode 100644 index 00000000..1cf1d194 --- /dev/null +++ b/doc/docs/files/90014_2.x升3.x注意事项.md @@ -0,0 +1,23 @@ +# 2.x升3.x注意事项 + +升级到3.x后`本地访问接口`方式会有不同。 + +```java +@ApiMapping(value = "alipay.story.get") +public StoryResult getStory(StoryParam param) { + StoryResult story = new StoryResult(); + story.setId(1L); + story.setName("海底小纵队(alipay.story.get1.0), port:" + environment.getProperty("server.port") + ", param:" + param); + return story; +} +``` + +- 2.x版本访问方式: + +`http://localhost:2222/alipay.story.get/?name=Jim&version=1.0` + +- 3.x版本访问方式: + +`http://localhost:2222/alipay.story.get/1.0/?name=Jim` + +3.x版本中把版本号融合在了url中,如果这个功能没有用到,可以放心升级。 \ No newline at end of file From 0d3489f17e00690b6c3b5cd7cdbb0f2dfbf51f42 Mon Sep 17 00:00:00 2001 From: tanghc Date: Tue, 14 Jan 2020 09:29:03 +0800 Subject: [PATCH 18/55] 3.0.0 --- .../src/main/resources/sop-bridge.properties | 3 +++ .../sop/gatewaycommon/gateway/filter/IndexFilter.java | 7 +++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/sop-common/sop-bridge-gateway/src/main/resources/sop-bridge.properties b/sop-common/sop-bridge-gateway/src/main/resources/sop-bridge.properties index b5c2e2e3..f3085c07 100644 --- a/sop-common/sop-bridge-gateway/src/main/resources/sop-bridge.properties +++ b/sop-common/sop-bridge-gateway/src/main/resources/sop-bridge.properties @@ -3,6 +3,9 @@ spring.application.name=sop-gateway # 不用改,如果要改,请全局替换修改 sop.secret=MZZOUSTua6LzApIWXCwEgbBmxSzpzC +# 网关入口 +gateway.index-path=/ + # nacos cloud配置 spring.cloud.nacos.discovery.server-addr=${nacos.url} diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/IndexFilter.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/IndexFilter.java index 3019bf2b..5f2d8797 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/IndexFilter.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/IndexFilter.java @@ -9,6 +9,7 @@ import com.gitee.sop.gatewaycommon.route.ForwardInfo; import com.gitee.sop.gatewaycommon.validate.Validator; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.cloud.gateway.support.BodyInserterContext; import org.springframework.cloud.gateway.support.CachedBodyOutputMessage; import org.springframework.core.Ordered; @@ -39,10 +40,12 @@ import java.util.Objects; @Order(Ordered.HIGHEST_PRECEDENCE) public class IndexFilter implements WebFilter { - private static final String INDEX_PATH = "/"; private static final String REST_PATH_PREFIX = "/rest"; private static final String SOP_PATH_PREFIX = "/sop"; + @Value("${gateway.index-path:/}") + private String indexPath; + @Autowired private Validator validator; @@ -67,7 +70,7 @@ public class IndexFilter implements WebFilter { ServerWebExchange newExchange = ServerWebExchangeUtil.getRestfulExchange(exchange, path); return chain.filter(newExchange); } - if (Objects.equals(path, INDEX_PATH)) { + if (Objects.equals(path, indexPath)) { if (request.getMethod() == HttpMethod.POST) { ServerRequest serverRequest = ServerWebExchangeUtil.createReadBodyRequest(exchange); // 读取请求体中的内容 From 69131929c771c82fb585b6ddde6dae8c54fe02a1 Mon Sep 17 00:00:00 2001 From: tanghc Date: Tue, 14 Jan 2020 11:22:22 +0800 Subject: [PATCH 19/55] 3.0.0 --- .../gateway/ServerWebExchangeUtil.java | 15 ++++++++++++--- .../gateway/controller/GatewayController.java | 5 ++--- .../gatewaycommon/gateway/filter/IndexFilter.java | 9 +++++---- .../gateway/route/GatewayForwardChooser.java | 13 +++++++++++++ .../gitee/sop/gatewaycommon/param/ApiParam.java | 10 +--------- .../gatewaycommon/route/BaseForwardChooser.java | 11 +++-------- .../sop/gatewaycommon/route/ForwardInfo.java | 6 ++++++ 7 files changed, 42 insertions(+), 27 deletions(-) diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/ServerWebExchangeUtil.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/ServerWebExchangeUtil.java index e76ec24a..6a7a1bba 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/ServerWebExchangeUtil.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/ServerWebExchangeUtil.java @@ -43,8 +43,8 @@ import java.util.function.Consumer; @Slf4j public class ServerWebExchangeUtil { + private static final String THROWABLE_KEY = "sop.throwable"; private static final String UNKNOWN_PATH = "/sop/unknown"; - private static final String VALIDATE_ERROR_PATH = "/sop/validateError"; private static final String REST_PATH = "/rest"; private static FormHttpMessageConverter formHttpMessageConverter = new FormHttpMessageConverter(); @@ -63,8 +63,9 @@ public class ServerWebExchangeUtil { * @return 返回新的ServerWebExchange,配合chain.filter(newExchange);使用 */ public static ServerWebExchange getForwardExchange(ServerWebExchange exchange, ForwardInfo forwardInfo) { - ServerHttpRequest newRequest = exchange.getRequest() - .mutate() + ServerHttpRequest.Builder builder = exchange.getRequest() + .mutate(); + ServerHttpRequest newRequest = builder .header(ParamNames.HEADER_VERSION_NAME, forwardInfo.getVersion()) .path(forwardInfo.getPath()).build(); return exchange.mutate().request(newRequest).build(); @@ -153,6 +154,14 @@ public class ServerWebExchangeUtil { return apiParam; } + public static void setThrowable(ServerWebExchange exchange, Throwable throwable) { + exchange.getAttributes().put(THROWABLE_KEY, throwable); + } + + public static Throwable getThrowable(ServerWebExchange exchange) { + return (Throwable)exchange.getAttribute(THROWABLE_KEY); + } + /** * 获取请求参数 * diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/controller/GatewayController.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/controller/GatewayController.java index c67c4a19..8836ad13 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/controller/GatewayController.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/controller/GatewayController.java @@ -4,7 +4,6 @@ import com.gitee.sop.gatewaycommon.bean.ApiContext; import com.gitee.sop.gatewaycommon.exception.ApiException; import com.gitee.sop.gatewaycommon.gateway.ServerWebExchangeUtil; import com.gitee.sop.gatewaycommon.message.ErrorEnum; -import com.gitee.sop.gatewaycommon.param.ApiParam; import com.gitee.sop.gatewaycommon.result.ResultExecutor; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @@ -25,10 +24,10 @@ public class GatewayController { */ @RequestMapping("/sop/validateError") public Mono validateError(ServerWebExchange exchange) { - ApiParam apiParam = ServerWebExchangeUtil.getApiParam(exchange); + Throwable throwable = ServerWebExchangeUtil.getThrowable(exchange); // 合并微服务传递过来的结果,变成最终结果 ResultExecutor resultExecutor = ApiContext.getApiConfig().getGatewayResultExecutor(); - String gatewayResult = resultExecutor.buildErrorResult(exchange, apiParam.getThrowable()); + String gatewayResult = resultExecutor.buildErrorResult(exchange, throwable); return Mono.just(gatewayResult); } diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/IndexFilter.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/IndexFilter.java index 5f2d8797..5441eb1d 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/IndexFilter.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/IndexFilter.java @@ -79,7 +79,7 @@ public class IndexFilter implements WebFilter { // 构建ApiParam ApiParam apiParam = ServerWebExchangeUtil.getApiParam(exchange, body); // 签名验证 - doValidate(apiParam); + doValidate(exchange, apiParam); return Mono.just(body); }); BodyInserter bodyInserter = BodyInserters.fromPublisher(modifiedBody, (Class) String.class); @@ -108,7 +108,8 @@ public class IndexFilter implements WebFilter { // 构建ApiParam ApiParam apiParam = ServerWebExchangeUtil.getApiParam(exchange, originalQuery); // 签名验证 - doValidate(apiParam); + doValidate(exchange, apiParam); + ForwardInfo forwardInfo = gatewayForwardChooser.getForwardInfo(exchange); ServerWebExchange forwardExchange = ServerWebExchangeUtil.getForwardExchange(exchange, forwardInfo); return chain.filter(forwardExchange); @@ -118,12 +119,12 @@ public class IndexFilter implements WebFilter { } } - private void doValidate(ApiParam apiParam) { + private void doValidate(ServerWebExchange exchange, ApiParam apiParam) { try { validator.validate(apiParam); } catch (ApiException e) { log.error("验证失败,ip:{}, params:{}, errorMsg:{}", apiParam.fetchIp(), apiParam.toJSONString(), e.getMessage()); - apiParam.setThrowable(e); + ServerWebExchangeUtil.setThrowable(exchange, e); } } diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/route/GatewayForwardChooser.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/route/GatewayForwardChooser.java index 5f2f73c3..219b1ec4 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/route/GatewayForwardChooser.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/route/GatewayForwardChooser.java @@ -3,14 +3,27 @@ package com.gitee.sop.gatewaycommon.gateway.route; import com.gitee.sop.gatewaycommon.gateway.ServerWebExchangeUtil; import com.gitee.sop.gatewaycommon.param.ApiParam; import com.gitee.sop.gatewaycommon.route.BaseForwardChooser; +import com.gitee.sop.gatewaycommon.route.ForwardInfo; import org.springframework.web.server.ServerWebExchange; /** * @author tanghc */ public class GatewayForwardChooser extends BaseForwardChooser { + + private static final String VALIDATE_ERROR_PATH = "/sop/validateError"; + @Override protected ApiParam getApiParam(ServerWebExchange exchange) { return ServerWebExchangeUtil.getApiParam(exchange); } + + @Override + public ForwardInfo getForwardInfo(ServerWebExchange exchange) { + // 如果有异常,直接跳转到异常处理 + if (ServerWebExchangeUtil.getThrowable(exchange) != null) { + return new ForwardInfo(VALIDATE_ERROR_PATH, ""); + } + return super.getForwardInfo(exchange); + } } 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 e0a38f81..4d48d78f 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 @@ -14,7 +14,7 @@ import java.util.Map; */ public class ApiParam extends JSONObject implements Param { - private static final String THROWABLE_KEY = "Throwable"; + public ApiParam() { } @@ -33,14 +33,6 @@ public class ApiParam extends JSONObject implements Param { private transient UploadContext uploadContext; - public void setThrowable(Throwable throwable) { - this.put(THROWABLE_KEY, throwable); - } - - public Throwable getThrowable() { - return (Throwable)get(THROWABLE_KEY); - } - public void fitNameVersion() { if (restName != null) { this.put(ParamNames.API_NAME, restName); diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/route/BaseForwardChooser.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/route/BaseForwardChooser.java index bfebdd77..254560c9 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/route/BaseForwardChooser.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/route/BaseForwardChooser.java @@ -21,12 +21,11 @@ public abstract class BaseForwardChooser implements ForwardChooser { @Override public ForwardInfo getForwardInfo(T t) { ApiParam apiParam = getApiParam(t); - ForwardInfo forwardInfo = new ForwardInfo(); String nameVersion = apiParam.fetchNameVersion(); TargetRoute targetRoute = RouteRepositoryContext.getRouteRepository().get(nameVersion); RouteDefinition routeDefinitionOrig = targetRoute.getRouteDefinition(); String path = routeDefinitionOrig.getPath(); - String versionInHead = apiParam.fetchVersion(); + String version = apiParam.fetchVersion(); String serviceId = targetRoute.getServiceRouteInfo().fetchServiceIdLowerCase(); // 如果服务在灰度阶段,返回一个灰度版本号 String grayVersion = envGrayManager.getVersion(serviceId, nameVersion); @@ -36,7 +35,7 @@ public abstract class BaseForwardChooser implements ForwardChooser { TargetRoute targetRouteDest = RouteRepositoryContext.getRouteRepository().get(newNameVersion); if (targetRouteDest != null) { if (BooleanUtils.toBoolean(routeDefinitionOrig.getCompatibleMode())) { - versionInHead = grayVersion; + version = grayVersion; } else { // 获取灰度接口 RouteDefinition routeDefinition = targetRouteDest.getRouteDefinition(); @@ -44,11 +43,7 @@ public abstract class BaseForwardChooser implements ForwardChooser { } } } - - forwardInfo.setPath(path); - forwardInfo.setVersion(versionInHead); - - return forwardInfo; + return new ForwardInfo(path, version); } } diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/route/ForwardInfo.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/route/ForwardInfo.java index f36932c1..00c9333d 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/route/ForwardInfo.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/route/ForwardInfo.java @@ -10,4 +10,10 @@ public class ForwardInfo { private String path; private String version; private String domain; + + public ForwardInfo(String path, String version) { + this.path = path; + this.version = version; + } + } From 7ce714dc05e452710c5788de6c5bf09cf843ccb2 Mon Sep 17 00:00:00 2001 From: tanghc Date: Wed, 15 Jan 2020 18:04:56 +0800 Subject: [PATCH 20/55] 3.0.0 --- .../sop-admin-server/src/main/resources/public/index.html | 2 +- ...{chunk-9f479afe.0d0ed757.js => chunk-9f479afe.b0599ada.js} | 2 +- sop-admin/sop-admin-vue/src/views/service/serviceList.vue | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) rename sop-admin/sop-admin-server/src/main/resources/public/static/js/{chunk-9f479afe.0d0ed757.js => chunk-9f479afe.b0599ada.js} (56%) diff --git a/sop-admin/sop-admin-server/src/main/resources/public/index.html b/sop-admin/sop-admin-server/src/main/resources/public/index.html index 4c586b35..138c8d0a 100644 --- a/sop-admin/sop-admin-server/src/main/resources/public/index.html +++ b/sop-admin/sop-admin-server/src/main/resources/public/index.html @@ -1 +1 @@ -SOP Admin
    \ No newline at end of file +SOP Admin
    \ No newline at end of file diff --git a/sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-9f479afe.0d0ed757.js b/sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-9f479afe.b0599ada.js similarity index 56% rename from sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-9f479afe.0d0ed757.js rename to sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-9f479afe.b0599ada.js index 8095a6ce..baeadadc 100644 --- a/sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-9f479afe.0d0ed757.js +++ b/sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-9f479afe.b0599ada.js @@ -1 +1 @@ -(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-9f479afe"],{"02f4":function(e,t,n){var r=n("4588"),o=n("be13");e.exports=function(e){return function(t,n){var i,a,s=String(o(t)),l=r(n),c=s.length;return l<0||l>=c?e?"":void 0:(i=s.charCodeAt(l),i<55296||i>56319||l+1===c||(a=s.charCodeAt(l+1))<56320||a>57343?e?s.charAt(l):i:e?s.slice(l,l+2):a-56320+(i-55296<<10)+65536)}}},"0390":function(e,t,n){"use strict";var r=n("02f4")(!0);e.exports=function(e,t,n){return t+(n?r(e,t).length:1)}},"0bfb":function(e,t,n){"use strict";var r=n("cb7c");e.exports=function(){var e=r(this),t="";return e.global&&(t+="g"),e.ignoreCase&&(t+="i"),e.multiline&&(t+="m"),e.unicode&&(t+="u"),e.sticky&&(t+="y"),t}},"214f":function(e,t,n){"use strict";n("b0c5");var r=n("2aba"),o=n("32e9"),i=n("79e5"),a=n("be13"),s=n("2b4c"),l=n("520a"),c=s("species"),u=!i(function(){var e=/./;return e.exec=function(){var e=[];return e.groups={a:"7"},e},"7"!=="".replace(e,"$")}),f=function(){var e=/(?:)/,t=e.exec;e.exec=function(){return t.apply(this,arguments)};var n="ab".split(e);return 2===n.length&&"a"===n[0]&&"b"===n[1]}();e.exports=function(e,t,n){var d=s(e),v=!i(function(){var t={};return t[d]=function(){return 7},7!=""[e](t)}),p=v?!i(function(){var t=!1,n=/a/;return n.exec=function(){return t=!0,null},"split"===e&&(n.constructor={},n.constructor[c]=function(){return n}),n[d](""),!t}):void 0;if(!v||!p||"replace"===e&&!u||"split"===e&&!f){var g=/./[d],y=n(a,d,""[e],function(e,t,n,r,o){return t.exec===l?v&&!o?{done:!0,value:g.call(t,n,r)}:{done:!0,value:e.call(n,t,r)}:{done:!1}}),h=y[0],m=y[1];r(String.prototype,e,h),o(RegExp.prototype,d,2==t?function(e,t){return m.call(e,this,t)}:function(e){return m.call(e,this)})}}},"28a5":function(e,t,n){"use strict";var r=n("aae3"),o=n("cb7c"),i=n("ebd6"),a=n("0390"),s=n("9def"),l=n("5f1b"),c=n("520a"),u=n("79e5"),f=Math.min,d=[].push,v="split",p="length",g="lastIndex",y=4294967295,h=!u(function(){RegExp(y,"y")});n("214f")("split",2,function(e,t,n,u){var m;return m="c"=="abbc"[v](/(b)*/)[1]||4!="test"[v](/(?:)/,-1)[p]||2!="ab"[v](/(?:ab)*/)[p]||4!="."[v](/(.?)(.?)/)[p]||"."[v](/()()/)[p]>1||""[v](/.?/)[p]?function(e,t){var o=String(this);if(void 0===e&&0===t)return[];if(!r(e))return n.call(o,e,t);var i,a,s,l=[],u=(e.ignoreCase?"i":"")+(e.multiline?"m":"")+(e.unicode?"u":"")+(e.sticky?"y":""),f=0,v=void 0===t?y:t>>>0,h=new RegExp(e.source,u+"g");while(i=c.call(h,o)){if(a=h[g],a>f&&(l.push(o.slice(f,i.index)),i[p]>1&&i.index=v))break;h[g]===i.index&&h[g]++}return f===o[p]?!s&&h.test("")||l.push(""):l.push(o.slice(f)),l[p]>v?l.slice(0,v):l}:"0"[v](void 0,0)[p]?function(e,t){return void 0===e&&0===t?[]:n.call(this,e,t)}:n,[function(n,r){var o=e(this),i=void 0==n?void 0:n[t];return void 0!==i?i.call(n,o,r):m.call(String(o),n,r)},function(e,t){var r=u(m,e,this,t,m!==n);if(r.done)return r.value;var c=o(e),d=String(this),v=i(c,RegExp),p=c.unicode,g=(c.ignoreCase?"i":"")+(c.multiline?"m":"")+(c.unicode?"u":"")+(h?"y":"g"),b=new v(h?c:"^(?:"+c.source+")",g),_=void 0===t?y:t>>>0;if(0===_)return[];if(0===d.length)return null===l(b,d)?[d]:[];var w=0,x=0,I=[];while(x1&&i.call(a[0],n,function(){for(u=1;u0&&"pre"===t.row.metadata.env?n("el-tag",{attrs:{type:"warning"}},[e._v("预发布")]):e._e(),e._v(" "),t.row.parentId>0&&"gray"===t.row.metadata.env?n("el-tag",{attrs:{type:"info"}},[e._v("灰度")]):e._e(),e._v(" "),t.row.parentId>0&&!t.row.metadata.env?n("el-tag",{attrs:{type:"success"}},[e._v("线上")]):e._e()],1):e._e()]}}])}),e._v(" "),n("el-table-column",{attrs:{prop:"metadata",label:"metadata",width:"250"},scopedSlots:e._u([{key:"default",fn:function(t){return[t.row.parentId>0?n("span",[e._v(e._s(JSON.stringify(t.row.metadata)))]):e._e()]}}])}),e._v(" "),n("el-table-column",{attrs:{prop:"status",label:"服务状态",width:"100"},scopedSlots:e._u([{key:"default",fn:function(t){return[t.row.parentId>0&&"UP"===t.row.status?n("el-tag",{attrs:{type:"success"}},[e._v("正常")]):e._e(),e._v(" "),t.row.parentId>0&&"STARTING"===t.row.status?n("el-tag",{attrs:{type:"info"}},[e._v("正在启动")]):e._e(),e._v(" "),t.row.parentId>0&&"UNKNOWN"===t.row.status?n("el-tag",[e._v("未知")]):e._e(),e._v(" "),t.row.parentId>0&&("OUT_OF_SERVICE"===t.row.status||"DOWN"===t.row.status)?n("el-tag",{attrs:{type:"danger"}},[e._v("已禁用")]):e._e()]}}])}),e._v(" "),n("el-table-column",{attrs:{prop:"updateTime",label:"最后更新时间",width:"160"}}),e._v(" "),n("el-table-column",{attrs:{label:"操作",width:"250"},scopedSlots:e._u([{key:"default",fn:function(t){return[0===t.row.parentId?n("div",[n("el-button",{attrs:{type:"text",size:"mini"},on:{click:function(n){return e.onGrayConfigUpdate(t.row)}}},[e._v("设置灰度参数")])],1):e._e(),e._v(" "),t.row.parentId>0?n("div",["UP"===t.row.status?n("span",["pre"===t.row.metadata.env?n("el-button",{attrs:{type:"text",size:"mini"},on:{click:function(n){return e.onEnvPreClose(t.row)}}},[e._v("结束预发布")]):e._e(),e._v(" "),"gray"===t.row.metadata.env?n("el-button",{attrs:{type:"text",size:"mini"},on:{click:function(n){return e.onEnvGrayClose(t.row)}}},[e._v("结束灰度")]):e._e(),e._v(" "),t.row.metadata.env?e._e():n("el-button",{attrs:{type:"text",size:"mini"},on:{click:function(n){return e.onEnvPreOpen(t.row)}}},[e._v("开启预发布")]),e._v(" "),t.row.metadata.env?e._e():n("el-button",{attrs:{type:"text",size:"mini"},on:{click:function(n){return e.onEnvGrayOpen(t.row)}}},[e._v("开启灰度")])],1):e._e(),e._v(" "),n("span",{staticStyle:{"margin-left":"10px"}},["UP"===t.row.status?n("el-button",{attrs:{type:"text",size:"mini"},on:{click:function(n){return e.onDisable(t.row)}}},[e._v("禁用")]):e._e(),e._v(" "),"OUT_OF_SERVICE"===t.row.status?n("el-button",{attrs:{type:"text",size:"mini"},on:{click:function(n){return e.onEnable(t.row)}}},[e._v("启用")]):e._e()],1)]):e._e()]}}])})],1),e._v(" "),n("el-dialog",{attrs:{title:"灰度设置",visible:e.grayDialogVisible,"close-on-click-modal":!1},on:{"update:visible":function(t){e.grayDialogVisible=t},close:function(t){return e.resetForm("grayForm")}}},[n("el-form",{ref:"grayForm",attrs:{model:e.grayForm,rules:e.grayFormRules,size:"mini"}},[n("el-form-item",{attrs:{label:"serviceId"}},[e._v("\n "+e._s(e.grayForm.serviceId)+"\n ")]),e._v(" "),n("el-tabs",{attrs:{type:"card"},model:{value:e.tabsActiveName,callback:function(t){e.tabsActiveName=t},expression:"tabsActiveName"}},[n("el-tab-pane",{attrs:{label:"灰度用户",name:"first"}},[n("el-alert",{staticStyle:{"margin-bottom":"20px"},attrs:{title:"可以是appId,或userId,多个用英文逗号隔开",type:"info",closable:!1}}),e._v(" "),n("el-form-item",{attrs:{prop:"userKeyContent"}},[n("el-input",{attrs:{placeholder:"可以是appId,或userId,多个用英文逗号隔开",type:"textarea",rows:6},model:{value:e.grayForm.userKeyContent,callback:function(t){e.$set(e.grayForm,"userKeyContent",t)},expression:"grayForm.userKeyContent"}})],1)],1),e._v(" "),n("el-tab-pane",{attrs:{label:"接口配置",name:"second"}},[n("el-form-item",[n("el-button",{attrs:{type:"text"},on:{click:e.addNameVersion}},[e._v("新增灰度接口")])],1),e._v(" "),n("table",{attrs:{cellpadding:"0",cellspacing:"0"}},e._l(e.grayForm.grayRouteConfigList,function(t,r){return n("tr",{key:t.key},[n("td",[n("el-form-item",{key:t.key,attrs:{prop:"grayRouteConfigList."+r+".oldRouteId",rules:{required:!0,message:"不能为空",trigger:["blur","change"]}}},[e._v("\n 老接口:\n "),n("el-select",{staticStyle:{"margin-right":"10px"},on:{change:function(n){return e.onChangeOldRoute(t)}},model:{value:t.oldRouteId,callback:function(n){e.$set(t,"oldRouteId",n)},expression:"grayRouteConfig.oldRouteId"}},e._l(e.routeList,function(e){return n("el-option",{key:e.id,attrs:{label:e.name+"("+e.version+")",value:e.id}})}),1)],1)],1),e._v(" "),n("td",[n("el-form-item",{key:t.key+1,attrs:{prop:"grayRouteConfigList."+r+".newVersion",rules:{required:!0,message:"不能为空",trigger:["blur","change"]}}},[e._v("\n 灰度接口:\n "),n("el-select",{attrs:{"no-data-text":"无数据"},model:{value:t.newVersion,callback:function(n){e.$set(t,"newVersion",n)},expression:"grayRouteConfig.newVersion"}},e._l(e.getGraySelectData(t.oldRouteId),function(e){return n("el-option",{key:e.id,attrs:{label:e.name+"("+e.version+")",value:e.version}})}),1)],1)],1),e._v(" "),n("td",{staticStyle:{"vertical-align":"baseline"}},[n("el-button",{directives:[{name:"show",rawName:"v-show",value:e.grayForm.grayRouteConfigList.length>1,expression:"grayForm.grayRouteConfigList.length > 1"}],attrs:{type:"text"},on:{click:function(n){return n.preventDefault(),e.removeNameVersion(t)}}},[e._v("删除")])],1)])}),0)],1)],1)],1),e._v(" "),n("span",{staticClass:"dialog-footer",attrs:{slot:"footer"},slot:"footer"},[n("el-button",{on:{click:function(t){e.grayDialogVisible=!1}}},[e._v("取 消")]),e._v(" "),n("el-button",{attrs:{type:"primary"},on:{click:e.onGrayConfigSave}},[e._v("确 定")])],1)],1)],1)},o=[],i=(n("28a5"),n("ac6a"),n("7f7f"),{data:function(){var e=/^\S+(,\S+)*$/,t=function(t,n,r){""===n?r(new Error("不能为空")):(e.test(n)||r(new Error("格式不正确")),r())};return{searchFormData:{serviceId:""},grayDialogVisible:!1,grayForm:{serviceId:"",userKeyContent:"",onlyUpdateGrayUserkey:!1,grayRouteConfigList:[]},tabsActiveName:"first",routeList:[],selectNameVersion:[],grayFormRules:{userKeyContent:[{required:!0,message:"不能为空",trigger:"blur"},{validator:t,trigger:"blur"}]},tableData:[]}},created:function(){this.loadTable()},methods:{loadTable:function(){this.post("service.instance.list",this.searchFormData,function(e){this.tableData=this.buildTreeData(e.data)})},loadRouteList:function(e){this.post("route.list/1.2",{serviceId:e.toLowerCase()},function(e){this.routeList=e.data})},getGraySelectData:function(e){return this.routeList.filter(function(t){return e!==t.id&&e.indexOf(t.name)>-1})},buildTreeData:function(e){return e.forEach(function(t){var n=t.parentId;0===n||e.forEach(function(e){if(e.id===n){var r=e.children;r||(r=[]),r.push(t),e.children=r}})}),e=e.filter(function(e){return 0===e.parentId}),e},onSearchTable:function(){this.loadTable()},onDisable:function(e){this.confirm("确定要禁用 ".concat(e.serviceId,"(").concat(e.ipPort,") 吗?"),function(t){this.post("service.instance.offline",e,function(){this.tip("禁用成功"),t(),this.loadTableDelay()})})},onEnable:function(e){this.confirm("确定要启用 ".concat(e.serviceId,"(").concat(e.ipPort,") 吗?"),function(t){this.post("service.instance.online",e,function(){this.tip("启用成功"),t(),this.loadTableDelay()})})},doEnvOnline:function(e,t){this.post("service.instance.env.online",e,function(){t&&t.call(this)})},onEnvPreOpen:function(e){this.confirm("确定要开启 ".concat(e.serviceId,"(").concat(e.ipPort,") 预发布吗?"),function(t){this.post("service.instance.env.pre.open",e,function(){this.tip("预发布成功"),t(),this.loadTableDelay()})})},onEnvPreClose:function(e){this.confirm("确定要结束 ".concat(e.serviceId,"(").concat(e.ipPort,") 预发布吗?"),function(t){this.doEnvOnline(e,function(){this.tip("操作成功"),t(),this.loadTableDelay()})})},onEnvGrayOpen:function(e){this.confirm("确定要开启 ".concat(e.serviceId,"(").concat(e.ipPort,") 灰度吗?"),function(t){this.post("service.instance.env.gray.open",e,function(){this.tip("开启成功"),t(),this.loadTableDelay()})})},onEnvGrayClose:function(e){this.confirm("确定要结束 ".concat(e.serviceId,"(").concat(e.ipPort,") 灰度吗?"),function(t){this.doEnvOnline(e,function(){this.tip("操作成功"),t(),this.loadTableDelay()})})},onGrayConfigUpdate:function(e){var t=e.serviceId;this.loadRouteList(t),this.post("service.gray.config.get",{serviceId:t},function(e){var n=this;this.grayDialogVisible=!0,this.$nextTick(function(){var r=e.data;Object.assign(n.grayForm,{serviceId:t,userKeyContent:r.userKeyContent||"",grayRouteConfigList:n.createGrayRouteConfigList(r.nameVersionContent)})})})},onGrayConfigSave:function(){var e=this;this.$refs.grayForm.validate(function(t){if(t){for(var n=[],r=e.grayForm.grayRouteConfigList,o=0;o=c?e?"":void 0:(i=s.charCodeAt(l),i<55296||i>56319||l+1===c||(a=s.charCodeAt(l+1))<56320||a>57343?e?s.charAt(l):i:e?s.slice(l,l+2):a-56320+(i-55296<<10)+65536)}}},"0390":function(e,t,n){"use strict";var r=n("02f4")(!0);e.exports=function(e,t,n){return t+(n?r(e,t).length:1)}},"0bfb":function(e,t,n){"use strict";var r=n("cb7c");e.exports=function(){var e=r(this),t="";return e.global&&(t+="g"),e.ignoreCase&&(t+="i"),e.multiline&&(t+="m"),e.unicode&&(t+="u"),e.sticky&&(t+="y"),t}},"214f":function(e,t,n){"use strict";n("b0c5");var r=n("2aba"),o=n("32e9"),i=n("79e5"),a=n("be13"),s=n("2b4c"),l=n("520a"),c=s("species"),u=!i(function(){var e=/./;return e.exec=function(){var e=[];return e.groups={a:"7"},e},"7"!=="".replace(e,"$")}),f=function(){var e=/(?:)/,t=e.exec;e.exec=function(){return t.apply(this,arguments)};var n="ab".split(e);return 2===n.length&&"a"===n[0]&&"b"===n[1]}();e.exports=function(e,t,n){var d=s(e),v=!i(function(){var t={};return t[d]=function(){return 7},7!=""[e](t)}),p=v?!i(function(){var t=!1,n=/a/;return n.exec=function(){return t=!0,null},"split"===e&&(n.constructor={},n.constructor[c]=function(){return n}),n[d](""),!t}):void 0;if(!v||!p||"replace"===e&&!u||"split"===e&&!f){var g=/./[d],y=n(a,d,""[e],function(e,t,n,r,o){return t.exec===l?v&&!o?{done:!0,value:g.call(t,n,r)}:{done:!0,value:e.call(n,t,r)}:{done:!1}}),h=y[0],m=y[1];r(String.prototype,e,h),o(RegExp.prototype,d,2==t?function(e,t){return m.call(e,this,t)}:function(e){return m.call(e,this)})}}},"28a5":function(e,t,n){"use strict";var r=n("aae3"),o=n("cb7c"),i=n("ebd6"),a=n("0390"),s=n("9def"),l=n("5f1b"),c=n("520a"),u=n("79e5"),f=Math.min,d=[].push,v="split",p="length",g="lastIndex",y=4294967295,h=!u(function(){RegExp(y,"y")});n("214f")("split",2,function(e,t,n,u){var m;return m="c"=="abbc"[v](/(b)*/)[1]||4!="test"[v](/(?:)/,-1)[p]||2!="ab"[v](/(?:ab)*/)[p]||4!="."[v](/(.?)(.?)/)[p]||"."[v](/()()/)[p]>1||""[v](/.?/)[p]?function(e,t){var o=String(this);if(void 0===e&&0===t)return[];if(!r(e))return n.call(o,e,t);var i,a,s,l=[],u=(e.ignoreCase?"i":"")+(e.multiline?"m":"")+(e.unicode?"u":"")+(e.sticky?"y":""),f=0,v=void 0===t?y:t>>>0,h=new RegExp(e.source,u+"g");while(i=c.call(h,o)){if(a=h[g],a>f&&(l.push(o.slice(f,i.index)),i[p]>1&&i.index=v))break;h[g]===i.index&&h[g]++}return f===o[p]?!s&&h.test("")||l.push(""):l.push(o.slice(f)),l[p]>v?l.slice(0,v):l}:"0"[v](void 0,0)[p]?function(e,t){return void 0===e&&0===t?[]:n.call(this,e,t)}:n,[function(n,r){var o=e(this),i=void 0==n?void 0:n[t];return void 0!==i?i.call(n,o,r):m.call(String(o),n,r)},function(e,t){var r=u(m,e,this,t,m!==n);if(r.done)return r.value;var c=o(e),d=String(this),v=i(c,RegExp),p=c.unicode,g=(c.ignoreCase?"i":"")+(c.multiline?"m":"")+(c.unicode?"u":"")+(h?"y":"g"),b=new v(h?c:"^(?:"+c.source+")",g),_=void 0===t?y:t>>>0;if(0===_)return[];if(0===d.length)return null===l(b,d)?[d]:[];var w=0,x=0,I=[];while(x1&&i.call(a[0],n,function(){for(u=1;u0&&"pre"===t.row.metadata.env?n("el-tag",{attrs:{type:"warning"}},[e._v("预发布")]):e._e(),e._v(" "),t.row.parentId>0&&"gray"===t.row.metadata.env?n("el-tag",{attrs:{type:"info"}},[e._v("灰度")]):e._e(),e._v(" "),t.row.parentId>0&&!t.row.metadata.env?n("el-tag",{attrs:{type:"success"}},[e._v("线上")]):e._e()],1):e._e()]}}])}),e._v(" "),n("el-table-column",{attrs:{prop:"metadata",label:"metadata",width:"250"},scopedSlots:e._u([{key:"default",fn:function(t){return[t.row.parentId>0?n("span",[e._v(e._s(JSON.stringify(t.row.metadata)))]):e._e()]}}])}),e._v(" "),n("el-table-column",{attrs:{prop:"status",label:"服务状态",width:"100"},scopedSlots:e._u([{key:"default",fn:function(t){return[t.row.parentId>0&&"UP"===t.row.status?n("el-tag",{attrs:{type:"success"}},[e._v("正常")]):e._e(),e._v(" "),t.row.parentId>0&&"STARTING"===t.row.status?n("el-tag",{attrs:{type:"info"}},[e._v("正在启动")]):e._e(),e._v(" "),t.row.parentId>0&&"UNKNOWN"===t.row.status?n("el-tag",[e._v("未知")]):e._e(),e._v(" "),t.row.parentId>0&&("OUT_OF_SERVICE"===t.row.status||"DOWN"===t.row.status)?n("el-tag",{attrs:{type:"danger"}},[e._v("已禁用")]):e._e()]}}])}),e._v(" "),n("el-table-column",{attrs:{prop:"updateTime",label:"最后更新时间",width:"160"}}),e._v(" "),n("el-table-column",{attrs:{label:"操作",width:"250"},scopedSlots:e._u([{key:"default",fn:function(t){return[0===t.row.parentId?n("div",[n("el-button",{attrs:{type:"text",size:"mini"},on:{click:function(n){return e.onGrayConfigUpdate(t.row)}}},[e._v("设置灰度参数")])],1):e._e(),e._v(" "),t.row.parentId>0?n("div",["UP"===t.row.status?n("span",["pre"===t.row.metadata.env?n("el-button",{attrs:{type:"text",size:"mini"},on:{click:function(n){return e.onEnvPreClose(t.row)}}},[e._v("结束预发布")]):e._e(),e._v(" "),"gray"===t.row.metadata.env?n("el-button",{attrs:{type:"text",size:"mini"},on:{click:function(n){return e.onEnvGrayClose(t.row)}}},[e._v("结束灰度")]):e._e(),e._v(" "),t.row.metadata.env?e._e():n("el-button",{attrs:{type:"text",size:"mini"},on:{click:function(n){return e.onEnvPreOpen(t.row)}}},[e._v("开启预发布")]),e._v(" "),t.row.metadata.env?e._e():n("el-button",{attrs:{type:"text",size:"mini"},on:{click:function(n){return e.onEnvGrayOpen(t.row)}}},[e._v("开启灰度")])],1):e._e(),e._v(" "),n("span",{staticStyle:{"margin-left":"10px"}},["UP"===t.row.status?n("el-button",{attrs:{type:"text",size:"mini"},on:{click:function(n){return e.onDisable(t.row)}}},[e._v("禁用")]):e._e(),e._v(" "),"OUT_OF_SERVICE"===t.row.status?n("el-button",{attrs:{type:"text",size:"mini"},on:{click:function(n){return e.onEnable(t.row)}}},[e._v("启用")]):e._e()],1)]):e._e()]}}])})],1),e._v(" "),n("el-dialog",{attrs:{title:"灰度设置",visible:e.grayDialogVisible,"close-on-click-modal":!1},on:{"update:visible":function(t){e.grayDialogVisible=t},close:function(t){return e.resetForm("grayForm")}}},[n("el-form",{ref:"grayForm",attrs:{model:e.grayForm,rules:e.grayFormRules,size:"mini"}},[n("el-form-item",{attrs:{label:"serviceId"}},[e._v("\n "+e._s(e.grayForm.serviceId)+"\n ")]),e._v(" "),n("el-tabs",{attrs:{type:"card"},model:{value:e.tabsActiveName,callback:function(t){e.tabsActiveName=t},expression:"tabsActiveName"}},[n("el-tab-pane",{attrs:{label:"灰度用户",name:"first"}},[n("el-alert",{staticStyle:{"margin-bottom":"20px"},attrs:{title:"可以是appId或IP地址,多个用英文逗号隔开",type:"info",closable:!1}}),e._v(" "),n("el-form-item",{attrs:{prop:"userKeyContent"}},[n("el-input",{attrs:{placeholder:"可以是appId或IP地址,多个用英文逗号隔开",type:"textarea",rows:6},model:{value:e.grayForm.userKeyContent,callback:function(t){e.$set(e.grayForm,"userKeyContent",t)},expression:"grayForm.userKeyContent"}})],1)],1),e._v(" "),n("el-tab-pane",{attrs:{label:"接口配置",name:"second"}},[n("el-form-item",[n("el-button",{attrs:{type:"text"},on:{click:e.addNameVersion}},[e._v("新增灰度接口")])],1),e._v(" "),n("table",{attrs:{cellpadding:"0",cellspacing:"0"}},e._l(e.grayForm.grayRouteConfigList,function(t,r){return n("tr",{key:t.key},[n("td",[n("el-form-item",{key:t.key,attrs:{prop:"grayRouteConfigList."+r+".oldRouteId",rules:{required:!0,message:"不能为空",trigger:["blur","change"]}}},[e._v("\n 老接口:\n "),n("el-select",{staticStyle:{"margin-right":"10px"},on:{change:function(n){return e.onChangeOldRoute(t)}},model:{value:t.oldRouteId,callback:function(n){e.$set(t,"oldRouteId",n)},expression:"grayRouteConfig.oldRouteId"}},e._l(e.routeList,function(e){return n("el-option",{key:e.id,attrs:{label:e.name+"("+e.version+")",value:e.id}})}),1)],1)],1),e._v(" "),n("td",[n("el-form-item",{key:t.key+1,attrs:{prop:"grayRouteConfigList."+r+".newVersion",rules:{required:!0,message:"不能为空",trigger:["blur","change"]}}},[e._v("\n 灰度接口:\n "),n("el-select",{attrs:{"no-data-text":"无数据"},model:{value:t.newVersion,callback:function(n){e.$set(t,"newVersion",n)},expression:"grayRouteConfig.newVersion"}},e._l(e.getGraySelectData(t.oldRouteId),function(e){return n("el-option",{key:e.id,attrs:{label:e.name+"("+e.version+")",value:e.version}})}),1)],1)],1),e._v(" "),n("td",{staticStyle:{"vertical-align":"baseline"}},[n("el-button",{directives:[{name:"show",rawName:"v-show",value:e.grayForm.grayRouteConfigList.length>1,expression:"grayForm.grayRouteConfigList.length > 1"}],attrs:{type:"text"},on:{click:function(n){return n.preventDefault(),e.removeNameVersion(t)}}},[e._v("删除")])],1)])}),0)],1)],1)],1),e._v(" "),n("span",{staticClass:"dialog-footer",attrs:{slot:"footer"},slot:"footer"},[n("el-button",{on:{click:function(t){e.grayDialogVisible=!1}}},[e._v("取 消")]),e._v(" "),n("el-button",{attrs:{type:"primary"},on:{click:e.onGrayConfigSave}},[e._v("确 定")])],1)],1)],1)},o=[],i=(n("28a5"),n("ac6a"),n("7f7f"),{data:function(){var e=/^\S+(,\S+)*$/,t=function(t,n,r){""===n?r(new Error("不能为空")):(e.test(n)||r(new Error("格式不正确")),r())};return{searchFormData:{serviceId:""},grayDialogVisible:!1,grayForm:{serviceId:"",userKeyContent:"",onlyUpdateGrayUserkey:!1,grayRouteConfigList:[]},tabsActiveName:"first",routeList:[],selectNameVersion:[],grayFormRules:{userKeyContent:[{required:!0,message:"不能为空",trigger:"blur"},{validator:t,trigger:"blur"}]},tableData:[]}},created:function(){this.loadTable()},methods:{loadTable:function(){this.post("service.instance.list",this.searchFormData,function(e){this.tableData=this.buildTreeData(e.data)})},loadRouteList:function(e){this.post("route.list/1.2",{serviceId:e.toLowerCase()},function(e){this.routeList=e.data})},getGraySelectData:function(e){return this.routeList.filter(function(t){return e!==t.id&&e.indexOf(t.name)>-1})},buildTreeData:function(e){return e.forEach(function(t){var n=t.parentId;0===n||e.forEach(function(e){if(e.id===n){var r=e.children;r||(r=[]),r.push(t),e.children=r}})}),e=e.filter(function(e){return 0===e.parentId}),e},onSearchTable:function(){this.loadTable()},onDisable:function(e){this.confirm("确定要禁用 ".concat(e.serviceId,"(").concat(e.ipPort,") 吗?"),function(t){this.post("service.instance.offline",e,function(){this.tip("禁用成功"),t(),this.loadTableDelay()})})},onEnable:function(e){this.confirm("确定要启用 ".concat(e.serviceId,"(").concat(e.ipPort,") 吗?"),function(t){this.post("service.instance.online",e,function(){this.tip("启用成功"),t(),this.loadTableDelay()})})},doEnvOnline:function(e,t){this.post("service.instance.env.online",e,function(){t&&t.call(this)})},onEnvPreOpen:function(e){this.confirm("确定要开启 ".concat(e.serviceId,"(").concat(e.ipPort,") 预发布吗?"),function(t){this.post("service.instance.env.pre.open",e,function(){this.tip("预发布成功"),t(),this.loadTableDelay()})})},onEnvPreClose:function(e){this.confirm("确定要结束 ".concat(e.serviceId,"(").concat(e.ipPort,") 预发布吗?"),function(t){this.doEnvOnline(e,function(){this.tip("操作成功"),t(),this.loadTableDelay()})})},onEnvGrayOpen:function(e){this.confirm("确定要开启 ".concat(e.serviceId,"(").concat(e.ipPort,") 灰度吗?"),function(t){this.post("service.instance.env.gray.open",e,function(){this.tip("开启成功"),t(),this.loadTableDelay()})})},onEnvGrayClose:function(e){this.confirm("确定要结束 ".concat(e.serviceId,"(").concat(e.ipPort,") 灰度吗?"),function(t){this.doEnvOnline(e,function(){this.tip("操作成功"),t(),this.loadTableDelay()})})},onGrayConfigUpdate:function(e){var t=e.serviceId;this.loadRouteList(t),this.post("service.gray.config.get",{serviceId:t},function(e){var n=this;this.grayDialogVisible=!0,this.$nextTick(function(){var r=e.data;Object.assign(n.grayForm,{serviceId:t,userKeyContent:r.userKeyContent||"",grayRouteConfigList:n.createGrayRouteConfigList(r.nameVersionContent)})})})},onGrayConfigSave:function(){var e=this;this.$refs.grayForm.validate(function(t){if(t){for(var n=[],r=e.grayForm.grayRouteConfigList,o=0;o From 9bb6bcb9cbc14b8c1b177ee1c27a9ae120b5cdea Mon Sep 17 00:00:00 2001 From: tanghc Date: Wed, 15 Jan 2020 18:05:18 +0800 Subject: [PATCH 21/55] 3.0.0 --- doc/docs/files/10110_预发布灰度发布.md | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/doc/docs/files/10110_预发布灰度发布.md b/doc/docs/files/10110_预发布灰度发布.md index f850baee..a468e932 100644 --- a/doc/docs/files/10110_预发布灰度发布.md +++ b/doc/docs/files/10110_预发布灰度发布.md @@ -18,7 +18,7 @@ SOP开启预发布步骤如下: 修改网关工程配置文件,指定预发布域名 ```properties -# 预发布网关域名 +# 预发布网关域名,多个用英文逗号(,)隔开 pre.domain=openpre.domain.com ``` 重启网关 @@ -38,7 +38,18 @@ pre.domain=openpre.domain.com - 先设置灰度参数,指定灰度appId和灰度接口 - 服务器实例开启灰度 + 参考类: -- PreEnvGrayFilter.java -- EnvironmentServerChooser.java \ No newline at end of file +- SopLoadBalancerClient.java gateway网关下预发布/灰度服务选取 +- EnvironmentServerChooser.java zuul网关下预发布/灰度服务选取 + +### 自定义判断灰度用户 + +默认根据`appId`和`IP`来判断灰度用户,如果要通过其它维度来判断是否是灰度用户,可实现GrayUserBuilder接口, +然后在springboot main方法中调用如下方法 + +```java +ApiConfig.getInstance().addGrayUserBuilder(new XXGrayUserBuilder()); +``` +参考:com.gitee.sop.gatewaycommon.loadbalancer.builder.AppIdGrayUserBuilder.java \ No newline at end of file From 23bbf26db7a8b507dba333a3fee9198c21e66d4e Mon Sep 17 00:00:00 2001 From: tanghc Date: Wed, 15 Jan 2020 18:08:35 +0800 Subject: [PATCH 22/55] =?UTF-8?q?=E9=87=8D=E6=9E=84=E9=A2=84=E5=8F=91?= =?UTF-8?q?=E5=B8=83/=E7=81=B0=E5=BA=A6=E5=8F=91=E5=B8=83=E7=8E=AF?= =?UTF-8?q?=E5=A2=83=E9=80=89=E6=8B=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- changelog.md | 1 + .../bridge/SopGatewayAutoConfiguration.java | 2 + .../src/main/resources/sop-bridge.properties | 4 +- .../bridge/SopGatewayAutoConfiguration.java | 3 + .../sop/gatewaycommon/bean/ApiConfig.java | 14 ++ .../sop/gatewaycommon/bean/ApiParamAware.java | 10 ++ .../sop/gatewaycommon/bean/SopConstants.java | 4 + .../BaseGatewayConfiguration.java | 30 +++++ .../gateway/filter/IndexFilter.java | 2 +- .../filter/SopLoadBalancerClientFilter.java | 32 +++++ .../GatewayLoadBalanceServerChooser.java | 29 ++++ .../loadbalancer/NacosServerIntrospector.java | 23 ++++ .../loadbalancer/SopLoadBalancerClient.java | 107 +++++++++++++++ .../gateway/route/GatewayForwardChooser.java | 2 +- .../EnvironmentServerChooser.java | 64 --------- .../EurekaEnvironmentServerChooser.java | 16 --- .../loadbalancer/LoadBalanceConfig.java | 8 ++ .../LoadBalanceServerChooser.java | 127 ++++++++++++++++++ .../loadbalancer/ServerChooserContext.java | 35 +++++ .../builder/AppIdGrayUserBuilder.java | 19 +++ .../loadbalancer/builder/GrayUserBuilder.java | 24 ++++ .../builder/IpGrayUserBuilder.java | 19 +++ .../manager/AbstractConfiguration.java | 25 +++- .../manager/EnvironmentKeys.java | 15 ++- .../sop/gatewaycommon/param/ApiParam.java | 10 ++ .../route/BaseForwardChooser.java | 25 +++- .../route/EurekaRegistryListener.java | 6 - .../zuul/loadbalancer/BaseServerChooser.java | 81 ----------- .../EnvironmentServerChooser.java | 55 ++++++++ .../ZuulLoadBalanceServerChooser.java | 24 ++++ .../zuul/route/ZuulForwardChooser.java | 2 +- .../mapping/ApiMappingHandlerMapping.java | 1 - 32 files changed, 638 insertions(+), 181 deletions(-) create mode 100644 sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/ApiParamAware.java create mode 100644 sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/SopLoadBalancerClientFilter.java create mode 100644 sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/loadbalancer/GatewayLoadBalanceServerChooser.java create mode 100644 sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/loadbalancer/NacosServerIntrospector.java create mode 100644 sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/loadbalancer/SopLoadBalancerClient.java delete mode 100644 sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/loadbalancer/EnvironmentServerChooser.java delete mode 100644 sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/loadbalancer/EurekaEnvironmentServerChooser.java create mode 100644 sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/loadbalancer/LoadBalanceConfig.java create mode 100644 sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/loadbalancer/LoadBalanceServerChooser.java create mode 100644 sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/loadbalancer/ServerChooserContext.java create mode 100644 sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/loadbalancer/builder/AppIdGrayUserBuilder.java create mode 100644 sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/loadbalancer/builder/GrayUserBuilder.java create mode 100644 sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/loadbalancer/builder/IpGrayUserBuilder.java delete mode 100644 sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/loadbalancer/BaseServerChooser.java create mode 100644 sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/loadbalancer/EnvironmentServerChooser.java create mode 100644 sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/loadbalancer/ZuulLoadBalanceServerChooser.java diff --git a/changelog.md b/changelog.md index 8a15f21a..828928df 100644 --- a/changelog.md +++ b/changelog.md @@ -3,6 +3,7 @@ ## 3.0.0 - 重构spring cloud gateway网关 +- 重构`预发布/灰度发布环境选择` - zuul和gateway网关二合一 - 精简配置文件 - 优化文档中心页面 diff --git a/sop-common/sop-bridge-gateway/src/main/java/com/gitee/sop/bridge/SopGatewayAutoConfiguration.java b/sop-common/sop-bridge-gateway/src/main/java/com/gitee/sop/bridge/SopGatewayAutoConfiguration.java index d38488fd..e454f0a1 100644 --- a/sop-common/sop-bridge-gateway/src/main/java/com/gitee/sop/bridge/SopGatewayAutoConfiguration.java +++ b/sop-common/sop-bridge-gateway/src/main/java/com/gitee/sop/bridge/SopGatewayAutoConfiguration.java @@ -1,12 +1,14 @@ package com.gitee.sop.bridge; import com.gitee.sop.gatewaycommon.gateway.configuration.AlipayGatewayConfiguration; +import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; /** * https://blog.csdn.net/seashouwang/article/details/80299571 * @author tanghc */ +@Configuration @Import(AlipayGatewayConfiguration.class) public class SopGatewayAutoConfiguration { } diff --git a/sop-common/sop-bridge-gateway/src/main/resources/sop-bridge.properties b/sop-common/sop-bridge-gateway/src/main/resources/sop-bridge.properties index f3085c07..0627a28d 100644 --- a/sop-common/sop-bridge-gateway/src/main/resources/sop-bridge.properties +++ b/sop-common/sop-bridge-gateway/src/main/resources/sop-bridge.properties @@ -4,7 +4,9 @@ spring.application.name=sop-gateway sop.secret=MZZOUSTua6LzApIWXCwEgbBmxSzpzC # 网关入口 -gateway.index-path=/ +sop.gateway-index-path=/ + +spring.main.allow-bean-definition-overriding=true # nacos cloud配置 spring.cloud.nacos.discovery.server-addr=${nacos.url} diff --git a/sop-common/sop-bridge-zuul/src/main/java/com/gitee/sop/bridge/SopGatewayAutoConfiguration.java b/sop-common/sop-bridge-zuul/src/main/java/com/gitee/sop/bridge/SopGatewayAutoConfiguration.java index 05762ea2..0b933ecc 100644 --- a/sop-common/sop-bridge-zuul/src/main/java/com/gitee/sop/bridge/SopGatewayAutoConfiguration.java +++ b/sop-common/sop-bridge-zuul/src/main/java/com/gitee/sop/bridge/SopGatewayAutoConfiguration.java @@ -2,13 +2,16 @@ package com.gitee.sop.bridge; import com.gitee.sop.gatewaycommon.zuul.configuration.AlipayZuulConfiguration; import org.springframework.cloud.netflix.zuul.EnableZuulProxy; +import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; /** * https://blog.csdn.net/seashouwang/article/details/80299571 * @author tanghc */ +@Configuration @EnableZuulProxy @Import(AlipayZuulConfiguration.class) public class SopGatewayAutoConfiguration { } + 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 d348be42..4cdbb9c7 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,9 @@ package com.gitee.sop.gatewaycommon.bean; 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.loadbalancer.builder.AppIdGrayUserBuilder; +import com.gitee.sop.gatewaycommon.loadbalancer.builder.GrayUserBuilder; +import com.gitee.sop.gatewaycommon.loadbalancer.builder.IpGrayUserBuilder; import com.gitee.sop.gatewaycommon.manager.DefaultEnvGrayManager; import com.gitee.sop.gatewaycommon.manager.DefaultIPBlacklistManager; import com.gitee.sop.gatewaycommon.manager.DefaultIsvRoutePermissionManager; @@ -41,6 +44,7 @@ import org.apache.commons.lang3.StringUtils; import org.springframework.web.server.ServerWebExchange; import java.util.ArrayList; +import java.util.Comparator; import java.util.List; import java.util.Map; @@ -53,6 +57,9 @@ public class ApiConfig { private static ApiConfig instance = new ApiConfig(); private ApiConfig() { + grayUserBuilders = new ArrayList<>(4); + grayUserBuilders.add(new AppIdGrayUserBuilder()); + grayUserBuilders.add(new IpGrayUserBuilder()); } /** @@ -193,6 +200,13 @@ public class ApiConfig { private boolean useGateway; + private List grayUserBuilders; + + public void addGrayUserBuilder(GrayUserBuilder grayUserBuilder) { + grayUserBuilders.add(grayUserBuilder); + grayUserBuilders.sort(Comparator.comparing(GrayUserBuilder::order)); + } + 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/ApiParamAware.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/ApiParamAware.java new file mode 100644 index 00000000..51b03d06 --- /dev/null +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/ApiParamAware.java @@ -0,0 +1,10 @@ +package com.gitee.sop.gatewaycommon.bean; + +import com.gitee.sop.gatewaycommon.param.ApiParam; + +/** + * @author tanghc + */ +public interface ApiParamAware { + ApiParam getApiParam(T t); +} diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/SopConstants.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/SopConstants.java index 61fbe357..ab9cad69 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/SopConstants.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/SopConstants.java @@ -54,4 +54,8 @@ public class SopConstants { public static final String UNKNOWN_METHOD = "_sop_unknown_method_"; public static final String UNKNOWN_VERSION = "_sop_unknown_version_"; + public static final String METADATA_ENV_KEY = "env"; + public static final String METADATA_ENV_PRE_VALUE = "pre"; + public static final String METADATA_ENV_GRAY_VALUE = "gray"; + } 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 c191985d..9c1d356f 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 @@ -8,7 +8,9 @@ import com.gitee.sop.gatewaycommon.gateway.filter.GatewayModifyResponseGatewayFi import com.gitee.sop.gatewaycommon.gateway.filter.IndexFilter; import com.gitee.sop.gatewaycommon.gateway.filter.LimitFilter; import com.gitee.sop.gatewaycommon.gateway.filter.ParameterFormatterFilter; +import com.gitee.sop.gatewaycommon.gateway.filter.SopLoadBalancerClientFilter; import com.gitee.sop.gatewaycommon.gateway.handler.GatewayExceptionHandler; +import com.gitee.sop.gatewaycommon.gateway.loadbalancer.SopLoadBalancerClient; import com.gitee.sop.gatewaycommon.gateway.route.GatewayForwardChooser; import com.gitee.sop.gatewaycommon.gateway.route.GatewayRouteCache; import com.gitee.sop.gatewaycommon.gateway.route.GatewayRouteRepository; @@ -17,6 +19,10 @@ import com.gitee.sop.gatewaycommon.manager.RouteRepositoryContext; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler; +import org.springframework.cloud.client.loadbalancer.LoadBalancerClient; +import org.springframework.cloud.gateway.config.LoadBalancerProperties; +import org.springframework.cloud.gateway.filter.LoadBalancerClientFilter; +import org.springframework.cloud.netflix.ribbon.SpringClientFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Primary; import org.springframework.core.Ordered; @@ -111,4 +117,28 @@ public class BaseGatewayConfiguration extends AbstractConfiguration { GatewayForwardChooser gatewayForwardChooser() { return new GatewayForwardChooser(); } + + /** + * 扩展默认的负载均衡选择,默认使用的是RibbonLoadBalancerClient。当配置了pre.domain时才生效 + * @param clientFactory + * @return + */ + @Primary + @Bean + LoadBalancerClient sopLoadBalancerClient(SpringClientFactory clientFactory) { + return new SopLoadBalancerClient(clientFactory); + } + + /** + * 扩展默认的负载均衡过滤器,默认是LoadBalancerClientFilter。当配置了pre.domain时才生效 + * @param sopLoadBalancerClient SopLoadBalancerClient + * @param loadBalancerProperties loadBalancerProperties + * @return + */ + @Primary + @Bean + LoadBalancerClientFilter loadBalancerClientFilter(LoadBalancerClient sopLoadBalancerClient, LoadBalancerProperties loadBalancerProperties) { + return new SopLoadBalancerClientFilter(sopLoadBalancerClient, loadBalancerProperties); + } + } diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/IndexFilter.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/IndexFilter.java index 5441eb1d..9af4a5e3 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/IndexFilter.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/IndexFilter.java @@ -43,7 +43,7 @@ public class IndexFilter implements WebFilter { private static final String REST_PATH_PREFIX = "/rest"; private static final String SOP_PATH_PREFIX = "/sop"; - @Value("${gateway.index-path:/}") + @Value("${sop.gateway-index-path:/}") private String indexPath; @Autowired diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/SopLoadBalancerClientFilter.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/SopLoadBalancerClientFilter.java new file mode 100644 index 00000000..b8e74c55 --- /dev/null +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/SopLoadBalancerClientFilter.java @@ -0,0 +1,32 @@ +package com.gitee.sop.gatewaycommon.gateway.filter; + +import com.gitee.sop.gatewaycommon.gateway.loadbalancer.SopLoadBalancerClient; +import org.springframework.cloud.client.ServiceInstance; +import org.springframework.cloud.client.loadbalancer.LoadBalancerClient; +import org.springframework.cloud.gateway.config.LoadBalancerProperties; +import org.springframework.cloud.gateway.filter.LoadBalancerClientFilter; +import org.springframework.web.server.ServerWebExchange; + +import java.net.URI; + +import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR; + +/** + * 扩展负载均衡过滤器 + * @author tanghc + */ +public class SopLoadBalancerClientFilter extends LoadBalancerClientFilter { + public SopLoadBalancerClientFilter(LoadBalancerClient loadBalancer, LoadBalancerProperties properties) { + super(loadBalancer, properties); + } + + @Override + protected ServiceInstance choose(ServerWebExchange exchange) { + if (loadBalancer instanceof SopLoadBalancerClient) { + SopLoadBalancerClient sopLoadBalancerClient = (SopLoadBalancerClient)loadBalancer; + return sopLoadBalancerClient.choose(((URI) exchange.getAttribute(GATEWAY_REQUEST_URL_ATTR)).getHost(), exchange); + } else { + return super.choose(exchange); + } + } +} diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/loadbalancer/GatewayLoadBalanceServerChooser.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/loadbalancer/GatewayLoadBalanceServerChooser.java new file mode 100644 index 00000000..8a6f8886 --- /dev/null +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/loadbalancer/GatewayLoadBalanceServerChooser.java @@ -0,0 +1,29 @@ +package com.gitee.sop.gatewaycommon.gateway.loadbalancer; + +import com.gitee.sop.gatewaycommon.gateway.ServerWebExchangeUtil; +import com.gitee.sop.gatewaycommon.loadbalancer.LoadBalanceServerChooser; +import com.gitee.sop.gatewaycommon.param.ApiParam; +import org.springframework.cloud.client.ServiceInstance; +import org.springframework.cloud.netflix.ribbon.SpringClientFactory; +import org.springframework.web.server.ServerWebExchange; + +/** + * @author tanghc + */ +public class GatewayLoadBalanceServerChooser extends LoadBalanceServerChooser { + + public GatewayLoadBalanceServerChooser(SpringClientFactory clientFactory) { + this.setClientFactory(clientFactory); + } + + @Override + public String getHost(ServerWebExchange exchange) { + return exchange.getRequest().getURI().getHost(); + } + + @Override + public ApiParam getApiParam(ServerWebExchange exchange) { + return ServerWebExchangeUtil.getApiParam(exchange); + } + +} diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/loadbalancer/NacosServerIntrospector.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/loadbalancer/NacosServerIntrospector.java new file mode 100644 index 00000000..565fa79a --- /dev/null +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/loadbalancer/NacosServerIntrospector.java @@ -0,0 +1,23 @@ +package com.gitee.sop.gatewaycommon.gateway.loadbalancer; + +import com.netflix.loadbalancer.Server; +import org.springframework.cloud.alibaba.nacos.ribbon.NacosServer; +import org.springframework.cloud.netflix.ribbon.DefaultServerIntrospector; + +import java.util.Map; + +/** + * @author tanghc + */ +public class NacosServerIntrospector extends DefaultServerIntrospector { + + @Override + public Map getMetadata(Server server) { + if (server instanceof NacosServer) { + NacosServer discoveryServer = (NacosServer)server; + return discoveryServer.getInstance().getMetadata(); + } else { + return super.getMetadata(server); + } + } +} diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/loadbalancer/SopLoadBalancerClient.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/loadbalancer/SopLoadBalancerClient.java new file mode 100644 index 00000000..9f38866b --- /dev/null +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/loadbalancer/SopLoadBalancerClient.java @@ -0,0 +1,107 @@ +package com.gitee.sop.gatewaycommon.gateway.loadbalancer; + +import com.gitee.sop.gatewaycommon.gateway.ServerWebExchangeUtil; +import com.gitee.sop.gatewaycommon.loadbalancer.ServerChooserContext; +import com.gitee.sop.gatewaycommon.param.ApiParam; +import com.netflix.client.config.IClientConfig; +import com.netflix.loadbalancer.Server; +import org.springframework.cloud.client.ServiceInstance; +import org.springframework.cloud.netflix.ribbon.DefaultServerIntrospector; +import org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient; +import org.springframework.cloud.netflix.ribbon.RibbonUtils; +import org.springframework.cloud.netflix.ribbon.ServerIntrospector; +import org.springframework.cloud.netflix.ribbon.SpringClientFactory; +import org.springframework.web.server.ServerWebExchange; + +import java.util.List; +import java.util.concurrent.ThreadLocalRandom; + +/** + * 重写负载均衡处理。 + * 默认使用的是RibbonLoadBalancerClient类,详见org.springframework.cloud.netflix.ribbon.RibbonAutoConfiguration#loadBalancerClient() + * + * @author tanghc + */ +public class SopLoadBalancerClient extends RibbonLoadBalancerClient implements ServerChooserContext { + + private final SpringClientFactory clientFactory; + private GatewayLoadBalanceServerChooser loadBalanceServerChooser; + + public SopLoadBalancerClient(SpringClientFactory clientFactory) { + super(clientFactory); + this.clientFactory = clientFactory; + this.loadBalanceServerChooser = new GatewayLoadBalanceServerChooser(clientFactory); + } + + /** + * New: Select a server using a 'key'. + */ + @Override + public ServiceInstance choose(String serviceId, Object hint) { + return loadBalanceServerChooser.choose( + serviceId + , (ServerWebExchange) hint + , this.getLoadBalancer(serviceId) + , () -> super.choose(serviceId, hint) + , (servers) -> getRibbonServer(serviceId, servers) + ); + } + + @Override + public ApiParam getApiParam(ServerWebExchange exchange) { + return ServerWebExchangeUtil.getApiParam(exchange); + } + + @Override + public String getHost(ServerWebExchange exchange) { + return exchange.getRequest().getURI().getHost(); + } + + private RibbonServer getRibbonServer(String serviceId, List servers) { + Server server = this.chooseRandomServer(servers); + if (server == null) { + return null; + } + return new RibbonServer( + serviceId + , server + , isSecure(server, serviceId) + , serverIntrospector(serviceId).getMetadata(server) + ); + } + + /** + * 随机选取一台实例 + * + * @param servers 服务列表 + * @return 返回实例,没有返回null + */ + private Server chooseRandomServer(List servers) { + if (servers.isEmpty()) { + return null; + } + int serverCount = servers.size(); + // 随机选取一台实例 + int index = chooseRandomInt(serverCount); + return servers.get(index); + } + + private int chooseRandomInt(int serverCount) { + return ThreadLocalRandom.current().nextInt(serverCount); + } + + private ServerIntrospector serverIntrospector(String serviceId) { + ServerIntrospector serverIntrospector = this.clientFactory.getInstance(serviceId, + ServerIntrospector.class); + if (serverIntrospector == null) { + serverIntrospector = new DefaultServerIntrospector(); + } + return serverIntrospector; + } + + private boolean isSecure(Server server, String serviceId) { + IClientConfig config = this.clientFactory.getClientConfig(serviceId); + ServerIntrospector serverIntrospector = serverIntrospector(serviceId); + return RibbonUtils.isSecure(config, serverIntrospector, server); + } +} diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/route/GatewayForwardChooser.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/route/GatewayForwardChooser.java index 219b1ec4..93feae5c 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/route/GatewayForwardChooser.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/route/GatewayForwardChooser.java @@ -14,7 +14,7 @@ public class GatewayForwardChooser extends BaseForwardChooser private static final String VALIDATE_ERROR_PATH = "/sop/validateError"; @Override - protected ApiParam getApiParam(ServerWebExchange exchange) { + public ApiParam getApiParam(ServerWebExchange exchange) { return ServerWebExchangeUtil.getApiParam(exchange); } diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/loadbalancer/EnvironmentServerChooser.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/loadbalancer/EnvironmentServerChooser.java deleted file mode 100644 index a3e7ddea..00000000 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/loadbalancer/EnvironmentServerChooser.java +++ /dev/null @@ -1,64 +0,0 @@ -package com.gitee.sop.gatewaycommon.loadbalancer; - -import com.gitee.sop.gatewaycommon.bean.SpringContext; -import com.gitee.sop.gatewaycommon.zuul.loadbalancer.BaseServerChooser; -import com.netflix.loadbalancer.Server; -import org.springframework.cloud.alibaba.nacos.ribbon.NacosServer; -import org.springframework.core.env.Environment; - -import javax.servlet.http.HttpServletRequest; -import java.util.Map; - -/** - * 预发布、灰度环境选择,参考自:https://segmentfault.com/a/1190000017412946 - * - * @author tanghc - */ -public class EnvironmentServerChooser extends BaseServerChooser { - - private static final String MEDATA_KEY_ENV = "env"; - private static final String ENV_PRE_VALUE = "pre"; - private static final String ENV_GRAY_VALUE = "gray"; - - /** - * 预发布机器域名 - */ - private static final String PRE_DOMAIN = "localhost"; - - @Override - protected boolean isPreServer(Server server) { - String env = getEnvValue(server); - return ENV_PRE_VALUE.equals(env); - } - - @Override - protected boolean isGrayServer(Server server) { - String env = getEnvValue(server); - return ENV_GRAY_VALUE.equals(env); - } - - private String getEnvValue(Server server) { - // eureka存储的metadata - Map metadata = getMetada(server); - return metadata.get(MEDATA_KEY_ENV); - } - - protected Map getMetada(Server server) { - return ((NacosServer) server).getMetadata(); - } - - - /** - * 通过判断hostname来确定是否是预发布请求,可修改此方法实现自己想要的 - * - * @param request request - * @return 返回true:可以进入到预发环境 - */ - @Override - protected boolean canVisitPre(Server server, HttpServletRequest request) { - String serverName = request.getServerName(); - String domain = SpringContext.getBean(Environment.class).getProperty("pre.domain", PRE_DOMAIN); - return domain.equals(serverName); - } - -} diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/loadbalancer/EurekaEnvironmentServerChooser.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/loadbalancer/EurekaEnvironmentServerChooser.java deleted file mode 100644 index f67ba85b..00000000 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/loadbalancer/EurekaEnvironmentServerChooser.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.gitee.sop.gatewaycommon.loadbalancer; - -import com.netflix.loadbalancer.Server; -import com.netflix.niws.loadbalancer.DiscoveryEnabledServer; - -import java.util.Map; - -/** - * @author tanghc - */ -public class EurekaEnvironmentServerChooser extends EnvironmentServerChooser { - @Override - protected Map getMetada(Server server) { - return ((DiscoveryEnabledServer) server).getInstanceInfo().getMetadata(); - } -} diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/loadbalancer/LoadBalanceConfig.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/loadbalancer/LoadBalanceConfig.java new file mode 100644 index 00000000..77f6c009 --- /dev/null +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/loadbalancer/LoadBalanceConfig.java @@ -0,0 +1,8 @@ +package com.gitee.sop.gatewaycommon.loadbalancer; + +/** + * @author tanghc + */ +public class LoadBalanceConfig { + +} diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/loadbalancer/LoadBalanceServerChooser.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/loadbalancer/LoadBalanceServerChooser.java new file mode 100644 index 00000000..0cea6478 --- /dev/null +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/loadbalancer/LoadBalanceServerChooser.java @@ -0,0 +1,127 @@ +package com.gitee.sop.gatewaycommon.loadbalancer; + +import com.gitee.sop.gatewaycommon.bean.SopConstants; +import com.gitee.sop.gatewaycommon.bean.SpringContext; +import com.netflix.loadbalancer.ILoadBalancer; +import com.netflix.loadbalancer.Server; +import org.springframework.cloud.netflix.ribbon.DefaultServerIntrospector; +import org.springframework.cloud.netflix.ribbon.ServerIntrospector; +import org.springframework.cloud.netflix.ribbon.SpringClientFactory; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.function.Function; +import java.util.function.Supplier; + +/** + * 预发布、灰度发布服务器选择 + * + * @author tanghc + */ +public abstract class LoadBalanceServerChooser implements ServerChooserContext { + + private SpringClientFactory clientFactory; + + /** + * 选择服务器 + * + * @param serviceId serviceId,仅gateway网关有作用 + * @param exchange 请求上下文 + * @param loadBalancer loadBalancer + * @param superChooser 父类默认的选择 + * @param serverChooserFunction 执行选择操作 + * @return 返回服务器实例 + */ + public R choose( + String serviceId + , T exchange + , ILoadBalancer loadBalancer + , Supplier superChooser + , Function, R> serverChooserFunction) { + // 获取所有服务实例 + List servers = loadBalancer.getReachableServers(); + + // 存放预发服务器 + List preServers = new ArrayList<>(4); + // 存放灰度发布服务器 + List grayServers = new ArrayList<>(4); + // 存放非预发服务器 + List notPreServers = new ArrayList<>(4); + + for (Server server : servers) { + // 获取实例metadata + Map metadata = getMetadata(serviceId, server); + // 是否开启了预发模式 + if (this.isPreServer(metadata)) { + preServers.add(server); + } else if (this.isGrayServer(metadata)) { + grayServers.add(server); + } else { + notPreServers.add(server); + } + } + notPreServers.addAll(grayServers); + // 如果没有开启预发布服务和灰度发布,直接用默认的方式 + if (preServers.isEmpty() && grayServers.isEmpty()) { + return superChooser.get(); + } + // 如果是从预发布域名访问过来,则认为是预发布请求 + if (this.isRequestFromPreDomain(exchange)) { + return serverChooserFunction.apply(preServers); + } + // 如果是灰度请求 + if (this.isRequestGrayServer(exchange)) { + return serverChooserFunction.apply(grayServers); + } + + // 到这里说明不能访问预发/灰度服务器,则需要路由到非预发服务器 + return serverChooserFunction.apply(notPreServers); + } + + protected Map getMetadata(String serviceId, Server server) { + return serverIntrospector(serviceId).getMetadata(server); + } + + protected SpringClientFactory getSpringClientFactory() { + if (clientFactory == null) { + clientFactory = SpringContext.getBean(SpringClientFactory.class); + } + return clientFactory; + } + + public void setClientFactory(SpringClientFactory clientFactory) { + this.clientFactory = clientFactory; + } + + private ServerIntrospector serverIntrospector(String serviceId) { + ServerIntrospector serverIntrospector = getSpringClientFactory().getInstance(serviceId, + ServerIntrospector.class); + if (serverIntrospector == null) { + serverIntrospector = new DefaultServerIntrospector(); + } + return serverIntrospector; + } + + /** + * 是否是预发布服务器 + * + * @param metadata metadata + * @return true:是 + */ + private boolean isPreServer(Map metadata) { + return Objects.equals(metadata.get(SopConstants.METADATA_ENV_KEY), SopConstants.METADATA_ENV_PRE_VALUE); + } + + /** + * 是否是灰度发布服务器 + * + * @param metadata metadata + * @return true:是 + */ + private boolean isGrayServer(Map metadata) { + return Objects.equals(metadata.get(SopConstants.METADATA_ENV_KEY), SopConstants.METADATA_ENV_GRAY_VALUE); + } + +} diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/loadbalancer/ServerChooserContext.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/loadbalancer/ServerChooserContext.java new file mode 100644 index 00000000..8b38406b --- /dev/null +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/loadbalancer/ServerChooserContext.java @@ -0,0 +1,35 @@ +package com.gitee.sop.gatewaycommon.loadbalancer; + +import com.gitee.sop.gatewaycommon.bean.ApiParamAware; +import com.gitee.sop.gatewaycommon.manager.EnvironmentKeys; +import com.gitee.sop.gatewaycommon.param.ApiParam; +import org.apache.commons.lang.ArrayUtils; +import org.springframework.util.StringUtils; + +/** + * @author tanghc + */ +public interface ServerChooserContext extends ApiParamAware { + + /** + * 通过判断hostname来确定是否是预发布请求 + * + * @param t t + * @return 返回true:可以进入到预发环境 + */ + default boolean isRequestFromPreDomain(T t) { + String domain = EnvironmentKeys.PRE_DOMAIN.getValue(); + if (StringUtils.isEmpty(domain)) { + return false; + } + String[] domains = domain.split("\\,"); + return ArrayUtils.contains(domains, getHost(t)); + } + + default boolean isRequestGrayServer(T t) { + ApiParam apiParam = getApiParam(t); + return apiParam.isGrayRequest(); + } + + String getHost(T t); +} diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/loadbalancer/builder/AppIdGrayUserBuilder.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/loadbalancer/builder/AppIdGrayUserBuilder.java new file mode 100644 index 00000000..1d4a6027 --- /dev/null +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/loadbalancer/builder/AppIdGrayUserBuilder.java @@ -0,0 +1,19 @@ +package com.gitee.sop.gatewaycommon.loadbalancer.builder; + +import com.gitee.sop.gatewaycommon.param.ApiParam; + +/** + * @author tanghc + */ +public class AppIdGrayUserBuilder implements GrayUserBuilder { + + @Override + public String buildGrayUserKey(ApiParam apiParam) { + return apiParam.fetchAppKey(); + } + + @Override + public int order() { + return 0; + } +} diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/loadbalancer/builder/GrayUserBuilder.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/loadbalancer/builder/GrayUserBuilder.java new file mode 100644 index 00000000..7e23eecb --- /dev/null +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/loadbalancer/builder/GrayUserBuilder.java @@ -0,0 +1,24 @@ +package com.gitee.sop.gatewaycommon.loadbalancer.builder; + +import com.gitee.sop.gatewaycommon.param.ApiParam; + +/** + * @author tanghc + */ +public interface GrayUserBuilder { + + /** + * 获取灰度用户key + * + * @param apiParam apiParam + * @return 返回用户key + */ + String buildGrayUserKey(ApiParam apiParam); + + /** + * 优先级,数字小优先 + * + * @return 返回数字 + */ + int order(); +} diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/loadbalancer/builder/IpGrayUserBuilder.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/loadbalancer/builder/IpGrayUserBuilder.java new file mode 100644 index 00000000..c629b183 --- /dev/null +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/loadbalancer/builder/IpGrayUserBuilder.java @@ -0,0 +1,19 @@ +package com.gitee.sop.gatewaycommon.loadbalancer.builder; + +import com.gitee.sop.gatewaycommon.param.ApiParam; + +/** + * @author tanghc + */ +public class IpGrayUserBuilder implements GrayUserBuilder { + + @Override + public String buildGrayUserKey(ApiParam apiParam) { + return apiParam.fetchIp(); + } + + @Override + public int order() { + return 1; + } +} diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/AbstractConfiguration.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/AbstractConfiguration.java index c8b8845a..d2a7c7ac 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/AbstractConfiguration.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/AbstractConfiguration.java @@ -4,15 +4,16 @@ import com.gitee.sop.gatewaycommon.bean.ApiConfig; import com.gitee.sop.gatewaycommon.bean.ApiContext; import com.gitee.sop.gatewaycommon.bean.BeanInitializer; import com.gitee.sop.gatewaycommon.bean.SpringContext; +import com.gitee.sop.gatewaycommon.gateway.loadbalancer.NacosServerIntrospector; import com.gitee.sop.gatewaycommon.limit.LimitManager; import com.gitee.sop.gatewaycommon.loadbalancer.SopPropertiesFactory; import com.gitee.sop.gatewaycommon.message.ErrorFactory; import com.gitee.sop.gatewaycommon.param.ParameterFormatter; -import com.gitee.sop.gatewaycommon.route.ServiceRouteListener; import com.gitee.sop.gatewaycommon.route.EurekaRegistryListener; import com.gitee.sop.gatewaycommon.route.NacosRegistryListener; import com.gitee.sop.gatewaycommon.route.RegistryListener; import com.gitee.sop.gatewaycommon.route.ServiceListener; +import com.gitee.sop.gatewaycommon.route.ServiceRouteListener; import com.gitee.sop.gatewaycommon.secret.IsvManager; import com.gitee.sop.gatewaycommon.session.SessionManager; import com.gitee.sop.gatewaycommon.validate.SignConfig; @@ -23,6 +24,8 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.cloud.client.discovery.event.HeartbeatEvent; import org.springframework.cloud.netflix.ribbon.PropertiesFactory; +import org.springframework.cloud.netflix.ribbon.ServerIntrospector; +import org.springframework.cloud.netflix.ribbon.eureka.EurekaServerIntrospector; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.context.ApplicationEvent; @@ -159,6 +162,26 @@ public class AbstractConfiguration implements ApplicationContextAware { return createCorsFilter(); } + /** + * 负责获取nacos实例的metadata + * @return + */ + @Bean + @ConditionalOnProperty("spring.cloud.nacos.discovery.server-addr") + ServerIntrospector nacosServerIntrospector() { + return new NacosServerIntrospector(); + } + + /** + * 负责获取eureka实例的metadata + * @return + */ + @Bean + @ConditionalOnProperty("eureka.client.serviceUrl.defaultZone") + ServerIntrospector eurekaServerIntrospector() { + return new EurekaServerIntrospector(); + } + protected CorsFilter createCorsFilter() { UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); this.registerCorsConfiguration(source); diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/EnvironmentKeys.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/EnvironmentKeys.java index f05fa2eb..3fa1b20f 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/EnvironmentKeys.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/EnvironmentKeys.java @@ -1,6 +1,6 @@ package com.gitee.sop.gatewaycommon.manager; -import com.gitee.sop.gatewaycommon.loadbalancer.EnvironmentServerChooser; +import com.gitee.sop.gatewaycommon.zuul.loadbalancer.EnvironmentServerChooser; public enum EnvironmentKeys { SPRING_PROFILES_ACTIVE("spring.profiles.active", "default"), @@ -9,7 +9,7 @@ public enum EnvironmentKeys { */ SPRING_APPLICATION_NAME("spring.application.name"), /** - * 指定负载均衡规则类,默认使用com.gitee.sop.gateway.loadbalancer.PreEnvironmentServerChooser + * 指定负载均衡规则类 */ ZUUL_CUSTOM_RULE_CLASSNAME("zuul.custom-rule-classname", EnvironmentServerChooser.class.getName()), @@ -35,8 +35,11 @@ public enum EnvironmentKeys { /** * 排除其它微服务,正则形式,多个用英文逗号隔开 */ - SOP_SERVICE_EXCLUDE_REGEX("sop.service.exclude-regex") - ; + SOP_SERVICE_EXCLUDE_REGEX("sop.service.exclude-regex"), + /** + * 预发布域名 + */ + PRE_DOMAIN("pre.domain"); private String key; private String defaultValue; @@ -57,4 +60,8 @@ public enum EnvironmentKeys { public String getValue() { return EnvironmentContext.getValue(key, defaultValue); } + + public String getValue(String defaultValue) { + return EnvironmentContext.getValue(key, defaultValue); + } } \ No newline at end of file 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 4d48d78f..1e3559b1 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 @@ -31,6 +31,8 @@ public class ApiParam extends JSONObject implements Param { private String ip; + private boolean isGrayRequest; + private transient UploadContext uploadContext; public void fitNameVersion() { @@ -248,4 +250,12 @@ public class ApiParam extends JSONObject implements Param { public String fetchIp() { return ip; } + + public boolean isGrayRequest() { + return isGrayRequest; + } + + public void setGrayRequest(boolean grayRequest) { + isGrayRequest = grayRequest; + } } diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/route/BaseForwardChooser.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/route/BaseForwardChooser.java index 254560c9..0b7715d5 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/route/BaseForwardChooser.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/route/BaseForwardChooser.java @@ -1,23 +1,28 @@ package com.gitee.sop.gatewaycommon.route; +import com.gitee.sop.gatewaycommon.bean.ApiConfig; import com.gitee.sop.gatewaycommon.bean.RouteDefinition; +import com.gitee.sop.gatewaycommon.bean.ApiParamAware; import com.gitee.sop.gatewaycommon.bean.TargetRoute; +import com.gitee.sop.gatewaycommon.loadbalancer.builder.GrayUserBuilder; import com.gitee.sop.gatewaycommon.manager.EnvGrayManager; import com.gitee.sop.gatewaycommon.manager.RouteRepositoryContext; import com.gitee.sop.gatewaycommon.param.ApiParam; import org.apache.commons.lang3.BooleanUtils; import org.springframework.beans.factory.annotation.Autowired; +import javax.annotation.PostConstruct; +import java.util.Comparator; +import java.util.List; + /** * @author tanghc */ -public abstract class BaseForwardChooser implements ForwardChooser { +public abstract class BaseForwardChooser implements ForwardChooser, ApiParamAware { @Autowired private EnvGrayManager envGrayManager; - protected abstract ApiParam getApiParam(T t); - @Override public ForwardInfo getForwardInfo(T t) { ApiParam apiParam = getApiParam(t); @@ -30,10 +35,11 @@ public abstract class BaseForwardChooser implements ForwardChooser { // 如果服务在灰度阶段,返回一个灰度版本号 String grayVersion = envGrayManager.getVersion(serviceId, nameVersion); // 如果是灰度环境 - if (grayVersion != null && envGrayManager.containsKey(serviceId, apiParam.fetchAppKey())) { + if (grayVersion != null && isGrayUser(serviceId, apiParam)) { String newNameVersion = apiParam.fetchName() + grayVersion; TargetRoute targetRouteDest = RouteRepositoryContext.getRouteRepository().get(newNameVersion); if (targetRouteDest != null) { + apiParam.setGrayRequest(true); if (BooleanUtils.toBoolean(routeDefinitionOrig.getCompatibleMode())) { version = grayVersion; } else { @@ -46,4 +52,15 @@ public abstract class BaseForwardChooser implements ForwardChooser { return new ForwardInfo(path, version); } + protected boolean isGrayUser(String serviceId, ApiParam apiParam) { + List grayUserBuilders = ApiConfig.getInstance().getGrayUserBuilders(); + for (GrayUserBuilder grayUserBuilder : grayUserBuilders) { + String userKey = grayUserBuilder.buildGrayUserKey(apiParam); + if (envGrayManager.containsKey(serviceId, userKey)) { + return true; + } + } + return false; + } + } diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/route/EurekaRegistryListener.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/route/EurekaRegistryListener.java index 6eb37113..55f71a3a 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/route/EurekaRegistryListener.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/route/EurekaRegistryListener.java @@ -1,8 +1,6 @@ package com.gitee.sop.gatewaycommon.route; import com.gitee.sop.gatewaycommon.bean.InstanceDefinition; -import com.gitee.sop.gatewaycommon.loadbalancer.EurekaEnvironmentServerChooser; -import com.gitee.sop.gatewaycommon.manager.EnvironmentKeys; import com.netflix.appinfo.InstanceInfo; import com.netflix.discovery.shared.Application; import com.netflix.discovery.shared.Applications; @@ -25,10 +23,6 @@ import java.util.stream.Collectors; */ public class EurekaRegistryListener extends BaseRegistryListener { - static { - System.setProperty(EnvironmentKeys.ZUUL_CUSTOM_RULE_CLASSNAME.getKey(), EurekaEnvironmentServerChooser.class.getName()); - } - private Set cacheServices = new HashSet<>(); @Override diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/loadbalancer/BaseServerChooser.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/loadbalancer/BaseServerChooser.java deleted file mode 100644 index d08db36b..00000000 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/loadbalancer/BaseServerChooser.java +++ /dev/null @@ -1,81 +0,0 @@ -package com.gitee.sop.gatewaycommon.zuul.loadbalancer; - -import com.google.common.base.Optional; -import com.netflix.loadbalancer.ILoadBalancer; -import com.netflix.loadbalancer.Server; -import com.netflix.loadbalancer.ZoneAvoidanceRule; -import com.netflix.zuul.context.RequestContext; -import lombok.extern.slf4j.Slf4j; - -import javax.servlet.http.HttpServletRequest; -import java.util.List; -import java.util.stream.Collectors; - -/** - * 服务实例选择器 - * - * @author tanghc - */ -@Slf4j -public abstract class BaseServerChooser extends ZoneAvoidanceRule { - - - /** - * 是否是预发布服务器 - * @param server 服务器 - * @return true:是 - */ - protected abstract boolean isPreServer(Server server); - - /** - * 是否是灰度发布服务器 - * @param server 服务器 - * @return true:是 - */ - protected abstract boolean isGrayServer(Server server); - - /** - * 能否访问预发布 - * @param server 预发布服务器 - * @param request request - * @return true:能 - */ - protected abstract boolean canVisitPre(Server server, HttpServletRequest request); - - - @Override - public Server choose(Object key) { - ILoadBalancer lb = getLoadBalancer(); - // 获取服务实例列表 - List allServers = lb.getAllServers(); - HttpServletRequest request = RequestContext.getCurrentContext().getRequest(); - - List preServers = allServers.stream() - .filter(this::isPreServer) - .filter(server -> canVisitPre(server, request)) - .collect(Collectors.toList()); - - if (!preServers.isEmpty()) { - return this.doChoose(preServers, key); - } - - List grayServers = allServers.stream() - .filter(this::isGrayServer) - .collect(Collectors.toList()); - if (!grayServers.isEmpty()) { - return doChoose(grayServers, key); - } - - return super.choose(key); - } - - protected Server doChoose(List servers, Object key) { - Optional server = getPredicate().chooseRoundRobinAfterFiltering(servers, key); - if (server.isPresent()) { - return server.get(); - } else { - return null; - } - } - -} diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/loadbalancer/EnvironmentServerChooser.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/loadbalancer/EnvironmentServerChooser.java new file mode 100644 index 00000000..a9a6c477 --- /dev/null +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/loadbalancer/EnvironmentServerChooser.java @@ -0,0 +1,55 @@ +package com.gitee.sop.gatewaycommon.zuul.loadbalancer; + +import com.gitee.sop.gatewaycommon.loadbalancer.ServerChooserContext; +import com.gitee.sop.gatewaycommon.param.ApiParam; +import com.gitee.sop.gatewaycommon.zuul.ZuulContext; +import com.google.common.base.Optional; +import com.netflix.loadbalancer.Server; +import com.netflix.loadbalancer.ZoneAvoidanceRule; +import com.netflix.zuul.context.RequestContext; +import lombok.extern.slf4j.Slf4j; + +import javax.servlet.http.HttpServletRequest; +import java.util.List; + +/** + * 预发布、灰度环境选择,参考自:https://segmentfault.com/a/1190000017412946 + * + * @author tanghc + */ +@Slf4j +public class EnvironmentServerChooser extends ZoneAvoidanceRule implements ServerChooserContext { + + private ZuulLoadBalanceServerChooser loadBalanceServerChooser = new ZuulLoadBalanceServerChooser(); + + @Override + public String getHost(HttpServletRequest request) { + return request.getServerName(); + } + + @Override + public ApiParam getApiParam(HttpServletRequest request) { + return ZuulContext.getApiParam(); + } + + @Override + public Server choose(Object key) { + return loadBalanceServerChooser.choose( + String.valueOf(key) + , RequestContext.getCurrentContext().getRequest() + , getLoadBalancer() + , () -> super.choose(key) + , (servers) -> this.doChoose(servers, key) + ); + } + + protected Server doChoose(List servers, Object key) { + Optional server = getPredicate().chooseRoundRobinAfterFiltering(servers, key); + if (server.isPresent()) { + return server.get(); + } else { + return null; + } + } + +} diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/loadbalancer/ZuulLoadBalanceServerChooser.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/loadbalancer/ZuulLoadBalanceServerChooser.java new file mode 100644 index 00000000..b1046ee9 --- /dev/null +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/loadbalancer/ZuulLoadBalanceServerChooser.java @@ -0,0 +1,24 @@ +package com.gitee.sop.gatewaycommon.zuul.loadbalancer; + +import com.gitee.sop.gatewaycommon.loadbalancer.LoadBalanceServerChooser; +import com.gitee.sop.gatewaycommon.param.ApiParam; +import com.gitee.sop.gatewaycommon.zuul.ZuulContext; +import com.netflix.loadbalancer.Server; + +import javax.servlet.http.HttpServletRequest; + +/** + * @author tanghc + */ +public class ZuulLoadBalanceServerChooser extends LoadBalanceServerChooser { + + @Override + public String getHost(HttpServletRequest request) { + return request.getServerName(); + } + + @Override + public ApiParam getApiParam(HttpServletRequest request) { + return ZuulContext.getApiParam(); + } +} diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/route/ZuulForwardChooser.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/route/ZuulForwardChooser.java index cea835d5..625d129f 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/route/ZuulForwardChooser.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/route/ZuulForwardChooser.java @@ -11,7 +11,7 @@ import com.netflix.zuul.context.RequestContext; public class ZuulForwardChooser extends BaseForwardChooser { @Override - protected ApiParam getApiParam(RequestContext requestContext) { + public ApiParam getApiParam(RequestContext requestContext) { return ZuulContext.getApiParam(); } diff --git a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/mapping/ApiMappingHandlerMapping.java b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/mapping/ApiMappingHandlerMapping.java index 8185d7f7..1d706005 100644 --- a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/mapping/ApiMappingHandlerMapping.java +++ b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/mapping/ApiMappingHandlerMapping.java @@ -19,7 +19,6 @@ import java.lang.reflect.Method; */ public class ApiMappingHandlerMapping extends RequestMappingHandlerMapping implements PriorityOrdered { - private static StringValueResolver stringValueResolver = new ApiMappingStringValueResolver(); private static StringValueResolver stringValueResolverMVC = new ApiMappingStringValueResolverMVC(); @Override From bba600a4f5e1e6256a395284a532014a00f3d7bd Mon Sep 17 00:00:00 2001 From: tanghc Date: Wed, 15 Jan 2020 18:12:43 +0800 Subject: [PATCH 23/55] 3.0.0 --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 406774fb..1e97f358 100644 --- a/README.md +++ b/README.md @@ -48,6 +48,7 @@ SOP封装了开放平台大部分功能包括:签名验证、统一异常处 - 监控日志 - 支持nacos - 网关动态修改参数 +- 预发布/灰度环境切换 ## 界面预览 @@ -69,7 +70,7 @@ SOP封装了开放平台大部分功能包括:签名验证、统一异常处 - doc:开发文档 - sop-common:公共模块,封装常用功能,包含签名校验、错误处理、限流等功能 -- sop-gateway:网关,统一访问入口,Spring Cloud Zuul实现,可切换成Spring Cloud Gateway +- sop-gateway:网关,统一访问入口,含`Spring Cloud Zuul`和`Spring Cloud Gateway`实现 - sop-example:微服务示例,含springboot,springmvc示例 - sop-website:开放平台对应网站,提供文档API、沙箱测试等内容 - sop-auth:应用授权服务 From c1849bcaf3a9c0d8a29177a303464a814ac4c96b Mon Sep 17 00:00:00 2001 From: tanghc Date: Thu, 16 Jan 2020 09:44:18 +0800 Subject: [PATCH 24/55] =?UTF-8?q?=E4=BC=98=E5=8C=96=E7=81=B0=E5=BA=A6?= =?UTF-8?q?=E9=A2=84=E5=8F=91=E5=B8=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../gatewaycommon/manager/EnvGrayManager.java | 2 + .../zuul/filter/PreEnvGrayFilter.java | 1 + .../zuul/loadbalancer/BaseServerChooser.java | 73 +++++++++++++++---- 3 files changed, 61 insertions(+), 15 deletions(-) diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/EnvGrayManager.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/EnvGrayManager.java index a42030a6..54d36f59 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/EnvGrayManager.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/EnvGrayManager.java @@ -8,6 +8,8 @@ import com.gitee.sop.gatewaycommon.zuul.loadbalancer.ServiceGrayConfig; */ public interface EnvGrayManager extends BeanInitializer { + String ENV_GRAY = "sop.env-gray"; + /** * 保存灰度配置 * @param serviceGrayConfig 灰度配置 diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/filter/PreEnvGrayFilter.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/filter/PreEnvGrayFilter.java index 7245cb74..bc5e00de 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/filter/PreEnvGrayFilter.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/filter/PreEnvGrayFilter.java @@ -42,6 +42,7 @@ public class PreEnvGrayFilter extends BaseZuulFilter { // 如果服务在灰度阶段,返回一个灰度版本号 String version = envGrayManager.getVersion(serviceId, nameVersion); if (version != null && envGrayManager.containsKey(serviceId, apiParam.fetchAppKey())) { + requestContext.set(EnvGrayManager.ENV_GRAY, true); requestContext.addZuulRequestHeader(ParamNames.HEADER_VERSION_NAME, version); } return null; diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/loadbalancer/BaseServerChooser.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/loadbalancer/BaseServerChooser.java index d08db36b..a452476f 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/loadbalancer/BaseServerChooser.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/loadbalancer/BaseServerChooser.java @@ -1,15 +1,20 @@ package com.gitee.sop.gatewaycommon.zuul.loadbalancer; +import com.gitee.sop.gatewaycommon.bean.SpringContext; +import com.gitee.sop.gatewaycommon.manager.EnvGrayManager; import com.google.common.base.Optional; import com.netflix.loadbalancer.ILoadBalancer; import com.netflix.loadbalancer.Server; import com.netflix.loadbalancer.ZoneAvoidanceRule; import com.netflix.zuul.context.RequestContext; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang.ArrayUtils; +import org.springframework.core.env.Environment; +import org.springframework.util.StringUtils; import javax.servlet.http.HttpServletRequest; +import java.util.ArrayList; import java.util.List; -import java.util.stream.Collectors; /** * 服务实例选择器 @@ -47,26 +52,64 @@ public abstract class BaseServerChooser extends ZoneAvoidanceRule { public Server choose(Object key) { ILoadBalancer lb = getLoadBalancer(); // 获取服务实例列表 - List allServers = lb.getAllServers(); + List servers = lb.getReachableServers(); HttpServletRequest request = RequestContext.getCurrentContext().getRequest(); + // 存放预发服务器 + List preServers = new ArrayList<>(4); + // 存放灰度发布服务器 + List grayServers = new ArrayList<>(4); + // 存放非预发服务器 + List notPreServers = new ArrayList<>(4); - List preServers = allServers.stream() - .filter(this::isPreServer) - .filter(server -> canVisitPre(server, request)) - .collect(Collectors.toList()); - - if (!preServers.isEmpty()) { - return this.doChoose(preServers, key); + for (Server server : servers) { + // 是否开启了预发模式 + if (this.isPreServer(server)) { + preServers.add(server); + } else if (this.isGrayServer(server)) { + grayServers.add(server); + } else { + notPreServers.add(server); + } } - - List grayServers = allServers.stream() - .filter(this::isGrayServer) - .collect(Collectors.toList()); - if (!grayServers.isEmpty()) { + notPreServers.addAll(grayServers); + // 如果没有开启预发布服务和灰度发布,直接用默认的方式 + if (preServers.isEmpty() && grayServers.isEmpty()) { + return super.choose(key); + } + // 如果是从预发布域名访问过来,则认为是预发布请求 + if (this.isRequestFromPreDomain(request)) { + return doChoose(preServers, key); + } + // 如果是灰度请求 + if (this.isRequestGrayServer(RequestContext.getCurrentContext())) { return doChoose(grayServers, key); } - return super.choose(key); + // 到这里说明不能访问预发/灰度服务器,则需要路由到非预发服务器 + return doChoose(notPreServers, key); + } + + /** + * 通过判断hostname来确定是否是预发布请求 + * + * @param t t + * @return 返回true:可以进入到预发环境 + */ + protected boolean isRequestFromPreDomain(HttpServletRequest t) { + String domain = SpringContext.getBean(Environment.class).getProperty("pre.domain"); + if (StringUtils.isEmpty(domain)) { + return false; + } + String[] domains = domain.split("\\,"); + return ArrayUtils.contains(domains, getHost(t)); + } + + protected boolean isRequestGrayServer(RequestContext t) { + return t.get(EnvGrayManager.ENV_GRAY) != null; + } + + protected String getHost(HttpServletRequest t) { + return t.getServerName(); } protected Server doChoose(List servers, Object key) { From 6b505dfd8d457f3a4386731f81d47669332d1c77 Mon Sep 17 00:00:00 2001 From: tanghc Date: Thu, 16 Jan 2020 09:46:27 +0800 Subject: [PATCH 25/55] =?UTF-8?q?=E4=BC=98=E5=8C=96=E7=81=B0=E5=BA=A6?= =?UTF-8?q?=E9=A2=84=E5=8F=91=E5=B8=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../gatewaycommon/zuul/loadbalancer/BaseServerChooser.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/loadbalancer/BaseServerChooser.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/loadbalancer/BaseServerChooser.java index a452476f..e92a2fb2 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/loadbalancer/BaseServerChooser.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/loadbalancer/BaseServerChooser.java @@ -53,7 +53,7 @@ public abstract class BaseServerChooser extends ZoneAvoidanceRule { ILoadBalancer lb = getLoadBalancer(); // 获取服务实例列表 List servers = lb.getReachableServers(); - HttpServletRequest request = RequestContext.getCurrentContext().getRequest(); + RequestContext currentContext = RequestContext.getCurrentContext(); // 存放预发服务器 List preServers = new ArrayList<>(4); // 存放灰度发布服务器 @@ -77,11 +77,11 @@ public abstract class BaseServerChooser extends ZoneAvoidanceRule { return super.choose(key); } // 如果是从预发布域名访问过来,则认为是预发布请求 - if (this.isRequestFromPreDomain(request)) { + if (this.isRequestFromPreDomain(currentContext.getRequest())) { return doChoose(preServers, key); } // 如果是灰度请求 - if (this.isRequestGrayServer(RequestContext.getCurrentContext())) { + if (this.isRequestGrayServer(currentContext)) { return doChoose(grayServers, key); } From 3bd540d98ffb6cde3faa2d2f33677c31254c6566 Mon Sep 17 00:00:00 2001 From: tanghc Date: Thu, 16 Jan 2020 09:47:30 +0800 Subject: [PATCH 26/55] 2.5.11 --- changelog.md | 4 ++++ sop-auth/pom.xml | 2 +- sop-common/pom.xml | 2 +- sop-common/sop-gateway-common/pom.xml | 4 ++-- sop-common/sop-service-common/pom.xml | 4 ++-- sop-example/sop-book/sop-book-web/pom.xml | 2 +- sop-example/sop-easyopen/pom.xml | 2 +- sop-example/sop-springmvc/pom.xml | 2 +- sop-example/sop-story/sop-story-web/pom.xml | 2 +- sop-gateway/pom.xml | 2 +- sop-website/pom.xml | 2 +- 11 files changed, 16 insertions(+), 12 deletions(-) diff --git a/changelog.md b/changelog.md index d7202a97..bb93ebb7 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,9 @@ # changelog +## 2.5.11 + +- 优化灰度/预发布请求 + ## 2.5.10 - 优化签名认证,优化校验日志打印 diff --git a/sop-auth/pom.xml b/sop-auth/pom.xml index a17fdc20..2fe15bc3 100644 --- a/sop-auth/pom.xml +++ b/sop-auth/pom.xml @@ -26,7 +26,7 @@ com.gitee.sop sop-service-common - 2.5.10-SNAPSHOT + 2.5.11-SNAPSHOT diff --git a/sop-common/pom.xml b/sop-common/pom.xml index 98e0cf7c..48c9c5f5 100644 --- a/sop-common/pom.xml +++ b/sop-common/pom.xml @@ -5,7 +5,7 @@ 4.0.0 com.gitee.sop sop-common - 2.5.10-SNAPSHOT + 2.5.11-SNAPSHOT pom diff --git a/sop-common/sop-gateway-common/pom.xml b/sop-common/sop-gateway-common/pom.xml index 1486cd9f..b0f6ad38 100644 --- a/sop-common/sop-gateway-common/pom.xml +++ b/sop-common/sop-gateway-common/pom.xml @@ -5,11 +5,11 @@ com.gitee.sop sop-common - 2.5.10-SNAPSHOT + 2.5.11-SNAPSHOT ../pom.xml sop-gateway-common - 2.5.10-SNAPSHOT + 2.5.11-SNAPSHOT jar sop-gateway-common diff --git a/sop-common/sop-service-common/pom.xml b/sop-common/sop-service-common/pom.xml index 3abf6f8c..acddbd0c 100644 --- a/sop-common/sop-service-common/pom.xml +++ b/sop-common/sop-service-common/pom.xml @@ -6,11 +6,11 @@ com.gitee.sop sop-common - 2.5.10-SNAPSHOT + 2.5.11-SNAPSHOT ../pom.xml sop-service-common - 2.5.10-SNAPSHOT + 2.5.11-SNAPSHOT jar sop-service-common diff --git a/sop-example/sop-book/sop-book-web/pom.xml b/sop-example/sop-book/sop-book-web/pom.xml index 68c3dfe5..e4254809 100644 --- a/sop-example/sop-book/sop-book-web/pom.xml +++ b/sop-example/sop-book/sop-book-web/pom.xml @@ -28,7 +28,7 @@ com.gitee.sop sop-service-common - 2.5.10-SNAPSHOT + 2.5.11-SNAPSHOT com.gitee.sop diff --git a/sop-example/sop-easyopen/pom.xml b/sop-example/sop-easyopen/pom.xml index 02829e7f..88279bab 100644 --- a/sop-example/sop-easyopen/pom.xml +++ b/sop-example/sop-easyopen/pom.xml @@ -29,7 +29,7 @@ com.gitee.sop sop-service-common - 2.5.10-SNAPSHOT + 2.5.11-SNAPSHOT diff --git a/sop-example/sop-story/sop-story-web/pom.xml b/sop-example/sop-story/sop-story-web/pom.xml index 1df94a82..f877e33a 100644 --- a/sop-example/sop-story/sop-story-web/pom.xml +++ b/sop-example/sop-story/sop-story-web/pom.xml @@ -28,7 +28,7 @@ com.gitee.sop sop-service-common - 2.5.10-SNAPSHOT + 2.5.11-SNAPSHOT com.gitee.sop diff --git a/sop-gateway/pom.xml b/sop-gateway/pom.xml index 79abd906..b5df0fc6 100644 --- a/sop-gateway/pom.xml +++ b/sop-gateway/pom.xml @@ -29,7 +29,7 @@ com.gitee.sop sop-gateway-common - 2.5.10-SNAPSHOT + 2.5.11-SNAPSHOT diff --git a/sop-website/pom.xml b/sop-website/pom.xml index 1e4d8251..a949cadc 100644 --- a/sop-website/pom.xml +++ b/sop-website/pom.xml @@ -35,7 +35,7 @@ com.gitee.sop sop-gateway-common - 2.5.10-SNAPSHOT + 2.5.11-SNAPSHOT From 626fd3a8e400a4c53651fd2af823adc8d03d03e0 Mon Sep 17 00:00:00 2001 From: tanghc Date: Thu, 16 Jan 2020 10:21:40 +0800 Subject: [PATCH 27/55] 2.5.11 --- .../zuul/controller/ConfigChannelController.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/controller/ConfigChannelController.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/controller/ConfigChannelController.java index 2f1acd07..3ff5371a 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/controller/ConfigChannelController.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/controller/ConfigChannelController.java @@ -14,8 +14,8 @@ import com.gitee.sop.gatewaycommon.secret.IsvManager; import com.gitee.sop.gatewaycommon.util.RequestUtil; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpServletRequest; import java.io.IOException; @@ -26,7 +26,7 @@ import java.util.Map; * @author tanghc */ @Slf4j -@Controller +@RestController public class ConfigChannelController { private static Map> processorMap = new HashMap<>(16); @@ -43,7 +43,7 @@ public class ConfigChannelController { @Value("${zuul.secret}") private String secret; - @PostMapping("/sop/configChannelMsg") + @PostMapping("/configChannelMsg") public String configChannel(HttpServletRequest request) throws IOException { String requestJson = RequestUtil.getText(request); String sign = request.getHeader("sign"); From 58add8be8202e76ad25215183f5adb6dc0754d7d Mon Sep 17 00:00:00 2001 From: tanghc Date: Thu, 16 Jan 2020 10:38:59 +0800 Subject: [PATCH 28/55] 3.0.0 --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 1e97f358..7d9d4ccd 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,7 @@ SOP封装了开放平台大部分功能包括:签名验证、统一异常处 - 支持nacos - 网关动态修改参数 - 预发布/灰度环境切换 +- 支持eureka注册中心 ## 界面预览 From f6ec1a6654f58b10a878447fad8c29164f3a8e1f Mon Sep 17 00:00:00 2001 From: tanghc Date: Thu, 16 Jan 2020 11:05:09 +0800 Subject: [PATCH 29/55] 3.0.0 --- .../main/java/com/gitee/sop/test/Client.java | 44 +++++++++ .../java/com/gitee/sop/test/HttpTool.java | 89 ++++++++++++++++++- .../java/com/gitee/sop/test/AllInOneTest.java | 20 +++++ 3 files changed, 152 insertions(+), 1 deletion(-) diff --git a/sop-test/src/main/java/com/gitee/sop/test/Client.java b/sop-test/src/main/java/com/gitee/sop/test/Client.java index 3d641df8..ec25a65d 100644 --- a/sop-test/src/main/java/com/gitee/sop/test/Client.java +++ b/sop-test/src/main/java/com/gitee/sop/test/Client.java @@ -117,6 +117,40 @@ public class Client { return responseData; } + /** + * 发送请求 + * + * @param requestBuilder 请求信息 + * @return 返回结果 + */ + public InputStream download(RequestBuilder requestBuilder) { + RequestInfo requestInfo = requestBuilder.build(appId, privateKey); + HttpTool.HTTPMethod httpMethod = requestInfo.getHttpMethod(); + boolean postJson = requestInfo.isPostJson(); + Map form = requestInfo.getForm(); + Map header = requestInfo.getHeader(); + String requestUrl = requestInfo.getUrl() != null ? requestInfo.getUrl() : url; + List uploadFileList = requestBuilder.getUploadFileList(); + InputStream responseData = null; + // 发送请求 + try { + // 如果有上传文件 + if (uploadFileList != null && uploadFileList.size() > 0) { + responseData = httpTool.downloadByRequestFile(url, form, header, uploadFileList); + } else { + if (httpMethod == HttpTool.HTTPMethod.POST && postJson) { + responseData = httpTool.downloadJson(requestUrl, JSON.toJSONString(form), header); + } else { + responseData = httpTool.download(requestUrl, form, header, httpMethod); + } + } + + } catch (IOException e) { + throw new RuntimeException(e); + } + return responseData; + } + public interface Callback { /** * 请求成功后回调 @@ -127,6 +161,16 @@ public class Client { void callback(RequestInfo requestInfo, String responseData); } + public interface DownloadCallback { + /** + * 请求成功后回调 + * + * @param requestInfo 请求信息 + * @param responseData 返回结果 + */ + void callback(RequestInfo requestInfo, InputStream responseData); + } + public static class RequestBuilder { private static final String DEFAULT_VERSION = "1.0"; diff --git a/sop-test/src/main/java/com/gitee/sop/test/HttpTool.java b/sop-test/src/main/java/com/gitee/sop/test/HttpTool.java index 55145558..a8f78454 100644 --- a/sop-test/src/main/java/com/gitee/sop/test/HttpTool.java +++ b/sop-test/src/main/java/com/gitee/sop/test/HttpTool.java @@ -130,6 +130,28 @@ public class HttpTool { } } + /** + * 下载文件 + * + * @param url url + * @param form 参数 + * @param header header + * @param method 请求方式,post,get等 + * @return + * @throws IOException + */ + public InputStream download(String url, Map form, Map header, HTTPMethod method) throws IOException { + Request.Builder requestBuilder = buildRequestBuilder(url, form, method); + // 添加header + addHeader(requestBuilder, header); + + Request request = requestBuilder.build(); + Response response = httpClient + .newCall(request) + .execute(); + return response.body().byteStream(); + } + /** * 请求json数据,contentType=application/json * @param url 请求路径 @@ -157,6 +179,29 @@ public class HttpTool { } } + /** + * 请求json数据,contentType=application/json + * @param url 请求路径 + * @param json json数据 + * @param header header + * @return 返回响应结果 + * @throws IOException + */ + public InputStream downloadJson(String url, String json, Map header) throws IOException { + RequestBody body = RequestBody.create(MEDIA_TYPE_JSON, json); + Request.Builder requestBuilder = new Request.Builder() + .url(url) + .post(body); + // 添加header + addHeader(requestBuilder, header); + + Request request = requestBuilder.build(); + Response response = httpClient + .newCall(request) + .execute(); + return response.body().byteStream(); + } + public static Request.Builder buildRequestBuilder(String url, Map form, HTTPMethod method) { switch (method) { case GET: @@ -244,6 +289,48 @@ public class HttpTool { } } + /** + * 上传文件,然后下载文件 + * + * @param url + * @param form + * @param header + * @param files + * @return + * @throws IOException + */ + public InputStream downloadByRequestFile(String url, Map form, Map header, List files) + throws IOException { + // 创建MultipartBody.Builder,用于添加请求的数据 + MultipartBody.Builder bodyBuilder = new MultipartBody.Builder(); + bodyBuilder.setType(MultipartBody.FORM); + + for (UploadFile uploadFile : files) { + // 请求的名字 + bodyBuilder.addFormDataPart(uploadFile.getName(), + // 文件的文字,服务器端用来解析的 + uploadFile.getFileName(), + // 创建RequestBody,把上传的文件放入 + RequestBody.create(null, uploadFile.getFileData()) + ); + } + + for (Map.Entry entry : form.entrySet()) { + bodyBuilder.addFormDataPart(entry.getKey(), String.valueOf(entry.getValue())); + } + + RequestBody requestBody = bodyBuilder.build(); + + Request.Builder builder = new Request.Builder().url(url).post(requestBody); + + // 添加header + addHeader(builder, header); + + Request request = builder.build(); + Response response = httpClient.newCall(request).execute(); + return response.body().byteStream(); + } + /** * 请求数据 * @@ -318,7 +405,7 @@ public class HttpTool { /** http DELETE */ DELETE; - private HTTPMethod() { + HTTPMethod() { } public String value() { diff --git a/sop-test/src/test/java/com/gitee/sop/test/AllInOneTest.java b/sop-test/src/test/java/com/gitee/sop/test/AllInOneTest.java index a6034f43..70c3d98e 100644 --- a/sop-test/src/test/java/com/gitee/sop/test/AllInOneTest.java +++ b/sop-test/src/test/java/com/gitee/sop/test/AllInOneTest.java @@ -2,9 +2,12 @@ package com.gitee.sop.test; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; +import org.apache.commons.io.IOUtils; import org.junit.Assert; import java.io.File; +import java.io.IOException; +import java.io.InputStream; import java.util.HashMap; import java.util.Optional; import java.util.concurrent.CountDownLatch; @@ -247,6 +250,23 @@ public class AllInOneTest extends TestBase { client.execute(requestBuilder); } + /** + * 下载文件 + */ + public void testDownloadFile() throws IOException { + Client.RequestBuilder requestBuilder = new Client.RequestBuilder() + .method("story.download") + .version("1.0") + .bizContent(new BizContent().add("id",1).add("name","Jim")) + .httpMethod(HttpTool.HTTPMethod.GET); + + // 文件流 + InputStream download = client.download(requestBuilder); + String content = IOUtils.toString(download, "UTF-8"); + System.out.println("下载文件内容:" + content); + Assert.assertEquals(content, "spring.profiles.active=dev"); + } + /** * 验证中文乱码问题 */ From 3a6ea57226c5289e29b669e46cf501b8eb7c6a02 Mon Sep 17 00:00:00 2001 From: tanghc Date: Thu, 16 Jan 2020 11:52:40 +0800 Subject: [PATCH 30/55] 3.0.0 --- .../bridge/SopGatewayAutoConfiguration.java | 6 ++++++ .../sop/gatewaycommon/bean/ApiConfig.java | 2 +- .../configuration/BaseZuulConfiguration.java | 3 ++- .../ZuulErrorController.java | 20 +++++++++++-------- 4 files changed, 21 insertions(+), 10 deletions(-) rename sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/{configuration => controller}/ZuulErrorController.java (74%) diff --git a/sop-common/sop-bridge-zuul/src/main/java/com/gitee/sop/bridge/SopGatewayAutoConfiguration.java b/sop-common/sop-bridge-zuul/src/main/java/com/gitee/sop/bridge/SopGatewayAutoConfiguration.java index 0b933ecc..2fb375df 100644 --- a/sop-common/sop-bridge-zuul/src/main/java/com/gitee/sop/bridge/SopGatewayAutoConfiguration.java +++ b/sop-common/sop-bridge-zuul/src/main/java/com/gitee/sop/bridge/SopGatewayAutoConfiguration.java @@ -1,6 +1,8 @@ package com.gitee.sop.bridge; import com.gitee.sop.gatewaycommon.zuul.configuration.AlipayZuulConfiguration; +import org.springframework.boot.autoconfigure.AutoConfigureBefore; +import org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration; import org.springframework.cloud.netflix.zuul.EnableZuulProxy; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; @@ -12,6 +14,10 @@ import org.springframework.context.annotation.Import; @Configuration @EnableZuulProxy @Import(AlipayZuulConfiguration.class) +// 在ErrorMvcAutoConfiguration之前加载 +// 如果不加会出现basicErrorController和zuulErrorController冲突 +// zuulErrorController是SOP中的,提前加载后basicErrorController就不会加载 +@AutoConfigureBefore({ErrorMvcAutoConfiguration.class}) public class SopGatewayAutoConfiguration { } 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 4cdbb9c7..60d04446 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 @@ -35,7 +35,7 @@ import com.gitee.sop.gatewaycommon.validate.Encrypter; import com.gitee.sop.gatewaycommon.validate.Signer; import com.gitee.sop.gatewaycommon.validate.TokenValidator; import com.gitee.sop.gatewaycommon.validate.Validator; -import com.gitee.sop.gatewaycommon.zuul.configuration.ZuulErrorController; +import com.gitee.sop.gatewaycommon.zuul.controller.ZuulErrorController; import com.gitee.sop.gatewaycommon.zuul.param.ZuulParamBuilder; import com.gitee.sop.gatewaycommon.zuul.result.ZuulResultExecutor; import com.netflix.zuul.context.RequestContext; 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 54b0a5b7..258f5f70 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 @@ -8,6 +8,7 @@ import com.gitee.sop.gatewaycommon.param.ParamBuilder; import com.gitee.sop.gatewaycommon.zuul.ValidateService; import com.gitee.sop.gatewaycommon.zuul.controller.ConfigChannelController; import com.gitee.sop.gatewaycommon.zuul.controller.ErrorLogController; +import com.gitee.sop.gatewaycommon.zuul.controller.ZuulErrorController; import com.gitee.sop.gatewaycommon.zuul.controller.ZuulIndexController; import com.gitee.sop.gatewaycommon.zuul.filter.ErrorFilter; import com.gitee.sop.gatewaycommon.zuul.filter.FormBodyWrapperFilterExt; @@ -166,7 +167,7 @@ public class BaseZuulConfiguration extends AbstractConfiguration { * 统一错误处理 */ @Bean - ZuulErrorController sopZuulController() { + ZuulErrorController zuulErrorController() { return ApiContext.getApiConfig().getZuulErrorController(); } diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/configuration/ZuulErrorController.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/controller/ZuulErrorController.java similarity index 74% rename from sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/configuration/ZuulErrorController.java rename to sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/controller/ZuulErrorController.java index dff2a294..ce682db5 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/configuration/ZuulErrorController.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/controller/ZuulErrorController.java @@ -1,31 +1,31 @@ -package com.gitee.sop.gatewaycommon.zuul.configuration; +package com.gitee.sop.gatewaycommon.zuul.controller; import com.gitee.sop.gatewaycommon.bean.ApiContext; import com.gitee.sop.gatewaycommon.result.ResultExecutor; import com.gitee.sop.gatewaycommon.zuul.ZuulContext; import com.netflix.zuul.context.RequestContext; import lombok.extern.slf4j.Slf4j; -import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.boot.web.servlet.error.ErrorController; import org.springframework.web.bind.annotation.ExceptionHandler; -import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** - * 处理网关自身异常 + * zuul的异常处理 * * @author tanghc */ -@ControllerAdvice @Slf4j -public class ZuulErrorController { +@RestController +public class ZuulErrorController implements ErrorController { /** * 错误最终会到这里来 */ - @ExceptionHandler(Exception.class) - @ResponseBody + @RequestMapping("/error") public Object error(HttpServletRequest request, HttpServletResponse response) { RequestContext ctx = RequestContext.getCurrentContext(); if (ctx.getResponse() == null) { @@ -45,4 +45,8 @@ public class ZuulErrorController { return resultExecutor.buildErrorResult(RequestContext.getCurrentContext(), throwable); } + @Override + public String getErrorPath() { + return "/error"; + } } From 554520d4b877736a0a6029c88f90da55fe0a304b Mon Sep 17 00:00:00 2001 From: tanghc Date: Thu, 16 Jan 2020 15:10:04 +0800 Subject: [PATCH 31/55] 3.0.0 --- .../gitee/sop/gatewaycommon/zuul/ValidateService.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/ValidateService.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/ValidateService.java index 3ad55621..46632c89 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/ValidateService.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/ValidateService.java @@ -37,7 +37,10 @@ public class ValidateService { RequestContext currentContext = RequestContext.getCurrentContext(); currentContext.setRequest(RequestUtil.wrapRequest(request)); currentContext.setResponse(response); - doValidate(currentContext, callback); + // 解析参数 + ApiParam param = paramBuilder.build(currentContext); + ZuulContext.setApiParam(param); + doValidate(currentContext, param, callback); } /** @@ -45,10 +48,7 @@ public class ValidateService { * * @param currentContext currentContext */ - private void doValidate(RequestContext currentContext, ValidateCallback callback) { - // 解析参数 - ApiParam param = paramBuilder.build(currentContext); - ZuulContext.setApiParam(param); + private void doValidate(RequestContext currentContext, ApiParam param, ValidateCallback callback) { Exception error = null; // 验证操作,这里有负责验证签名参数 try { From 7b7ccf0e089fc3b4a2924687400f2cd3c4e4cd9d Mon Sep 17 00:00:00 2001 From: tanghc Date: Thu, 16 Jan 2020 15:52:18 +0800 Subject: [PATCH 32/55] 3.0.0 --- .../com/gitee/sop/test/AlipayClientPostTest.java | 1 + .../src/test/java/com/gitee/sop/test/TestBase.java | 14 ++++++++++++++ 2 files changed, 15 insertions(+) diff --git a/sop-test/src/test/java/com/gitee/sop/test/AlipayClientPostTest.java b/sop-test/src/test/java/com/gitee/sop/test/AlipayClientPostTest.java index 2dad56e1..67d80f96 100644 --- a/sop-test/src/test/java/com/gitee/sop/test/AlipayClientPostTest.java +++ b/sop-test/src/test/java/com/gitee/sop/test/AlipayClientPostTest.java @@ -56,6 +56,7 @@ public class AlipayClientPostTest extends TestBase { System.out.println("----------- 请求信息 -----------"); System.out.println("请求参数:" + buildParamQuery(params)); + System.out.println("URL参数:" + buildUrlQuery(params)); System.out.println("商户秘钥:" + privateKey); String content = AlipaySignature.getSignContent(params); System.out.println("待签名内容:" + content); diff --git a/sop-test/src/test/java/com/gitee/sop/test/TestBase.java b/sop-test/src/test/java/com/gitee/sop/test/TestBase.java index adbb3538..d6e37210 100644 --- a/sop-test/src/test/java/com/gitee/sop/test/TestBase.java +++ b/sop-test/src/test/java/com/gitee/sop/test/TestBase.java @@ -5,6 +5,8 @@ import junit.framework.TestCase; import java.io.IOException; import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; import java.util.Collections; import java.util.Map; @@ -73,4 +75,16 @@ public class TestBase extends TestCase { return sb.toString().substring(1); } + protected static String buildUrlQuery(Map params) { + StringBuilder sb = new StringBuilder(); + for (Map.Entry entry : params.entrySet()) { + try { + sb.append("&").append(entry.getKey()).append("=").append(URLEncoder.encode(entry.getValue(), "UTF-8")); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + } + return sb.toString().substring(1); + } + } From d76c5a5963442c1be90810deaf27931d6bd94796 Mon Sep 17 00:00:00 2001 From: tanghc Date: Thu, 16 Jan 2020 17:26:01 +0800 Subject: [PATCH 33/55] 3.0.0 --- .../com/gitee/sop/bridge/SopGatewayAutoConfiguration.java | 3 +++ .../src/main/resources/sop-bridge.properties | 2 -- .../gateway/configuration/BaseGatewayConfiguration.java | 4 +--- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/sop-common/sop-bridge-gateway/src/main/java/com/gitee/sop/bridge/SopGatewayAutoConfiguration.java b/sop-common/sop-bridge-gateway/src/main/java/com/gitee/sop/bridge/SopGatewayAutoConfiguration.java index e454f0a1..98184616 100644 --- a/sop-common/sop-bridge-gateway/src/main/java/com/gitee/sop/bridge/SopGatewayAutoConfiguration.java +++ b/sop-common/sop-bridge-gateway/src/main/java/com/gitee/sop/bridge/SopGatewayAutoConfiguration.java @@ -1,6 +1,8 @@ package com.gitee.sop.bridge; import com.gitee.sop.gatewaycommon.gateway.configuration.AlipayGatewayConfiguration; +import org.springframework.boot.autoconfigure.AutoConfigureBefore; +import org.springframework.cloud.netflix.ribbon.RibbonAutoConfiguration; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; @@ -10,5 +12,6 @@ import org.springframework.context.annotation.Import; */ @Configuration @Import(AlipayGatewayConfiguration.class) +@AutoConfigureBefore(RibbonAutoConfiguration.class) public class SopGatewayAutoConfiguration { } diff --git a/sop-common/sop-bridge-gateway/src/main/resources/sop-bridge.properties b/sop-common/sop-bridge-gateway/src/main/resources/sop-bridge.properties index 0627a28d..115692b7 100644 --- a/sop-common/sop-bridge-gateway/src/main/resources/sop-bridge.properties +++ b/sop-common/sop-bridge-gateway/src/main/resources/sop-bridge.properties @@ -6,8 +6,6 @@ sop.secret=MZZOUSTua6LzApIWXCwEgbBmxSzpzC # 网关入口 sop.gateway-index-path=/ -spring.main.allow-bean-definition-overriding=true - # nacos cloud配置 spring.cloud.nacos.discovery.server-addr=${nacos.url} 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 9c1d356f..815ff647 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 @@ -123,9 +123,8 @@ public class BaseGatewayConfiguration extends AbstractConfiguration { * @param clientFactory * @return */ - @Primary @Bean - LoadBalancerClient sopLoadBalancerClient(SpringClientFactory clientFactory) { + LoadBalancerClient loadBalancerClient(SpringClientFactory clientFactory) { return new SopLoadBalancerClient(clientFactory); } @@ -135,7 +134,6 @@ public class BaseGatewayConfiguration extends AbstractConfiguration { * @param loadBalancerProperties loadBalancerProperties * @return */ - @Primary @Bean LoadBalancerClientFilter loadBalancerClientFilter(LoadBalancerClient sopLoadBalancerClient, LoadBalancerProperties loadBalancerProperties) { return new SopLoadBalancerClientFilter(sopLoadBalancerClient, loadBalancerProperties); From 935bb2a45478780366d64576318888f93828def9 Mon Sep 17 00:00:00 2001 From: tanghc Date: Thu, 16 Jan 2020 18:20:58 +0800 Subject: [PATCH 34/55] 3.0.0 --- doc/docs/_sidebar.md | 69 +++++++------- doc/docs/files/10110_预发布灰度发布.md | 22 +++-- .../files/90014_原理分析之预发布灰度发布.md | 92 +++++++++++++++++++ ....x注意事项.md => 90099_2.x升3.x注意事项.md} | 0 .../BaseGatewayConfiguration.java | 4 +- .../LoadBalanceServerChooser.java | 7 +- 6 files changed, 148 insertions(+), 46 deletions(-) create mode 100644 doc/docs/files/90014_原理分析之预发布灰度发布.md rename doc/docs/files/{90014_2.x升3.x注意事项.md => 90099_2.x升3.x注意事项.md} (100%) diff --git a/doc/docs/_sidebar.md b/doc/docs/_sidebar.md index b0701362..b48ca6d2 100644 --- a/doc/docs/_sidebar.md +++ b/doc/docs/_sidebar.md @@ -1,36 +1,37 @@ -* [首页](/?t=1578910309712) +* [首页](/?t=1579169719974) * 开发文档 - * [快速体验](files/10010_快速体验.md?t=1578910309714) - * [项目接入到SOP](files/10011_项目接入到SOP.md?t=1578910309731) - * [新增接口](files/10020_新增接口.md?t=1578910309732) - * [开发流程](files/10021_开发流程.md?t=1578910309732) - * [业务参数校验](files/10030_业务参数校验.md?t=1578910309732) - * [错误处理](files/10040_错误处理.md?t=1578910309732) - * [编写文档](files/10041_编写文档.md?t=1578910309732) - * [接口交互详解](files/10050_接口交互详解.md?t=1578910309732) - * [easyopen支持](files/10070_easyopen支持.md?t=1578910309732) - * [使用签名校验工具](files/10080_使用签名校验工具.md?t=1578910309732) - * [ISV管理](files/10085_ISV管理.md?t=1578910309732) - * [自定义返回结果](files/10087_自定义返回结果.md?t=1578910309733) - * [自定义过滤器](files/10088_自定义过滤器.md?t=1578910309733) - * [自定义校验token](files/10089_自定义校验token.md?t=1578910309733) - * [路由授权](files/10090_路由授权.md?t=1578910309733) - * [接口限流](files/10092_接口限流.md?t=1578910309733) - * [监控日志](files/10093_监控日志.md?t=1578910309733) - * [SDK开发](files/10095_SDK开发.md?t=1578910309733) - * [使用SpringCloudGateway](files/10096_使用SpringCloudGateway.md?t=1578910309733) - * [应用授权](files/10097_应用授权.md?t=1578910309733) - * [提供restful接口](files/10100_提供restful接口.md?t=1578910309733) - * [文件上传](files/10104_文件上传.md?t=1578910309734) - * [配置Sleuth链路追踪](files/10109_配置Sleuth链路追踪.md?t=1578910309734) - * [预发布灰度发布](files/10110_预发布灰度发布.md?t=1578910309734) - * [动态修改请求参数](files/10111_动态修改请求参数.md?t=1578910309734) - * [使用eureka](files/10112_使用eureka.md?t=1578910309734) - * [扩展其它注册中心](files/10113_扩展其它注册中心.md?t=1578910309734) + * [快速体验](files/10010_快速体验.md?t=1579169719976) + * [项目接入到SOP](files/10011_项目接入到SOP.md?t=1579169719993) + * [新增接口](files/10020_新增接口.md?t=1579169719993) + * [开发流程](files/10021_开发流程.md?t=1579169719993) + * [业务参数校验](files/10030_业务参数校验.md?t=1579169719993) + * [错误处理](files/10040_错误处理.md?t=1579169719993) + * [编写文档](files/10041_编写文档.md?t=1579169719993) + * [接口交互详解](files/10050_接口交互详解.md?t=1579169719993) + * [easyopen支持](files/10070_easyopen支持.md?t=1579169719993) + * [使用签名校验工具](files/10080_使用签名校验工具.md?t=1579169719993) + * [ISV管理](files/10085_ISV管理.md?t=1579169719994) + * [自定义返回结果](files/10087_自定义返回结果.md?t=1579169719994) + * [自定义过滤器](files/10088_自定义过滤器.md?t=1579169719994) + * [自定义校验token](files/10089_自定义校验token.md?t=1579169719994) + * [路由授权](files/10090_路由授权.md?t=1579169719994) + * [接口限流](files/10092_接口限流.md?t=1579169719994) + * [监控日志](files/10093_监控日志.md?t=1579169719994) + * [SDK开发](files/10095_SDK开发.md?t=1579169719994) + * [使用SpringCloudGateway](files/10096_使用SpringCloudGateway.md?t=1579169719994) + * [应用授权](files/10097_应用授权.md?t=1579169719994) + * [提供restful接口](files/10100_提供restful接口.md?t=1579169719995) + * [文件上传](files/10104_文件上传.md?t=1579169719995) + * [配置Sleuth链路追踪](files/10109_配置Sleuth链路追踪.md?t=1579169719995) + * [预发布灰度发布](files/10110_预发布灰度发布.md?t=1579169719995) + * [动态修改请求参数](files/10111_动态修改请求参数.md?t=1579169719995) + * [使用eureka](files/10112_使用eureka.md?t=1579169719995) + * [扩展其它注册中心](files/10113_扩展其它注册中心.md?t=1579169719995) * 原理分析 - * [原理分析之@ApiMapping](files/90010_原理分析之@ApiMapping.md?t=1578910309734) - * [原理分析之如何存储路由](files/90011_原理分析之如何存储路由.md?t=1578910309734) - * [原理分析之如何路由](files/90012_原理分析之如何路由.md?t=1578910309734) - * [原理分析之文档归纳](files/90013_原理分析之文档归纳.md?t=1578910309734) - * [2.x升3.x注意事项](files/90014_2.x升3.x注意事项.md?t=1578910309734) - * [常见问题](files/90100_常见问题.md?t=1578910309734) + * [原理分析之@ApiMapping](files/90010_原理分析之@ApiMapping.md?t=1579169719995) + * [原理分析之如何存储路由](files/90011_原理分析之如何存储路由.md?t=1579169719995) + * [原理分析之如何路由](files/90012_原理分析之如何路由.md?t=1579169719995) + * [原理分析之文档归纳](files/90013_原理分析之文档归纳.md?t=1579169719996) + * [原理分析之预发布灰度发布](files/90014_原理分析之预发布灰度发布.md?t=1579169719996) + * [2.x升3.x注意事项](files/90099_2.x升3.x注意事项.md?t=1579169719996) + * [常见问题](files/90100_常见问题.md?t=1579169719996) diff --git a/doc/docs/files/10110_预发布灰度发布.md b/doc/docs/files/10110_预发布灰度发布.md index a468e932..6b469196 100644 --- a/doc/docs/files/10110_预发布灰度发布.md +++ b/doc/docs/files/10110_预发布灰度发布.md @@ -4,14 +4,20 @@ ## 使用预发布 -假设网关工程在阿里云负载均衡有两台服务器,域名分别为: +SOP中预发布的思路如下: + +假设网关工程sop-gateway在阿里云负载均衡有两台服务器,域名分别为: |域名|说明| |:---- |:---- | |open1.domain.com |网关服务器1 | |openpre.domain.com | 网关服务器2,作为预发布请求入口| -线上网关入口为`http://open.domain.com/`,请求网关`http://open.domain.com/`会负载均衡到这两台服务器 +SLB对外域名为:`open.domain.com`,即开放平台入口为:`http://open.domain.com` + +访问`open.domain.com`会负载均衡到`open1.domain.com`和`openpre.domain.com`这两台实例 + +如果单独从`openpre.domain.com`访问,则会访问到预发布微服务。 SOP开启预发布步骤如下: @@ -21,13 +27,16 @@ SOP开启预发布步骤如下: # 预发布网关域名,多个用英文逗号(,)隔开 pre.domain=openpre.domain.com ``` + 重启网关 + 微服务启动参数添加:`--spring.cloud.nacos.discovery.metadata.env=pre`(eureka下是:`--eureka.instance.metadata-map.env=pre`)。 -建议线上配两套启动脚本,其中预发布启动脚本添加启动参数`--eureka.instance.metadata-map.env=pre` +建议线上配两套启动脚本,其中预发布启动脚本添加启动参数`--spring.cloud.nacos.discovery.metadata.env=pre` + +登录SOP-Admin,在服务列表中点击预发布。 -登录SOP-Admin,在服务列表中点击预发布,然后预发布请求地址变成:`http://openpre.domain.com/`。 -从`openpre.domain.com`请求进来的用户都会进预发布服务器,其它情况都走非预发布服务器。 +从`openpre.domain.com`请求进来的用户都会进预发布服务器,从SLB域名进来请求路由到非预发服务器 ## 使用灰度发布 @@ -41,8 +50,7 @@ pre.domain=openpre.domain.com 参考类: -- SopLoadBalancerClient.java gateway网关下预发布/灰度服务选取 -- EnvironmentServerChooser.java zuul网关下预发布/灰度服务选取 +- LoadBalanceServerChooser.java 预发布/灰度发布服务实例选择 ### 自定义判断灰度用户 diff --git a/doc/docs/files/90014_原理分析之预发布灰度发布.md b/doc/docs/files/90014_原理分析之预发布灰度发布.md new file mode 100644 index 00000000..04bc5350 --- /dev/null +++ b/doc/docs/files/90014_原理分析之预发布灰度发布.md @@ -0,0 +1,92 @@ +# 原理分析之预发布灰度发布 + +SOP网关采用`自定义负载均衡策略`来实现对预发布/灰度发布服务器实例的选择。 + +spring cloud gateway默认的负载均衡实现类在:`org.springframework.cloud.gateway.filter.LoadBalancerClientFilter.java`中 + +这个类主要做了几件事情: + +1. 解析出请求路径中的scheme +2. 如果scheme不是以`lb`协议开头直接跳过 +3. 如果scheme以`lb`协议开头,则说明需要进行负载均衡,选出一台微服务实例 +4. 将`lb`协议解析成`http://ip:port`,继续向下请求 + +其中第4步是由`org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient`来完成的, +我们只要分别继承`LoadBalancerClientFilter`和`RibbonLoadBalancerClient`,然后重写其中的方法就能完成自定义负载均衡。 + +SOP中的重写类是:`SopLoadBalancerClientFilter`和`SopLoadBalancerClient`,核心代码委托给了`LoadBalanceServerChooser`处理,核心代码如下: + +```java + /** + * 选择服务器 + * + * @param serviceId serviceId,仅gateway网关有作用 + * @param exchange 请求上下文 + * @param loadBalancer loadBalancer + * @param superChooser 父类默认的选择 + * @param serverChooserFunction 执行选择操作 + * @return 返回服务器实例,没有选到则返回null + */ + public R choose( + String serviceId + , T exchange + , ILoadBalancer loadBalancer + , Supplier superChooser + , Function, R> serverChooserFunction) { + // 获取所有服务实例 + List servers = loadBalancer.getReachableServers(); + + // 存放预发服务器 + List preServers = new ArrayList<>(4); + // 存放灰度发布服务器 + List grayServers = new ArrayList<>(4); + // 存放非预发服务器 + List notPreServers = new ArrayList<>(4); + + for (Server server : servers) { + // 获取实例metadata + Map metadata = getMetadata(serviceId, server); + // 是否开启了预发模式 + if (this.isPreServer(metadata)) { + preServers.add(server); + } else if (this.isGrayServer(metadata)) { + grayServers.add(server); + } else { + notPreServers.add(server); + } + } + notPreServers.addAll(grayServers); + // 如果没有开启预发布服务和灰度发布,直接用默认的方式 + if (preServers.isEmpty() && grayServers.isEmpty()) { + return superChooser.get(); + } + // 如果是从预发布域名访问过来,则认为是预发布请求,选出预发服务器 + if (this.isRequestFromPreDomain(exchange)) { + return serverChooserFunction.apply(preServers); + } + // 如果是灰度请求,则认为是灰度用户,选出灰度服务器 + if (this.isRequestGrayServer(exchange)) { + return serverChooserFunction.apply(grayServers); + } + + // 到这里说明不能访问预发/灰度服务器,则需要路由到非预发服务器 + // 注意:这里允许走灰度服务器,如果不允许走,注释notPreServers.addAll(grayServers);这行 + return serverChooserFunction.apply(notPreServers); + } +``` + +其业务逻辑如下: + +1. 选出`serviceId`对应的所有服务器实例 +2. 将服务器实例进行分类,分别放进`预发布List`,`灰度List`,`非预发布List`中 +3. 如果`预发布List`,`灰度List`都为空,表示没有开启任何预发/灰度服务,直接使用父类的负载均衡策略 +4. 如果是从预发布域名访问过来,则认为是预发布请求,选出预发服务器 +5. 如果是灰度请求,则认为是灰度用户,选出灰度服务器 +6. 最后剩下的是正常用户,正常用户不能走预发环境 + +## 参考类 + +- com.gitee.sop.gatewaycommon.gateway.filter.SopLoadBalancerClientFilter +- com.gitee.sop.gatewaycommon.gateway.loadbalancer.SopLoadBalancerClient +- com.gitee.sop.gatewaycommon.gateway.loadbalancer.GatewayLoadBalanceServerChooser + diff --git a/doc/docs/files/90014_2.x升3.x注意事项.md b/doc/docs/files/90099_2.x升3.x注意事项.md similarity index 100% rename from doc/docs/files/90014_2.x升3.x注意事项.md rename to doc/docs/files/90099_2.x升3.x注意事项.md 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 815ff647..f65151a4 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 @@ -119,7 +119,7 @@ public class BaseGatewayConfiguration extends AbstractConfiguration { } /** - * 扩展默认的负载均衡选择,默认使用的是RibbonLoadBalancerClient。当配置了pre.domain时才生效 + * 扩展默认的负载均衡选择,默认使用的是RibbonLoadBalancerClient * @param clientFactory * @return */ @@ -129,7 +129,7 @@ public class BaseGatewayConfiguration extends AbstractConfiguration { } /** - * 扩展默认的负载均衡过滤器,默认是LoadBalancerClientFilter。当配置了pre.domain时才生效 + * 扩展默认的负载均衡过滤器,默认是LoadBalancerClientFilter * @param sopLoadBalancerClient SopLoadBalancerClient * @param loadBalancerProperties loadBalancerProperties * @return diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/loadbalancer/LoadBalanceServerChooser.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/loadbalancer/LoadBalanceServerChooser.java index 0cea6478..11dba443 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/loadbalancer/LoadBalanceServerChooser.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/loadbalancer/LoadBalanceServerChooser.java @@ -32,7 +32,7 @@ public abstract class LoadBalanceServerChooser implements ServerChooserCon * @param loadBalancer loadBalancer * @param superChooser 父类默认的选择 * @param serverChooserFunction 执行选择操作 - * @return 返回服务器实例 + * @return 返回服务器实例,没有选到则返回null */ public R choose( String serviceId @@ -67,16 +67,17 @@ public abstract class LoadBalanceServerChooser implements ServerChooserCon if (preServers.isEmpty() && grayServers.isEmpty()) { return superChooser.get(); } - // 如果是从预发布域名访问过来,则认为是预发布请求 + // 如果是从预发布域名访问过来,则认为是预发布请求,选出预发服务器 if (this.isRequestFromPreDomain(exchange)) { return serverChooserFunction.apply(preServers); } - // 如果是灰度请求 + // 如果是灰度请求,则认为是灰度用户,选出灰度服务器 if (this.isRequestGrayServer(exchange)) { return serverChooserFunction.apply(grayServers); } // 到这里说明不能访问预发/灰度服务器,则需要路由到非预发服务器 + // 注意:这里允许走灰度服务器,如果不允许走,注释notPreServers.addAll(grayServers);这行 return serverChooserFunction.apply(notPreServers); } From 820909036b92f154671a2a4b72a17302da392ee2 Mon Sep 17 00:00:00 2001 From: tanghc Date: Fri, 17 Jan 2020 11:24:57 +0800 Subject: [PATCH 35/55] 3.0.0 --- doc/docs/files/10010_快速体验.md | 16 +++++++ sop-common/pom.xml | 6 +++ .../bridge/SopGatewayAutoConfiguration.java | 3 +- .../bridge/SopGatewayAutoConfiguration.java | 3 +- .../sop/gatewaycommon/bean/ApiConfig.java | 12 ++--- .../config/ApiConfigProperties.java | 48 +++++++++++++++++++ .../config/BaseGatewayAutoConfiguration.java | 29 +++++++++++ .../easyopen/EasyopenResultExecutor.java | 4 +- .../gateway/result/GatewayResultExecutor.java | 4 +- .../result/ResultExecutorForGateway.java | 9 ++++ .../result/ResultExecutorForZuul.java | 9 ++++ .../zuul/result/ZuulResultExecutor.java | 3 +- 12 files changed, 133 insertions(+), 13 deletions(-) create mode 100644 sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/config/ApiConfigProperties.java create mode 100644 sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/config/BaseGatewayAutoConfiguration.java create mode 100644 sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/result/ResultExecutorForGateway.java create mode 100644 sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/result/ResultExecutorForZuul.java diff --git a/doc/docs/files/10010_快速体验.md b/doc/docs/files/10010_快速体验.md index 1f7acca0..8029b969 100644 --- a/doc/docs/files/10010_快速体验.md +++ b/doc/docs/files/10010_快速体验.md @@ -31,3 +31,19 @@ - 运行WebsiteServerApplication.java - 访问http://localhost:8083 +## 基本配置 + +在`sop-gateway`下的application-dev.properties配置,各项配置说明如下 + +```properties +# 忽略验证,设置true,则所有接口不会进行签名校验,默认false +sop.api-config.ignore-validate=false +# 是否对结果进行合并,默认true +sop.api-config.merge-result=true +# 显示返回sign,默认true +sop.api-config.show-return-sign=true +# 是否开启限流功能,默认true +sop.api-config.open-limit=true +# 请求超时时间,默认5分钟,即允许在5分钟内重复请求,默认300 +sop.api-config.timeout-seconds=300 +``` \ No newline at end of file diff --git a/sop-common/pom.xml b/sop-common/pom.xml index 7878108f..48b4bed4 100644 --- a/sop-common/pom.xml +++ b/sop-common/pom.xml @@ -119,6 +119,12 @@ true + + org.springframework.boot + spring-boot-configuration-processor + true + + org.projectlombok diff --git a/sop-common/sop-bridge-gateway/src/main/java/com/gitee/sop/bridge/SopGatewayAutoConfiguration.java b/sop-common/sop-bridge-gateway/src/main/java/com/gitee/sop/bridge/SopGatewayAutoConfiguration.java index 98184616..34c61cd8 100644 --- a/sop-common/sop-bridge-gateway/src/main/java/com/gitee/sop/bridge/SopGatewayAutoConfiguration.java +++ b/sop-common/sop-bridge-gateway/src/main/java/com/gitee/sop/bridge/SopGatewayAutoConfiguration.java @@ -1,5 +1,6 @@ package com.gitee.sop.bridge; +import com.gitee.sop.gatewaycommon.config.BaseGatewayAutoConfiguration; import com.gitee.sop.gatewaycommon.gateway.configuration.AlipayGatewayConfiguration; import org.springframework.boot.autoconfigure.AutoConfigureBefore; import org.springframework.cloud.netflix.ribbon.RibbonAutoConfiguration; @@ -13,5 +14,5 @@ import org.springframework.context.annotation.Import; @Configuration @Import(AlipayGatewayConfiguration.class) @AutoConfigureBefore(RibbonAutoConfiguration.class) -public class SopGatewayAutoConfiguration { +public class SopGatewayAutoConfiguration extends BaseGatewayAutoConfiguration { } diff --git a/sop-common/sop-bridge-zuul/src/main/java/com/gitee/sop/bridge/SopGatewayAutoConfiguration.java b/sop-common/sop-bridge-zuul/src/main/java/com/gitee/sop/bridge/SopGatewayAutoConfiguration.java index 2fb375df..2e17861c 100644 --- a/sop-common/sop-bridge-zuul/src/main/java/com/gitee/sop/bridge/SopGatewayAutoConfiguration.java +++ b/sop-common/sop-bridge-zuul/src/main/java/com/gitee/sop/bridge/SopGatewayAutoConfiguration.java @@ -1,5 +1,6 @@ package com.gitee.sop.bridge; +import com.gitee.sop.gatewaycommon.config.BaseGatewayAutoConfiguration; import com.gitee.sop.gatewaycommon.zuul.configuration.AlipayZuulConfiguration; import org.springframework.boot.autoconfigure.AutoConfigureBefore; import org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration; @@ -18,6 +19,6 @@ import org.springframework.context.annotation.Import; // 如果不加会出现basicErrorController和zuulErrorController冲突 // zuulErrorController是SOP中的,提前加载后basicErrorController就不会加载 @AutoConfigureBefore({ErrorMvcAutoConfiguration.class}) -public class SopGatewayAutoConfiguration { +public class SopGatewayAutoConfiguration extends BaseGatewayAutoConfiguration { } 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 60d04446..acda4d79 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 @@ -18,12 +18,12 @@ import com.gitee.sop.gatewaycommon.manager.IsvRoutePermissionManager; import com.gitee.sop.gatewaycommon.manager.LimitConfigManager; import com.gitee.sop.gatewaycommon.manager.RouteConfigManager; import com.gitee.sop.gatewaycommon.manager.ServiceErrorManager; -import com.gitee.sop.gatewaycommon.param.ParamBuilder; import com.gitee.sop.gatewaycommon.param.ParameterFormatter; import com.gitee.sop.gatewaycommon.result.DataNameBuilder; import com.gitee.sop.gatewaycommon.result.DefaultDataNameBuilder; import com.gitee.sop.gatewaycommon.result.ResultAppender; -import com.gitee.sop.gatewaycommon.result.ResultExecutor; +import com.gitee.sop.gatewaycommon.result.ResultExecutorForGateway; +import com.gitee.sop.gatewaycommon.result.ResultExecutorForZuul; import com.gitee.sop.gatewaycommon.secret.CacheIsvManager; import com.gitee.sop.gatewaycommon.secret.IsvManager; import com.gitee.sop.gatewaycommon.session.ApiSessionManager; @@ -38,10 +38,8 @@ import com.gitee.sop.gatewaycommon.validate.Validator; import com.gitee.sop.gatewaycommon.zuul.controller.ZuulErrorController; import com.gitee.sop.gatewaycommon.zuul.param.ZuulParamBuilder; import com.gitee.sop.gatewaycommon.zuul.result.ZuulResultExecutor; -import com.netflix.zuul.context.RequestContext; import lombok.Data; import org.apache.commons.lang3.StringUtils; -import org.springframework.web.server.ServerWebExchange; import java.util.ArrayList; import java.util.Comparator; @@ -65,12 +63,12 @@ public class ApiConfig { /** * gateway合并结果处理 */ - private ResultExecutor gatewayResultExecutor = new GatewayResultExecutor(); + private ResultExecutorForGateway gatewayResultExecutor = new GatewayResultExecutor(); /** * zuul合并结果处理 */ - private ResultExecutor zuulResultExecutor = new ZuulResultExecutor(); + private ResultExecutorForZuul zuulResultExecutor = new ZuulResultExecutor(); /** * isv管理 @@ -90,7 +88,7 @@ public class ApiConfig { /** * 参数解析,zuul */ - private ParamBuilder zuulParamBuilder = new ZuulParamBuilder(); + private ZuulParamBuilder zuulParamBuilder = new ZuulParamBuilder(); /** * 验证 diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/config/ApiConfigProperties.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/config/ApiConfigProperties.java new file mode 100644 index 00000000..c9d5526d --- /dev/null +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/config/ApiConfigProperties.java @@ -0,0 +1,48 @@ +package com.gitee.sop.gatewaycommon.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author tanghc + */ +@Data +@ConfigurationProperties(prefix = "sop.api-config") +public class ApiConfigProperties { + + private List i18nModules = new ArrayList<>(); + + /** + * 忽略验证,设置true,则所有接口不会进行签名校验 + */ + private boolean ignoreValidate; + + /** + * 是否对结果进行合并。
    + * 默认情况下是否合并结果由微服务端决定,一旦指定该值,则由该值决定,不管微服务端如何设置。 + */ + private Boolean mergeResult; + + /** + * 请求超时时间,默认5分钟,即允许在5分钟内重复请求 + */ + private int timeoutSeconds = 300; + + /** + * 是否开启限流功能 + */ + private boolean openLimit = true; + + /** + * 显示返回sign + */ + private boolean showReturnSign = true; + + /** + * 保存错误信息容器的容量 + */ + private int storeErrorCapacity = 20; +} diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/config/BaseGatewayAutoConfiguration.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/config/BaseGatewayAutoConfiguration.java new file mode 100644 index 00000000..e11c49eb --- /dev/null +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/config/BaseGatewayAutoConfiguration.java @@ -0,0 +1,29 @@ +package com.gitee.sop.gatewaycommon.config; + +import com.alibaba.fastjson.JSON; +import com.gitee.sop.gatewaycommon.bean.ApiConfig; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.context.properties.EnableConfigurationProperties; + +import javax.annotation.PostConstruct; + +/** + * @author tanghc + */ +@Slf4j +@EnableConfigurationProperties(ApiConfigProperties.class) +public class BaseGatewayAutoConfiguration { + + @Autowired + private ApiConfigProperties apiConfigProperties; + + @PostConstruct + public void after() { + log.info("网关基本配置:{}", JSON.toJSONString(apiConfigProperties)); + ApiConfig apiConfig = ApiConfig.getInstance(); + BeanUtils.copyProperties(apiConfigProperties, apiConfig); + } + +} diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/easyopen/EasyopenResultExecutor.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/easyopen/EasyopenResultExecutor.java index d0ab701c..ba322249 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/easyopen/EasyopenResultExecutor.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/easyopen/EasyopenResultExecutor.java @@ -4,7 +4,7 @@ import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.gitee.sop.gatewaycommon.message.Error; import com.gitee.sop.gatewaycommon.result.ApiResult; -import com.gitee.sop.gatewaycommon.result.ResultExecutor; +import com.gitee.sop.gatewaycommon.result.ResultExecutorForZuul; import com.gitee.sop.gatewaycommon.zuul.result.ZuulResultExecutor; import com.netflix.zuul.context.RequestContext; @@ -13,7 +13,7 @@ import java.util.Optional; /** * @author tanghc */ -public class EasyopenResultExecutor implements ResultExecutor { +public class EasyopenResultExecutor implements ResultExecutorForZuul { boolean onlyReturnData; diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/result/GatewayResultExecutor.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/result/GatewayResultExecutor.java index 9554647a..3c69cdda 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/result/GatewayResultExecutor.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/result/GatewayResultExecutor.java @@ -9,6 +9,7 @@ import com.gitee.sop.gatewaycommon.message.Error; import com.gitee.sop.gatewaycommon.message.ErrorEnum; import com.gitee.sop.gatewaycommon.param.ApiParam; import com.gitee.sop.gatewaycommon.result.BaseExecutorAdapter; +import com.gitee.sop.gatewaycommon.result.ResultExecutorForGateway; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; import org.springframework.util.CollectionUtils; @@ -22,7 +23,8 @@ import java.util.Map; * @author tanghc */ @Slf4j -public class GatewayResultExecutor extends BaseExecutorAdapter { +public class GatewayResultExecutor extends BaseExecutorAdapter + implements ResultExecutorForGateway { @Override public int getResponseStatus(ServerWebExchange exchange) { diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/result/ResultExecutorForGateway.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/result/ResultExecutorForGateway.java new file mode 100644 index 00000000..050309b1 --- /dev/null +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/result/ResultExecutorForGateway.java @@ -0,0 +1,9 @@ +package com.gitee.sop.gatewaycommon.result; + +import org.springframework.web.server.ServerWebExchange; + +/** + * @author tanghc + */ +public interface ResultExecutorForGateway extends ResultExecutor { +} diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/result/ResultExecutorForZuul.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/result/ResultExecutorForZuul.java new file mode 100644 index 00000000..12cbc89b --- /dev/null +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/result/ResultExecutorForZuul.java @@ -0,0 +1,9 @@ +package com.gitee.sop.gatewaycommon.result; + +import com.netflix.zuul.context.RequestContext; + +/** + * @author tanghc + */ +public interface ResultExecutorForZuul extends ResultExecutor { +} diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/result/ZuulResultExecutor.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/result/ZuulResultExecutor.java index fb428811..ad4de22d 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/result/ZuulResultExecutor.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/result/ZuulResultExecutor.java @@ -8,6 +8,7 @@ import com.gitee.sop.gatewaycommon.message.Error; import com.gitee.sop.gatewaycommon.message.ErrorEnum; import com.gitee.sop.gatewaycommon.param.ApiParam; import com.gitee.sop.gatewaycommon.result.BaseExecutorAdapter; +import com.gitee.sop.gatewaycommon.result.ResultExecutorForZuul; import com.gitee.sop.gatewaycommon.zuul.ZuulContext; import com.netflix.util.Pair; import com.netflix.zuul.context.RequestContext; @@ -20,7 +21,7 @@ import java.util.List; * @author tanghc */ @Slf4j -public class ZuulResultExecutor extends BaseExecutorAdapter { +public class ZuulResultExecutor extends BaseExecutorAdapter implements ResultExecutorForZuul { @Override protected boolean isMergeResult(RequestContext request) { From 40b4709b38aece1924298d12211676483efbc266 Mon Sep 17 00:00:00 2001 From: tanghc Date: Fri, 17 Jan 2020 14:00:37 +0800 Subject: [PATCH 36/55] 3.0.0 --- changelog.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelog.md b/changelog.md index 828928df..de11209d 100644 --- a/changelog.md +++ b/changelog.md @@ -4,7 +4,7 @@ - 重构spring cloud gateway网关 - 重构`预发布/灰度发布环境选择` -- zuul和gateway网关二合一 +- zuul和gateway网关二合一,可随意切换 - 精简配置文件 - 优化文档中心页面 From 89916949719ec25a341049ccba25d817a84f305b Mon Sep 17 00:00:00 2001 From: tanghc Date: Fri, 17 Jan 2020 14:51:38 +0800 Subject: [PATCH 37/55] 3.0.0 --- .../SopAdminEnvironmentPostProcessor.java | 40 +++++++++++++++++++ .../main/resources/META-INF/spring.factories | 2 + .../main/resources/application-dev.properties | 30 -------------- .../src/main/resources/sop-admin.properties | 32 +++++++++++++++ .../SopGatewayEnvironmentPostProcessor.java} | 4 +- .../main/resources/META-INF/spring.factories | 2 +- 6 files changed, 77 insertions(+), 33 deletions(-) create mode 100644 sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/config/SopAdminEnvironmentPostProcessor.java create mode 100644 sop-admin/sop-admin-server/src/main/resources/META-INF/spring.factories create mode 100644 sop-admin/sop-admin-server/src/main/resources/sop-admin.properties rename sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/{env/SopEnvironmentPostProcessor.java => config/SopGatewayEnvironmentPostProcessor.java} (91%) diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/config/SopAdminEnvironmentPostProcessor.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/config/SopAdminEnvironmentPostProcessor.java new file mode 100644 index 00000000..cd87aaf0 --- /dev/null +++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/config/SopAdminEnvironmentPostProcessor.java @@ -0,0 +1,40 @@ +package com.gitee.sop.adminserver.config; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.env.EnvironmentPostProcessor; +import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.core.env.PropertiesPropertySource; +import org.springframework.core.env.PropertySource; +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; + +import java.io.IOException; +import java.util.Properties; + +/** + * 自定义环境处理,在运行SpringApplication之前加载任意配置文件到Environment环境中 + * https://www.jianshu.com/p/be6c818fe6ff + */ +public class SopAdminEnvironmentPostProcessor implements EnvironmentPostProcessor { + + private final Properties properties = new Properties(); + + @Override + public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) { + Resource resource = new ClassPathResource("sop-admin.properties"); + // 加载成PropertySource对象,并添加到Environment环境中 + environment.getPropertySources().addLast(loadProfiles(resource)); + } + + private PropertySource loadProfiles(Resource resource) { + if (resource == null || !resource.exists()) { + throw new IllegalArgumentException("资源" + resource + "不存在"); + } + try { + properties.load(resource.getInputStream()); + return new PropertiesPropertySource(resource.getFilename(), properties); + } catch (IOException ex) { + throw new IllegalStateException("加载配置文件失败" + resource, ex); + } + } +} diff --git a/sop-admin/sop-admin-server/src/main/resources/META-INF/spring.factories b/sop-admin/sop-admin-server/src/main/resources/META-INF/spring.factories new file mode 100644 index 00000000..201aa743 --- /dev/null +++ b/sop-admin/sop-admin-server/src/main/resources/META-INF/spring.factories @@ -0,0 +1,2 @@ +# 自定义自动配置类,如果有多个类,使用逗号(,)分隔,\正斜杠标示换行还可以读取到指定的类 +org.springframework.boot.env.EnvironmentPostProcessor=com.gitee.sop.adminserver.config.SopAdminEnvironmentPostProcessor diff --git a/sop-admin/sop-admin-server/src/main/resources/application-dev.properties b/sop-admin/sop-admin-server/src/main/resources/application-dev.properties index 2588e1a7..917d0f92 100644 --- a/sop-admin/sop-admin-server/src/main/resources/application-dev.properties +++ b/sop-admin/sop-admin-server/src/main/resources/application-dev.properties @@ -1,7 +1,5 @@ server.port=8082 -spring.application.name=sop-admin -# ------- 需要改的配置 ------- # mysql数据库账号 mysql.host=localhost:3306 mysql.username=root @@ -9,33 +7,5 @@ mysql.password=root # nacos注册中心地址 nacos.url=127.0.0.1:8848 -# ------- 需要改的配置end ------- - -# session过期时间,分钟 -admin.access-token.timeout-minutes=30 -# 签名方式,rsa:支付宝开放平台签名方式,md5:淘宝开放平台签名方式 -sop.sign-type=rsa - -# nacos配置 -nacos.config.server-addr=${nacos.url} -nacos.discovery.server-addr=${nacos.url} - -# 数据库配置 -spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver -spring.datasource.url=jdbc:mysql://${mysql.host}/sop?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&serverTimezone=Asia/Shanghai -spring.datasource.username=${mysql.username} -spring.datasource.password=${mysql.password} - -# 固定不用改 -mybatis.mapper-locations=classpath:mybatis/mapper/*.xml -easyopen.show-doc=false -easyopen.ignore-validate=true logging.level.com.gitee=debug - -# 不用改 -mybatis.fill.com.gitee.fastmybatis.core.support.DateFillInsert=gmt_create -mybatis.fill.com.gitee.fastmybatis.core.support.DateFillUpdate=gmt_modified - -# 不用改,如果要改,请全局替换修改 -sop.secret=MZZOUSTua6LzApIWXCwEgbBmxSzpzC diff --git a/sop-admin/sop-admin-server/src/main/resources/sop-admin.properties b/sop-admin/sop-admin-server/src/main/resources/sop-admin.properties new file mode 100644 index 00000000..a98965a0 --- /dev/null +++ b/sop-admin/sop-admin-server/src/main/resources/sop-admin.properties @@ -0,0 +1,32 @@ +# 这里的配置不用改,如果要改在application-xx.properties中改 +# 在application-xx.properties中配置会覆盖这里的值 +# 参考:com.gitee.sop.adminserver.config.SopAdminEnvironmentPostProcessor + +spring.application.name=sop-admin + +# session过期时间,分钟 +admin.access-token.timeout-minutes=30 +# 签名方式,rsa:支付宝开放平台签名方式,md5:淘宝开放平台签名方式 +sop.sign-type=rsa + +# nacos配置 +nacos.config.server-addr=${nacos.url} +nacos.discovery.server-addr=${nacos.url} + +# 数据库配置 +spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver +spring.datasource.url=jdbc:mysql://${mysql.host}/sop?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&serverTimezone=Asia/Shanghai +spring.datasource.username=${mysql.username} +spring.datasource.password=${mysql.password} + +# 固定不用改 +mybatis.mapper-locations=classpath:mybatis/mapper/*.xml +easyopen.show-doc=false +easyopen.ignore-validate=true + +# 不用改 +mybatis.fill.com.gitee.fastmybatis.core.support.DateFillInsert=gmt_create +mybatis.fill.com.gitee.fastmybatis.core.support.DateFillUpdate=gmt_modified + +# 不用改,如果要改,请全局替换修改 +sop.secret=MZZOUSTua6LzApIWXCwEgbBmxSzpzC diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/env/SopEnvironmentPostProcessor.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/config/SopGatewayEnvironmentPostProcessor.java similarity index 91% rename from sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/env/SopEnvironmentPostProcessor.java rename to sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/config/SopGatewayEnvironmentPostProcessor.java index a4122b3a..9ea1cbc1 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/env/SopEnvironmentPostProcessor.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/config/SopGatewayEnvironmentPostProcessor.java @@ -1,4 +1,4 @@ -package com.gitee.sop.gatewaycommon.env; +package com.gitee.sop.gatewaycommon.config; import org.springframework.boot.SpringApplication; import org.springframework.boot.env.EnvironmentPostProcessor; @@ -14,7 +14,7 @@ import java.util.Properties; /** * 自定义环境处理,在运行SpringApplication之前加载任意配置文件到Environment环境中 */ -public class SopEnvironmentPostProcessor implements EnvironmentPostProcessor { +public class SopGatewayEnvironmentPostProcessor implements EnvironmentPostProcessor { private final Properties properties = new Properties(); diff --git a/sop-gateway/src/main/resources/META-INF/spring.factories b/sop-gateway/src/main/resources/META-INF/spring.factories index c0f0b43f..c7499f27 100644 --- a/sop-gateway/src/main/resources/META-INF/spring.factories +++ b/sop-gateway/src/main/resources/META-INF/spring.factories @@ -1,3 +1,3 @@ -org.springframework.boot.env.EnvironmentPostProcessor=com.gitee.sop.gatewaycommon.env.SopEnvironmentPostProcessor # 自定义自动配置类,如果有多个类,使用逗号(,)分隔,\正斜杠标示换行还可以读取到指定的类 +org.springframework.boot.env.EnvironmentPostProcessor=com.gitee.sop.gatewaycommon.config.SopGatewayEnvironmentPostProcessor org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.gitee.sop.bridge.SopGatewayAutoConfiguration From 150fae4ae02723354efcd3936f87456e5bdbba6e Mon Sep 17 00:00:00 2001 From: tanghc Date: Fri, 17 Jan 2020 14:56:22 +0800 Subject: [PATCH 38/55] 3.0.0 --- .../adminserver/config/SopAdminEnvironmentPostProcessor.java | 2 +- .../src/main/resources/{ => META-INF}/sop-admin.properties | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename sop-admin/sop-admin-server/src/main/resources/{ => META-INF}/sop-admin.properties (100%) diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/config/SopAdminEnvironmentPostProcessor.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/config/SopAdminEnvironmentPostProcessor.java index cd87aaf0..a8905697 100644 --- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/config/SopAdminEnvironmentPostProcessor.java +++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/config/SopAdminEnvironmentPostProcessor.java @@ -21,7 +21,7 @@ public class SopAdminEnvironmentPostProcessor implements EnvironmentPostProcesso @Override public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) { - Resource resource = new ClassPathResource("sop-admin.properties"); + Resource resource = new ClassPathResource("META-INF/sop-admin.properties"); // 加载成PropertySource对象,并添加到Environment环境中 environment.getPropertySources().addLast(loadProfiles(resource)); } diff --git a/sop-admin/sop-admin-server/src/main/resources/sop-admin.properties b/sop-admin/sop-admin-server/src/main/resources/META-INF/sop-admin.properties similarity index 100% rename from sop-admin/sop-admin-server/src/main/resources/sop-admin.properties rename to sop-admin/sop-admin-server/src/main/resources/META-INF/sop-admin.properties From 09a25f9629cd5d0baa34b90d5566a4d7f9740e2b Mon Sep 17 00:00:00 2001 From: tanghc Date: Sun, 19 Jan 2020 09:40:24 +0800 Subject: [PATCH 39/55] 3.0.0 --- sop-gateway/readme.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 sop-gateway/readme.md diff --git a/sop-gateway/readme.md b/sop-gateway/readme.md new file mode 100644 index 00000000..c0790aa6 --- /dev/null +++ b/sop-gateway/readme.md @@ -0,0 +1,12 @@ +# sop-gateway + +网关入口,默认使用的是Spring Cloud Gateway,如果要使用Zuul,修改pom.xml + +```xml + + com.gitee.sop + + sop-bridge-zuul + version + +``` \ No newline at end of file From fab1a88d78511c9a1b8803ce1a66bf4e2e300df2 Mon Sep 17 00:00:00 2001 From: tanghc Date: Sun, 19 Jan 2020 10:44:21 +0800 Subject: [PATCH 40/55] 3.0.0 --- sop-common/pom.xml | 2 +- .../servercommon/manager/ServiceRouteInfoHandler.java | 9 --------- sop-sdk/sdk-java/pom.xml | 2 +- sop-test/pom.xml | 2 +- sop-website/pom.xml | 2 +- 5 files changed, 4 insertions(+), 13 deletions(-) delete mode 100644 sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/manager/ServiceRouteInfoHandler.java diff --git a/sop-common/pom.xml b/sop-common/pom.xml index 48b4bed4..89ff6588 100644 --- a/sop-common/pom.xml +++ b/sop-common/pom.xml @@ -22,7 +22,7 @@ 4.11 - 1.2.60 + 1.2.62 2.5 1.3.3 3.2.2 diff --git a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/manager/ServiceRouteInfoHandler.java b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/manager/ServiceRouteInfoHandler.java deleted file mode 100644 index 882963ea..00000000 --- a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/manager/ServiceRouteInfoHandler.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.gitee.sop.servercommon.manager; - -import org.springframework.web.bind.annotation.RequestMapping; - -/** - * @author tanghc - */ -public interface ServiceRouteInfoHandler { -} diff --git a/sop-sdk/sdk-java/pom.xml b/sop-sdk/sdk-java/pom.xml index 12def640..d7f37743 100644 --- a/sop-sdk/sdk-java/pom.xml +++ b/sop-sdk/sdk-java/pom.xml @@ -24,7 +24,7 @@ com.alibaba fastjson - 1.2.60 + 1.2.62 diff --git a/sop-test/pom.xml b/sop-test/pom.xml index 0f8040be..c6e167f5 100644 --- a/sop-test/pom.xml +++ b/sop-test/pom.xml @@ -33,7 +33,7 @@ com.alibaba fastjson - 1.2.60 + 1.2.62 commons-codec diff --git a/sop-website/pom.xml b/sop-website/pom.xml index 2bf3e40f..d949848f 100644 --- a/sop-website/pom.xml +++ b/sop-website/pom.xml @@ -65,7 +65,7 @@ com.alibaba fastjson - 1.2.60 + 1.2.62 compile From e8e6fc4ce4a20a2681bce7e8a42da031027b1c7a Mon Sep 17 00:00:00 2001 From: tanghc Date: Sun, 19 Jan 2020 16:24:45 +0800 Subject: [PATCH 41/55] 3.0.0 --- .../gitee/sop/gatewaycommon/manager/DefaultEnvGrayManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/DefaultEnvGrayManager.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/DefaultEnvGrayManager.java index 9e6df3be..abf3ae4f 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/DefaultEnvGrayManager.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/DefaultEnvGrayManager.java @@ -49,7 +49,7 @@ public class DefaultEnvGrayManager implements EnvGrayManager { } private ServiceGrayConfig getGrayConfig(String serviceId) { - if (serviceId == null) { + if (serviceId == null || !instanceIdServiceIdMap.containsValue(serviceId)) { return null; } return serviceGrayConfigMap.get(serviceId); From 563d5adcc0b84f5428069422f0d3d4d0bdd2e084 Mon Sep 17 00:00:00 2001 From: tanghc Date: Mon, 20 Jan 2020 15:16:26 +0800 Subject: [PATCH 42/55] 3.0.0 --- .../com/gitee/sop/gatewaycommon/zuul/ValidateService.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/ValidateService.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/ValidateService.java index 46632c89..c5c69032 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/ValidateService.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/ValidateService.java @@ -38,8 +38,11 @@ public class ValidateService { currentContext.setRequest(RequestUtil.wrapRequest(request)); currentContext.setResponse(response); // 解析参数 - ApiParam param = paramBuilder.build(currentContext); - ZuulContext.setApiParam(param); + ApiParam param = ZuulContext.getApiParam(); + if (param == null) { + param = paramBuilder.build(currentContext); + ZuulContext.setApiParam(param); + } doValidate(currentContext, param, callback); } From 99cb38eaa4a27207e86466597e4b07bf484fd332 Mon Sep 17 00:00:00 2001 From: tanghc Date: Mon, 20 Jan 2020 16:10:24 +0800 Subject: [PATCH 43/55] 3.0.0 --- .../src/main/resources/sop-bridge.properties | 5 ++ .../manager/DefaultLimitConfigManager.java | 51 +++++++++++++++++-- .../zuul/controller/ZuulIndexController.java | 12 ----- 3 files changed, 52 insertions(+), 16 deletions(-) diff --git a/sop-common/sop-bridge-zuul/src/main/resources/sop-bridge.properties b/sop-common/sop-bridge-zuul/src/main/resources/sop-bridge.properties index 4f0c045e..7f4699ad 100644 --- a/sop-common/sop-bridge-zuul/src/main/resources/sop-bridge.properties +++ b/sop-common/sop-bridge-zuul/src/main/resources/sop-bridge.properties @@ -8,6 +8,11 @@ zuul.Servlet30WrapperFilter.pre.disable=true # 不用改,如果要改,请全局替换修改 sop.secret=MZZOUSTua6LzApIWXCwEgbBmxSzpzC +# zuul优化配置 +zuul.host.max-per-route-connections=1000 +zuul.host.max-total-connections=1000 +zuul.semaphore.max-semaphores=1000 + # nacos cloud配置 spring.cloud.nacos.discovery.server-addr=${nacos.url} diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/DefaultLimitConfigManager.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/DefaultLimitConfigManager.java index 54efd924..d7885087 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/DefaultLimitConfigManager.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/DefaultLimitConfigManager.java @@ -3,6 +3,7 @@ package com.gitee.sop.gatewaycommon.manager; import com.gitee.sop.gatewaycommon.bean.ConfigLimitDto; import org.apache.commons.lang.StringUtils; +import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; @@ -39,22 +40,64 @@ public class DefaultLimitConfigManager implements LimitConfigManager { } } + /** + * // 根据路由ID限流 + * routeId, + * // 根据appKey限流 + * appKey, + * // 根据路由ID + appKey限流 + * routeId + appKey, + * + * // 根据ip限流 + * ip, + * // 根据ip+路由id限流 + * ip + routeId, + * // 根据ip+appKey限流 + * ip + appKey, + * // 根据ip+路由id+appKey限流 + * ip + routeId + appKey, + * @param configLimitDto + * @return + */ protected Set buildKeys(ConfigLimitDto configLimitDto) { Set keys = new HashSet<>(); + Set baseKeys = new HashSet<>(); String routeId = Optional.ofNullable(configLimitDto.getRouteId()).orElse(""); String appKey = Optional.ofNullable(configLimitDto.getAppKey()).orElse(""); String limitIp = Optional.ofNullable(configLimitDto.getLimitIp()).orElse("").replaceAll("\\s", ""); - String baseKey = routeId.trim() + appKey.trim(); - keys.add(baseKey); + // 根据路由ID限流 + if (StringUtils.isNotBlank(routeId) && StringUtils.isBlank(appKey) && StringUtils.isBlank(limitIp)) { + keys.add(routeId); + baseKeys.add(routeId); + } + // 根据appKey限流 + if (StringUtils.isBlank(routeId) && StringUtils.isNotBlank(appKey) && StringUtils.isBlank(limitIp)) { + keys.add(appKey); + baseKeys.add(appKey); + } + // 根据路由ID + appKey限流 + if (StringUtils.isNotBlank(routeId) && StringUtils.isNotBlank(appKey) && StringUtils.isBlank(limitIp)) { + keys.add(routeId.trim() + appKey.trim()); + baseKeys.add(routeId.trim() + appKey.trim()); + } + // 根据ip限流 + if (StringUtils.isBlank(routeId) && StringUtils.isBlank(appKey) && StringUtils.isNotBlank(limitIp)) { + String[] ips = limitIp.split("\\,|\\,"); + keys.addAll(Arrays.asList(ips)); + } + // 根据ip+路由id限流 + // 根据ip+appKey限流 + // 根据ip+路由id+appKey限流 if (StringUtils.isNotBlank(limitIp)) { String[] ips = limitIp.split("\\,|\\,"); for (String ip : ips) { - keys.add(ip + baseKey); + for (String baseKey : baseKeys) { + keys.add(ip + baseKey); + } } } - return keys; } diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/controller/ZuulIndexController.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/controller/ZuulIndexController.java index ac1606e4..bc7ebd27 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/controller/ZuulIndexController.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/controller/ZuulIndexController.java @@ -6,7 +6,6 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import javax.servlet.ServletException; @@ -75,15 +74,4 @@ public class ZuulIndexController { request.getRequestDispatcher(this.path).forward(request, response); } - @RequestMapping("/{method}/{version}/") - public void redirect( - @PathVariable("method") String method - , @PathVariable("version") String version - , HttpServletRequest request - , HttpServletResponse response - ) { - request.setAttribute(SopConstants.REDIRECT_METHOD_KEY, method); - request.setAttribute(SopConstants.REDIRECT_VERSION_KEY, version); - validateService.validate(request, response, callback); - } } From 2a7835e29042c80625d29690c916d336543d866b Mon Sep 17 00:00:00 2001 From: tanghc Date: Mon, 20 Jan 2020 16:11:51 +0800 Subject: [PATCH 44/55] 3.0.0 --- .../com/gitee/sop/gateway/manager/DbLimitConfigManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sop-gateway/src/main/java/com/gitee/sop/gateway/manager/DbLimitConfigManager.java b/sop-gateway/src/main/java/com/gitee/sop/gateway/manager/DbLimitConfigManager.java index 3cb71232..20645d62 100644 --- a/sop-gateway/src/main/java/com/gitee/sop/gateway/manager/DbLimitConfigManager.java +++ b/sop-gateway/src/main/java/com/gitee/sop/gateway/manager/DbLimitConfigManager.java @@ -29,7 +29,7 @@ public class DbLimitConfigManager extends DefaultLimitConfigManager { public void load() { Query query = new Query(); configLimitMapper.list(query) - .forEach(configLimit -> putVal(configLimit)); + .forEach(this::putVal); } From f92318dc7a4bd73e89cbc1cd2600fa303463ac43 Mon Sep 17 00:00:00 2001 From: tanghc Date: Tue, 21 Jan 2020 08:50:57 +0800 Subject: [PATCH 45/55] 3.0.0 --- .../gatewaycommon/manager/DefaultLimitConfigManager.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/DefaultLimitConfigManager.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/DefaultLimitConfigManager.java index d7885087..0af913b8 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/DefaultLimitConfigManager.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/DefaultLimitConfigManager.java @@ -61,27 +61,23 @@ public class DefaultLimitConfigManager implements LimitConfigManager { */ protected Set buildKeys(ConfigLimitDto configLimitDto) { Set keys = new HashSet<>(); - Set baseKeys = new HashSet<>(); String routeId = Optional.ofNullable(configLimitDto.getRouteId()).orElse(""); String appKey = Optional.ofNullable(configLimitDto.getAppKey()).orElse(""); String limitIp = Optional.ofNullable(configLimitDto.getLimitIp()).orElse("").replaceAll("\\s", ""); - // 根据路由ID限流 if (StringUtils.isNotBlank(routeId) && StringUtils.isBlank(appKey) && StringUtils.isBlank(limitIp)) { keys.add(routeId); - baseKeys.add(routeId); } // 根据appKey限流 if (StringUtils.isBlank(routeId) && StringUtils.isNotBlank(appKey) && StringUtils.isBlank(limitIp)) { keys.add(appKey); - baseKeys.add(appKey); } // 根据路由ID + appKey限流 if (StringUtils.isNotBlank(routeId) && StringUtils.isNotBlank(appKey) && StringUtils.isBlank(limitIp)) { keys.add(routeId.trim() + appKey.trim()); - baseKeys.add(routeId.trim() + appKey.trim()); } + Set baseKeys = new HashSet<>(keys); // 根据ip限流 if (StringUtils.isBlank(routeId) && StringUtils.isBlank(appKey) && StringUtils.isNotBlank(limitIp)) { String[] ips = limitIp.split("\\,|\\,"); From 250a9b61c58168a59802c0aebc634dfee0b85442 Mon Sep 17 00:00:00 2001 From: tanghc Date: Tue, 21 Jan 2020 09:29:43 +0800 Subject: [PATCH 46/55] 3.0.0 --- sop-website/src/main/resources/application-dev.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sop-website/src/main/resources/application-dev.properties b/sop-website/src/main/resources/application-dev.properties index 72235474..cce940d2 100644 --- a/sop-website/src/main/resources/application-dev.properties +++ b/sop-website/src/main/resources/application-dev.properties @@ -1,5 +1,5 @@ server.port=8083 -spring.application.name=website-server +spring.application.name=sop-website # ------- 需要改的配置 ------- # nacos地址 From 65038a94381f4fcc8068e8203579d518f9c30386 Mon Sep 17 00:00:00 2001 From: tanghc Date: Tue, 21 Jan 2020 09:39:07 +0800 Subject: [PATCH 47/55] 3.0.0 --- changelog.md | 1 + doc/docs/_sidebar.md | 71 +++++------ doc/docs/files/90999_网关性能测试.md | 112 ++++++++++++++++++ .../src/main/resources/sop-bridge.properties | 3 +- .../manager/AbstractConfiguration.java | 40 ++++++- .../gitee/sop/test/AlipayClientPostTest.java | 2 +- 6 files changed, 189 insertions(+), 40 deletions(-) create mode 100644 doc/docs/files/90999_网关性能测试.md diff --git a/changelog.md b/changelog.md index de11209d..e81dc56c 100644 --- a/changelog.md +++ b/changelog.md @@ -7,6 +7,7 @@ - zuul和gateway网关二合一,可随意切换 - 精简配置文件 - 优化文档中心页面 +- 优化接口限流 ## 2.5.10 diff --git a/doc/docs/_sidebar.md b/doc/docs/_sidebar.md index b48ca6d2..c1076802 100644 --- a/doc/docs/_sidebar.md +++ b/doc/docs/_sidebar.md @@ -1,37 +1,38 @@ -* [首页](/?t=1579169719974) +* [首页](/?t=1579512230184) * 开发文档 - * [快速体验](files/10010_快速体验.md?t=1579169719976) - * [项目接入到SOP](files/10011_项目接入到SOP.md?t=1579169719993) - * [新增接口](files/10020_新增接口.md?t=1579169719993) - * [开发流程](files/10021_开发流程.md?t=1579169719993) - * [业务参数校验](files/10030_业务参数校验.md?t=1579169719993) - * [错误处理](files/10040_错误处理.md?t=1579169719993) - * [编写文档](files/10041_编写文档.md?t=1579169719993) - * [接口交互详解](files/10050_接口交互详解.md?t=1579169719993) - * [easyopen支持](files/10070_easyopen支持.md?t=1579169719993) - * [使用签名校验工具](files/10080_使用签名校验工具.md?t=1579169719993) - * [ISV管理](files/10085_ISV管理.md?t=1579169719994) - * [自定义返回结果](files/10087_自定义返回结果.md?t=1579169719994) - * [自定义过滤器](files/10088_自定义过滤器.md?t=1579169719994) - * [自定义校验token](files/10089_自定义校验token.md?t=1579169719994) - * [路由授权](files/10090_路由授权.md?t=1579169719994) - * [接口限流](files/10092_接口限流.md?t=1579169719994) - * [监控日志](files/10093_监控日志.md?t=1579169719994) - * [SDK开发](files/10095_SDK开发.md?t=1579169719994) - * [使用SpringCloudGateway](files/10096_使用SpringCloudGateway.md?t=1579169719994) - * [应用授权](files/10097_应用授权.md?t=1579169719994) - * [提供restful接口](files/10100_提供restful接口.md?t=1579169719995) - * [文件上传](files/10104_文件上传.md?t=1579169719995) - * [配置Sleuth链路追踪](files/10109_配置Sleuth链路追踪.md?t=1579169719995) - * [预发布灰度发布](files/10110_预发布灰度发布.md?t=1579169719995) - * [动态修改请求参数](files/10111_动态修改请求参数.md?t=1579169719995) - * [使用eureka](files/10112_使用eureka.md?t=1579169719995) - * [扩展其它注册中心](files/10113_扩展其它注册中心.md?t=1579169719995) + * [快速体验](files/10010_快速体验.md?t=1579512230186) + * [项目接入到SOP](files/10011_项目接入到SOP.md?t=1579512230207) + * [新增接口](files/10020_新增接口.md?t=1579512230208) + * [开发流程](files/10021_开发流程.md?t=1579512230208) + * [业务参数校验](files/10030_业务参数校验.md?t=1579512230208) + * [错误处理](files/10040_错误处理.md?t=1579512230208) + * [编写文档](files/10041_编写文档.md?t=1579512230208) + * [接口交互详解](files/10050_接口交互详解.md?t=1579512230208) + * [easyopen支持](files/10070_easyopen支持.md?t=1579512230208) + * [使用签名校验工具](files/10080_使用签名校验工具.md?t=1579512230209) + * [ISV管理](files/10085_ISV管理.md?t=1579512230209) + * [自定义返回结果](files/10087_自定义返回结果.md?t=1579512230209) + * [自定义过滤器](files/10088_自定义过滤器.md?t=1579512230209) + * [自定义校验token](files/10089_自定义校验token.md?t=1579512230209) + * [路由授权](files/10090_路由授权.md?t=1579512230209) + * [接口限流](files/10092_接口限流.md?t=1579512230209) + * [监控日志](files/10093_监控日志.md?t=1579512230209) + * [SDK开发](files/10095_SDK开发.md?t=1579512230210) + * [使用SpringCloudGateway](files/10096_使用SpringCloudGateway.md?t=1579512230210) + * [应用授权](files/10097_应用授权.md?t=1579512230210) + * [提供restful接口](files/10100_提供restful接口.md?t=1579512230210) + * [文件上传](files/10104_文件上传.md?t=1579512230210) + * [配置Sleuth链路追踪](files/10109_配置Sleuth链路追踪.md?t=1579512230210) + * [预发布灰度发布](files/10110_预发布灰度发布.md?t=1579512230211) + * [动态修改请求参数](files/10111_动态修改请求参数.md?t=1579512230211) + * [使用eureka](files/10112_使用eureka.md?t=1579512230211) + * [扩展其它注册中心](files/10113_扩展其它注册中心.md?t=1579512230211) * 原理分析 - * [原理分析之@ApiMapping](files/90010_原理分析之@ApiMapping.md?t=1579169719995) - * [原理分析之如何存储路由](files/90011_原理分析之如何存储路由.md?t=1579169719995) - * [原理分析之如何路由](files/90012_原理分析之如何路由.md?t=1579169719995) - * [原理分析之文档归纳](files/90013_原理分析之文档归纳.md?t=1579169719996) - * [原理分析之预发布灰度发布](files/90014_原理分析之预发布灰度发布.md?t=1579169719996) - * [2.x升3.x注意事项](files/90099_2.x升3.x注意事项.md?t=1579169719996) - * [常见问题](files/90100_常见问题.md?t=1579169719996) + * [原理分析之@ApiMapping](files/90010_原理分析之@ApiMapping.md?t=1579512230211) + * [原理分析之如何存储路由](files/90011_原理分析之如何存储路由.md?t=1579512230211) + * [原理分析之如何路由](files/90012_原理分析之如何路由.md?t=1579512230211) + * [原理分析之文档归纳](files/90013_原理分析之文档归纳.md?t=1579512230211) + * [原理分析之预发布灰度发布](files/90014_原理分析之预发布灰度发布.md?t=1579512230211) + * [2.x升3.x注意事项](files/90099_2.x升3.x注意事项.md?t=1579512230212) + * [常见问题](files/90100_常见问题.md?t=1579512230212) + * [网关性能测试](files/90999_网关性能测试.md?t=1579512230212) diff --git a/doc/docs/files/90999_网关性能测试.md b/doc/docs/files/90999_网关性能测试.md new file mode 100644 index 00000000..38c47d0e --- /dev/null +++ b/doc/docs/files/90999_网关性能测试.md @@ -0,0 +1,112 @@ +# 网关性能测试 + +**测试环境** + +> 注意:记得关闭限流功能 + +- 测试工具:[wrk](https://github.com/wg/wrk),[安装教程](https://www.cnblogs.com/quanxiaoha/p/10661650.html) +- 服务器:CentOS7(虚拟机,宿主机:macbookpro),内存:2G,CPU:1,核数:2核 +- 运行环境:Java8、Mysql-5.7、Nacos-1.1.3 +- 运行参数:`-verbose:gc -XX:+PrintGCDetails -XX:+PrintHeapAtGC -Xloggc:gc-zuul.log \ + -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=128m -Xms1024m -Xmx1024m -Xmn512m -Xss256k -XX:SurvivorRatio=8\ + -XX:+UseConcMarkSweepGC` + +- zuul配置: + +```properties +# 不校验时间,这样一个链接可以一直进行测试 +sop.api-config.timeout-seconds=0 +sop.restful.enable=true + +logging.level.com.gitee=info + +# zuul调优 +zuul.host.max-per-route-connections=5000 +zuul.host.max-total-connections=5000 +zuul.semaphore.max-semaphores=5000 + +ribbon.ReadTimeout=5000 +hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=13000 + +logging.file=sop-gateway.log +``` + +以上配置仅针对zuul,Spring Cloud Gateway没有做优化配置 + +CentOS允许最大连接数 +``` +$ ulimit -n +65535 +``` + +## 调用开放接口 + +- wrk命令: + +``` +wrk -t8 -c200 -d30s "http://10.1.31.227:8081/?charset=utf-8&biz_content=%7B%22name%22%3A%22%E8%91%AB%E8%8A%A6%E5%A8%83%22%2C%22id%22%3A%221%22%7D&method=alipay.story.get&format=json&sign=RjK%2FThnzAJQOw%2BfoVLS18PgWZAR%2B25SI2XdONFhS%2BmS8vsv2jNT3rygFoh%2ByX1AJbMgIEfcBzkQyqrs29jjd5dcwHVkcf7vxXshyfcEgl0fbMF6Ihycnz7rqSqkW3lzAWx4NuWUfkPnTX8Ffuf%2BhYRaI0NCpNv%2FV300HvsvmUjS6ZzS4YHaT1peSq0agfUhwRPd97aYMnUwRZDzxNfc5wuXA7OQ1o%2FPYIuIb%2FajVfwNP5ysitc%2FKtYEqt9rNAuzkcFmsw71d2RRnrPLsDN%2BuBXnIEh482f%2FbMj2Rj4%2FMq%2B0PEtlTRbg3rYnxyfowymfX%2BNmI4gNRUt70D4a%2FL3Qiug%3D%3D&app_id=2019032617262200001&sign_type=RSA2&version=1.0×tamp=2020-01-19+13%3A34%3A12" +``` + +- Spring Cloud Gateway测试结果 + +``` + 8 threads and 200 connections + Thread Stats Avg Stdev Max +/- Stdev + Latency 139.74ms 69.39ms 617.14ms 69.82% + Req/Sec 182.12 55.74 343.00 66.24% + 43391 requests in 30.09s, 11.96MB read +Requests/sec: 1441.96 +Transfer/sec: 406.96KB +``` + +- Spring Cloud Zuul测试结果 + +``` + 8 threads and 200 connections + Thread Stats Avg Stdev Max +/- Stdev + Latency 230.14ms 331.27ms 2.00s 86.98% + Req/Sec 141.69 51.04 323.00 66.99% + 33945 requests in 30.09s, 9.88MB read + Socket errors: connect 0, read 0, write 0, timeout 385 +Requests/sec: 1128.05 +Transfer/sec: 336.15KB +``` + +## 调用restful请求 + +- wrk命令: + +``` +wrk -t8 -c200 -d30s "http://10.1.31.227:8081/rest/story-service/food/getFoodById?id=2" +``` + +线程数为 8,模拟 200 个并发请求,持续 30 秒 + +- Spring Cloud Gateway测试结果 + +``` + 8 threads and 200 connections + Thread Stats Avg Stdev Max +/- Stdev + Latency 120.14ms 58.30ms 513.85ms 67.47% + Req/Sec 210.47 54.26 770.00 69.37% + 50301 requests in 30.10s, 7.53MB read +Requests/sec: 1670.97 +Transfer/sec: 256.21KB +``` + + +- Spring Cloud Zuul测试结果 + +``` + 8 threads and 200 connections + Thread Stats Avg Stdev Max +/- Stdev + Latency 185.86ms 285.65ms 1.99s 88.55% + Req/Sec 167.75 55.60 460.00 68.05% + 40070 requests in 30.09s, 6.65MB read + Socket errors: connect 0, read 0, write 0, timeout 466 +Requests/sec: 1331.81 +Transfer/sec: 226.50KB +``` + + +综上所述,Spring Cloud Gateway在没有优化的情况下,压测表现比zuul好,但zuul的数据表现也不差,但是出现超时现象,总的来说还是Spring Cloud Gateway具有优势。 \ No newline at end of file diff --git a/sop-common/sop-bridge-zuul/src/main/resources/sop-bridge.properties b/sop-common/sop-bridge-zuul/src/main/resources/sop-bridge.properties index 7f4699ad..4f95afd1 100644 --- a/sop-common/sop-bridge-zuul/src/main/resources/sop-bridge.properties +++ b/sop-common/sop-bridge-zuul/src/main/resources/sop-bridge.properties @@ -25,10 +25,11 @@ spring.datasource.password=${mysql.password} # https://blog.csdn.net/qq_36872046/article/details/81058045 # 路由转发超时时间,毫秒,默认值1000,详见:RibbonClientConfiguration.DEFAULT_READ_TIMEOUT。 # 如果微服务端 处理时间过长,会导致ribbon read超时,解决办法将这个值调大一点 -ribbon.ReadTimeout=2000 +ribbon.ReadTimeout=5000 # 设置为true(默认false),则所有请求都重试,默认只支持get请求重试 # 请谨慎设置,因为post请求大多都是写入请求,如果要支持重试,确保服务的幂等性 ribbon.OkToRetryOnAllOperations=false +hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=5000 # 不用改 mybatis.fill.com.gitee.fastmybatis.core.support.DateFillInsert=gmt_create diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/AbstractConfiguration.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/AbstractConfiguration.java index d2a7c7ac..ff8dd619 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/AbstractConfiguration.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/AbstractConfiguration.java @@ -18,8 +18,11 @@ import com.gitee.sop.gatewaycommon.secret.IsvManager; import com.gitee.sop.gatewaycommon.session.SessionManager; import com.gitee.sop.gatewaycommon.validate.SignConfig; import com.gitee.sop.gatewaycommon.validate.Validator; +import lombok.extern.slf4j.Slf4j; import org.springframework.beans.BeansException; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.ApplicationArguments; +import org.springframework.boot.ApplicationRunner; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.cloud.client.discovery.event.HeartbeatEvent; @@ -37,11 +40,20 @@ import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import org.springframework.web.filter.CorsFilter; import javax.annotation.PostConstruct; +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; /** * @author tanghc */ -public class AbstractConfiguration implements ApplicationContextAware { +@Slf4j +public class AbstractConfiguration implements ApplicationContextAware, ApplicationRunner { + + private Lock lock = new ReentrantLock(); + private Condition condition = lock.newCondition(); + + private volatile boolean isStartupCompleted; @Autowired protected Environment environment; @@ -63,6 +75,17 @@ public class AbstractConfiguration implements ApplicationContextAware { */ @EventListener(classes = HeartbeatEvent.class) public void listenNacosEvent(ApplicationEvent heartbeatEvent) { + // 没有启动完毕先等待 + if (!isStartupCompleted) { + lock.lock(); + try { + condition.await(); + } catch (InterruptedException e) { + log.error("condition.await() error", e); + } finally { + lock.unlock(); + } + } registryListener.onEvent(heartbeatEvent); } @@ -200,10 +223,22 @@ public class AbstractConfiguration implements ApplicationContextAware { return corsConfiguration; } + @Override + public void run(ApplicationArguments args) throws Exception { + this.isStartupCompleted = true; + lock.lock(); + condition.signal(); + lock.unlock(); + after(); + } + @PostConstruct - public final void after() { + private void post() { EnvironmentContext.setEnvironment(environment); SpringContext.setApplicationContext(applicationContext); + } + + public final void after() { if (RouteRepositoryContext.getRouteRepository() == null) { throw new IllegalArgumentException("RouteRepositoryContext.setRouteRepository()方法未使用"); } @@ -219,7 +254,6 @@ public class AbstractConfiguration implements ApplicationContextAware { initMessage(); initBeanInitializer(); doAfter(); - } protected void initBeanInitializer() { diff --git a/sop-test/src/test/java/com/gitee/sop/test/AlipayClientPostTest.java b/sop-test/src/test/java/com/gitee/sop/test/AlipayClientPostTest.java index 67d80f96..fa3c93e2 100644 --- a/sop-test/src/test/java/com/gitee/sop/test/AlipayClientPostTest.java +++ b/sop-test/src/test/java/com/gitee/sop/test/AlipayClientPostTest.java @@ -56,7 +56,6 @@ public class AlipayClientPostTest extends TestBase { System.out.println("----------- 请求信息 -----------"); System.out.println("请求参数:" + buildParamQuery(params)); - System.out.println("URL参数:" + buildUrlQuery(params)); System.out.println("商户秘钥:" + privateKey); String content = AlipaySignature.getSignContent(params); System.out.println("待签名内容:" + content); @@ -64,6 +63,7 @@ public class AlipayClientPostTest extends TestBase { System.out.println("签名(sign):" + sign); params.put("sign", sign); + System.out.println("URL参数:" + buildUrlQuery(params)); System.out.println("----------- 返回结果 -----------"); String responseData = get(url, params);// 发送请求 From 7887d1ac62332d4bfb18703113f553e18590f740 Mon Sep 17 00:00:00 2001 From: tanghc Date: Tue, 21 Jan 2020 09:40:32 +0800 Subject: [PATCH 48/55] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=99=90=E6=B5=81BUG?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../manager/DefaultLimitConfigManager.java | 49 +++++++++++++++++-- 1 file changed, 44 insertions(+), 5 deletions(-) diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/DefaultLimitConfigManager.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/DefaultLimitConfigManager.java index 54efd924..0af913b8 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/DefaultLimitConfigManager.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/DefaultLimitConfigManager.java @@ -3,6 +3,7 @@ package com.gitee.sop.gatewaycommon.manager; import com.gitee.sop.gatewaycommon.bean.ConfigLimitDto; import org.apache.commons.lang.StringUtils; +import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; @@ -39,22 +40,60 @@ public class DefaultLimitConfigManager implements LimitConfigManager { } } + /** + * // 根据路由ID限流 + * routeId, + * // 根据appKey限流 + * appKey, + * // 根据路由ID + appKey限流 + * routeId + appKey, + * + * // 根据ip限流 + * ip, + * // 根据ip+路由id限流 + * ip + routeId, + * // 根据ip+appKey限流 + * ip + appKey, + * // 根据ip+路由id+appKey限流 + * ip + routeId + appKey, + * @param configLimitDto + * @return + */ protected Set buildKeys(ConfigLimitDto configLimitDto) { Set keys = new HashSet<>(); String routeId = Optional.ofNullable(configLimitDto.getRouteId()).orElse(""); String appKey = Optional.ofNullable(configLimitDto.getAppKey()).orElse(""); String limitIp = Optional.ofNullable(configLimitDto.getLimitIp()).orElse("").replaceAll("\\s", ""); - String baseKey = routeId.trim() + appKey.trim(); - keys.add(baseKey); - + // 根据路由ID限流 + if (StringUtils.isNotBlank(routeId) && StringUtils.isBlank(appKey) && StringUtils.isBlank(limitIp)) { + keys.add(routeId); + } + // 根据appKey限流 + if (StringUtils.isBlank(routeId) && StringUtils.isNotBlank(appKey) && StringUtils.isBlank(limitIp)) { + keys.add(appKey); + } + // 根据路由ID + appKey限流 + if (StringUtils.isNotBlank(routeId) && StringUtils.isNotBlank(appKey) && StringUtils.isBlank(limitIp)) { + keys.add(routeId.trim() + appKey.trim()); + } + Set baseKeys = new HashSet<>(keys); + // 根据ip限流 + if (StringUtils.isBlank(routeId) && StringUtils.isBlank(appKey) && StringUtils.isNotBlank(limitIp)) { + String[] ips = limitIp.split("\\,|\\,"); + keys.addAll(Arrays.asList(ips)); + } + // 根据ip+路由id限流 + // 根据ip+appKey限流 + // 根据ip+路由id+appKey限流 if (StringUtils.isNotBlank(limitIp)) { String[] ips = limitIp.split("\\,|\\,"); for (String ip : ips) { - keys.add(ip + baseKey); + for (String baseKey : baseKeys) { + keys.add(ip + baseKey); + } } } - return keys; } From 8fe0951c02f656d5b0319266bc973c768c167c68 Mon Sep 17 00:00:00 2001 From: tanghc Date: Tue, 21 Jan 2020 09:42:22 +0800 Subject: [PATCH 49/55] 2.5.12 --- changelog.md | 4 ++++ sop-auth/pom.xml | 2 +- sop-common/pom.xml | 2 +- sop-common/sop-gateway-common/pom.xml | 4 ++-- sop-common/sop-service-common/pom.xml | 4 ++-- sop-example/sop-book/sop-book-web/pom.xml | 2 +- sop-example/sop-easyopen/pom.xml | 2 +- sop-example/sop-springmvc/pom.xml | 2 +- sop-example/sop-story/sop-story-web/pom.xml | 2 +- sop-gateway/pom.xml | 2 +- sop-website/pom.xml | 2 +- 11 files changed, 16 insertions(+), 12 deletions(-) diff --git a/changelog.md b/changelog.md index bb93ebb7..30cdc776 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,9 @@ # changelog +## 2.5.12 + +- 修复限流BUG + ## 2.5.11 - 优化灰度/预发布请求 diff --git a/sop-auth/pom.xml b/sop-auth/pom.xml index 2fe15bc3..d7204352 100644 --- a/sop-auth/pom.xml +++ b/sop-auth/pom.xml @@ -26,7 +26,7 @@ com.gitee.sop sop-service-common - 2.5.11-SNAPSHOT + 2.5.12-SNAPSHOT diff --git a/sop-common/pom.xml b/sop-common/pom.xml index 48c9c5f5..a9f7750e 100644 --- a/sop-common/pom.xml +++ b/sop-common/pom.xml @@ -5,7 +5,7 @@ 4.0.0 com.gitee.sop sop-common - 2.5.11-SNAPSHOT + 2.5.12-SNAPSHOT pom diff --git a/sop-common/sop-gateway-common/pom.xml b/sop-common/sop-gateway-common/pom.xml index b0f6ad38..29390522 100644 --- a/sop-common/sop-gateway-common/pom.xml +++ b/sop-common/sop-gateway-common/pom.xml @@ -5,11 +5,11 @@ com.gitee.sop sop-common - 2.5.11-SNAPSHOT + 2.5.12-SNAPSHOT ../pom.xml sop-gateway-common - 2.5.11-SNAPSHOT + 2.5.12-SNAPSHOT jar sop-gateway-common diff --git a/sop-common/sop-service-common/pom.xml b/sop-common/sop-service-common/pom.xml index acddbd0c..d471851b 100644 --- a/sop-common/sop-service-common/pom.xml +++ b/sop-common/sop-service-common/pom.xml @@ -6,11 +6,11 @@ com.gitee.sop sop-common - 2.5.11-SNAPSHOT + 2.5.12-SNAPSHOT ../pom.xml sop-service-common - 2.5.11-SNAPSHOT + 2.5.12-SNAPSHOT jar sop-service-common diff --git a/sop-example/sop-book/sop-book-web/pom.xml b/sop-example/sop-book/sop-book-web/pom.xml index e4254809..61815f56 100644 --- a/sop-example/sop-book/sop-book-web/pom.xml +++ b/sop-example/sop-book/sop-book-web/pom.xml @@ -28,7 +28,7 @@ com.gitee.sop sop-service-common - 2.5.11-SNAPSHOT + 2.5.12-SNAPSHOT com.gitee.sop diff --git a/sop-example/sop-easyopen/pom.xml b/sop-example/sop-easyopen/pom.xml index 88279bab..5c2099d7 100644 --- a/sop-example/sop-easyopen/pom.xml +++ b/sop-example/sop-easyopen/pom.xml @@ -29,7 +29,7 @@ com.gitee.sop sop-service-common - 2.5.11-SNAPSHOT + 2.5.12-SNAPSHOT diff --git a/sop-example/sop-story/sop-story-web/pom.xml b/sop-example/sop-story/sop-story-web/pom.xml index f877e33a..f39b5429 100644 --- a/sop-example/sop-story/sop-story-web/pom.xml +++ b/sop-example/sop-story/sop-story-web/pom.xml @@ -28,7 +28,7 @@ com.gitee.sop sop-service-common - 2.5.11-SNAPSHOT + 2.5.12-SNAPSHOT com.gitee.sop diff --git a/sop-gateway/pom.xml b/sop-gateway/pom.xml index b5df0fc6..2f5c34c6 100644 --- a/sop-gateway/pom.xml +++ b/sop-gateway/pom.xml @@ -29,7 +29,7 @@ com.gitee.sop sop-gateway-common - 2.5.11-SNAPSHOT + 2.5.12-SNAPSHOT diff --git a/sop-website/pom.xml b/sop-website/pom.xml index a949cadc..9075bfd5 100644 --- a/sop-website/pom.xml +++ b/sop-website/pom.xml @@ -35,7 +35,7 @@ com.gitee.sop sop-gateway-common - 2.5.11-SNAPSHOT + 2.5.12-SNAPSHOT From 03b6ce2c709eaf89a15dbbf7065f02ab4f472c73 Mon Sep 17 00:00:00 2001 From: tanghc Date: Tue, 21 Jan 2020 09:51:49 +0800 Subject: [PATCH 50/55] 3.0.0 --- .../com/gitee/sop/gatewaycommon/route/BaseRegistryListener.java | 1 + 1 file changed, 1 insertion(+) diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/route/BaseRegistryListener.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/route/BaseRegistryListener.java index 4167e93b..0eed415d 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/route/BaseRegistryListener.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/route/BaseRegistryListener.java @@ -26,6 +26,7 @@ public abstract class BaseRegistryListener implements RegistryListener { static { EXCLUDE_SERVICE_ID_LIST.add("sop-gateway"); + EXCLUDE_SERVICE_ID_LIST.add("sop-website"); EXCLUDE_SERVICE_ID_LIST.add("website-server"); } From 7d2d18226303f004f7bd192f78c3ebcfd443bdb0 Mon Sep 17 00:00:00 2001 From: tanghc Date: Tue, 21 Jan 2020 10:15:47 +0800 Subject: [PATCH 51/55] 3.0.0 --- .../gitee/sop/gatewaycommon/manager/AbstractConfiguration.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/AbstractConfiguration.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/AbstractConfiguration.java index ff8dd619..f502e6ab 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/AbstractConfiguration.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/AbstractConfiguration.java @@ -227,7 +227,7 @@ public class AbstractConfiguration implements ApplicationContextAware, Applicati public void run(ApplicationArguments args) throws Exception { this.isStartupCompleted = true; lock.lock(); - condition.signal(); + condition.signalAll(); lock.unlock(); after(); } From 9b8f7be8dddf3bc73a6315ffdb29a987f7e29c5c Mon Sep 17 00:00:00 2001 From: tanghc Date: Tue, 21 Jan 2020 11:07:59 +0800 Subject: [PATCH 52/55] 3.0.0 --- .../gitee/sop/gatewaycommon/route/BaseRegistryListener.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/route/BaseRegistryListener.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/route/BaseRegistryListener.java index 0eed415d..39ef7da9 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/route/BaseRegistryListener.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/route/BaseRegistryListener.java @@ -38,7 +38,7 @@ public abstract class BaseRegistryListener implements RegistryListener { * * @param serviceId serviceId */ - public void removeRoutes(String serviceId) { + public synchronized void removeRoutes(String serviceId) { serviceListener.onRemoveService(serviceId.toLowerCase()); } @@ -47,7 +47,7 @@ public abstract class BaseRegistryListener implements RegistryListener { * * @param instance 服务实例 */ - public void pullRoutes(InstanceDefinition instance) { + public synchronized void pullRoutes(InstanceDefinition instance) { // serviceId统一小写 instance.setServiceId(instance.getServiceId().toLowerCase()); serviceListener.onAddInstance(instance); From 4ba59e0ebeb08fe28a4ab22392a8eccc68d618aa Mon Sep 17 00:00:00 2001 From: tanghc Date: Tue, 21 Jan 2020 13:51:42 +0800 Subject: [PATCH 53/55] 3.0.0 --- sop-auth/pom.xml | 2 +- sop-common/pom.xml | 2 +- sop-common/sop-bridge-gateway/pom.xml | 6 +++--- sop-common/sop-bridge-zuul/pom.xml | 6 +++--- sop-common/sop-gateway-common/pom.xml | 4 ++-- sop-common/sop-service-common/pom.xml | 4 ++-- sop-example/sop-book/sop-book-web/pom.xml | 2 +- sop-example/sop-easyopen/pom.xml | 2 +- sop-example/sop-springmvc/pom.xml | 2 +- sop-example/sop-story/sop-story-web/pom.xml | 2 +- sop-gateway/pom.xml | 2 +- sop-website/pom.xml | 2 +- 12 files changed, 18 insertions(+), 18 deletions(-) diff --git a/sop-auth/pom.xml b/sop-auth/pom.xml index 06a0fc2c..113cfff8 100644 --- a/sop-auth/pom.xml +++ b/sop-auth/pom.xml @@ -26,7 +26,7 @@ com.gitee.sop sop-service-common - 2.6.0-SNAPSHOT + 3.0.0-SNAPSHOT diff --git a/sop-common/pom.xml b/sop-common/pom.xml index 89ff6588..3a464160 100644 --- a/sop-common/pom.xml +++ b/sop-common/pom.xml @@ -5,7 +5,7 @@ 4.0.0 com.gitee.sop sop-common - 2.6.0-SNAPSHOT + 3.0.0-SNAPSHOT pom diff --git a/sop-common/sop-bridge-gateway/pom.xml b/sop-common/sop-bridge-gateway/pom.xml index 95217036..aa776b53 100644 --- a/sop-common/sop-bridge-gateway/pom.xml +++ b/sop-common/sop-bridge-gateway/pom.xml @@ -5,11 +5,11 @@ sop-common com.gitee.sop - 2.6.0-SNAPSHOT + 3.0.0-SNAPSHOT ../pom.xml 4.0.0 - 2.6.0-SNAPSHOT + 3.0.0-SNAPSHOT sop-bridge-gateway @@ -17,7 +17,7 @@ com.gitee.sop sop-gateway-common - 2.6.0-SNAPSHOT + 3.0.0-SNAPSHOT diff --git a/sop-common/sop-bridge-zuul/pom.xml b/sop-common/sop-bridge-zuul/pom.xml index 9ed09852..723ce3d0 100644 --- a/sop-common/sop-bridge-zuul/pom.xml +++ b/sop-common/sop-bridge-zuul/pom.xml @@ -5,11 +5,11 @@ sop-common com.gitee.sop - 2.6.0-SNAPSHOT + 3.0.0-SNAPSHOT ../pom.xml 4.0.0 - 2.6.0-SNAPSHOT + 3.0.0-SNAPSHOT sop-bridge-zuul @@ -17,7 +17,7 @@ com.gitee.sop sop-gateway-common - 2.6.0-SNAPSHOT + 3.0.0-SNAPSHOT diff --git a/sop-common/sop-gateway-common/pom.xml b/sop-common/sop-gateway-common/pom.xml index 7c3e9b7f..040b57d8 100644 --- a/sop-common/sop-gateway-common/pom.xml +++ b/sop-common/sop-gateway-common/pom.xml @@ -5,11 +5,11 @@ com.gitee.sop sop-common - 2.6.0-SNAPSHOT + 3.0.0-SNAPSHOT ../pom.xml sop-gateway-common - 2.6.0-SNAPSHOT + 3.0.0-SNAPSHOT jar sop-gateway-common diff --git a/sop-common/sop-service-common/pom.xml b/sop-common/sop-service-common/pom.xml index 01a6fff7..e0558fc1 100644 --- a/sop-common/sop-service-common/pom.xml +++ b/sop-common/sop-service-common/pom.xml @@ -6,11 +6,11 @@ com.gitee.sop sop-common - 2.6.0-SNAPSHOT + 3.0.0-SNAPSHOT ../pom.xml sop-service-common - 2.6.0-SNAPSHOT + 3.0.0-SNAPSHOT jar sop-service-common diff --git a/sop-example/sop-book/sop-book-web/pom.xml b/sop-example/sop-book/sop-book-web/pom.xml index 335b4762..ffd1adc7 100644 --- a/sop-example/sop-book/sop-book-web/pom.xml +++ b/sop-example/sop-book/sop-book-web/pom.xml @@ -28,7 +28,7 @@ com.gitee.sop sop-service-common - 2.6.0-SNAPSHOT + 3.0.0-SNAPSHOT com.gitee.sop diff --git a/sop-example/sop-easyopen/pom.xml b/sop-example/sop-easyopen/pom.xml index b998dc17..8140f57a 100644 --- a/sop-example/sop-easyopen/pom.xml +++ b/sop-example/sop-easyopen/pom.xml @@ -29,7 +29,7 @@ com.gitee.sop sop-service-common - 2.6.0-SNAPSHOT + 3.0.0-SNAPSHOT diff --git a/sop-example/sop-story/sop-story-web/pom.xml b/sop-example/sop-story/sop-story-web/pom.xml index 0943327a..7b7c6ba6 100644 --- a/sop-example/sop-story/sop-story-web/pom.xml +++ b/sop-example/sop-story/sop-story-web/pom.xml @@ -28,7 +28,7 @@ com.gitee.sop sop-service-common - 2.6.0-SNAPSHOT + 3.0.0-SNAPSHOT com.gitee.sop diff --git a/sop-gateway/pom.xml b/sop-gateway/pom.xml index fb2d5b50..2b18e01e 100644 --- a/sop-gateway/pom.xml +++ b/sop-gateway/pom.xml @@ -34,7 +34,7 @@ com.gitee.sop sop-bridge-gateway - 2.6.0-SNAPSHOT + 3.0.0-SNAPSHOT diff --git a/sop-website/pom.xml b/sop-website/pom.xml index d949848f..fcbaaef5 100644 --- a/sop-website/pom.xml +++ b/sop-website/pom.xml @@ -35,7 +35,7 @@ com.gitee.sop sop-gateway-common - 2.6.0-SNAPSHOT + 3.0.0-SNAPSHOT From d7a089b1ca533c9e203d526025d237ddf7d1055d Mon Sep 17 00:00:00 2001 From: tanghc Date: Tue, 21 Jan 2020 14:09:38 +0800 Subject: [PATCH 54/55] 3.0.0 --- doc/docs/files/90999_网关性能测试.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/doc/docs/files/90999_网关性能测试.md b/doc/docs/files/90999_网关性能测试.md index 38c47d0e..f7046d37 100644 --- a/doc/docs/files/90999_网关性能测试.md +++ b/doc/docs/files/90999_网关性能测试.md @@ -7,9 +7,12 @@ - 测试工具:[wrk](https://github.com/wg/wrk),[安装教程](https://www.cnblogs.com/quanxiaoha/p/10661650.html) - 服务器:CentOS7(虚拟机,宿主机:macbookpro),内存:2G,CPU:1,核数:2核 - 运行环境:Java8、Mysql-5.7、Nacos-1.1.3 -- 运行参数:`-verbose:gc -XX:+PrintGCDetails -XX:+PrintHeapAtGC -Xloggc:gc-zuul.log \ +- 运行参数: +``` +-verbose:gc -XX:+PrintGCDetails -XX:+PrintHeapAtGC -Xloggc:gc-zuul.log \ -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=128m -Xms1024m -Xmx1024m -Xmn512m -Xss256k -XX:SurvivorRatio=8\ - -XX:+UseConcMarkSweepGC` + -XX:+UseConcMarkSweepGC +``` - zuul配置: From 5c0a635a646218dba19b529971fae9b3f49caa82 Mon Sep 17 00:00:00 2001 From: tanghc Date: Tue, 21 Jan 2020 14:10:54 +0800 Subject: [PATCH 55/55] 3.0.0 --- doc/docs/files/90999_网关性能测试.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/docs/files/90999_网关性能测试.md b/doc/docs/files/90999_网关性能测试.md index f7046d37..a262ab66 100644 --- a/doc/docs/files/90999_网关性能测试.md +++ b/doc/docs/files/90999_网关性能测试.md @@ -8,9 +8,10 @@ - 服务器:CentOS7(虚拟机,宿主机:macbookpro),内存:2G,CPU:1,核数:2核 - 运行环境:Java8、Mysql-5.7、Nacos-1.1.3 - 运行参数: + ``` -verbose:gc -XX:+PrintGCDetails -XX:+PrintHeapAtGC -Xloggc:gc-zuul.log \ - -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=128m -Xms1024m -Xmx1024m -Xmn512m -Xss256k -XX:SurvivorRatio=8\ + -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=128m -Xms1024m -Xmx1024m -Xmn512m -Xss256k -XX:SurvivorRatio=8 \ -XX:+UseConcMarkSweepGC ```