From fcf4b6362d27da95719e825fddf8658f3efeadb9 Mon Sep 17 00:00:00 2001 From: tanghc Date: Mon, 16 Sep 2019 15:57:41 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8F=AF=E8=87=AA=E5=AE=9A=E4=B9=89=E8=B7=AF?= =?UTF-8?q?=E7=94=B1=E6=8B=89=E5=8F=96url?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/docs/_sidebar.md | 60 +++++++------- doc/docs/files/10011_项目接入到SOP.md | 82 +++++++++++++++++++ .../gatewaycommon/bean/RouteDefinition.java | 5 +- .../gatewaycommon/bean/ServiceRouteInfo.java | 5 -- .../gateway/route/GatewayRouteCache.java | 14 ++++ .../gatewaycommon/manager/BaseRouteCache.java | 41 +++++++++- .../manager/ServiceRouteInfoBuilder.java | 34 +------- .../servercommon/route/ServiceRouteInfo.java | 5 -- 8 files changed, 169 insertions(+), 77 deletions(-) diff --git a/doc/docs/_sidebar.md b/doc/docs/_sidebar.md index b4b85507..af4a2aad 100644 --- a/doc/docs/_sidebar.md +++ b/doc/docs/_sidebar.md @@ -1,32 +1,32 @@ -* [首页](/?t=1567997064207) +* [首页](/?t=1568619386330) * 开发文档 - * [快速体验](files/10010_快速体验.md?t=1567997064209) - * [项目接入到SOP](files/10011_项目接入到SOP.md?t=1567997064227) - * [新增接口](files/10020_新增接口.md?t=1567997064227) - * [开发流程](files/10021_开发流程.md?t=1567997064227) - * [业务参数校验](files/10030_业务参数校验.md?t=1567997064227) - * [错误处理](files/10040_错误处理.md?t=1567997064227) - * [编写文档](files/10041_编写文档.md?t=1567997064227) - * [接口交互详解](files/10050_接口交互详解.md?t=1567997064227) - * [easyopen支持](files/10070_easyopen支持.md?t=1567997064227) - * [使用签名校验工具](files/10080_使用签名校验工具.md?t=1567997064227) - * [ISV管理](files/10085_ISV管理.md?t=1567997064227) - * [自定义返回结果](files/10087_自定义返回结果.md?t=1567997064227) - * [自定义过滤器](files/10088_自定义过滤器.md?t=1567997064228) - * [路由授权](files/10090_路由授权.md?t=1567997064228) - * [接口限流](files/10092_接口限流.md?t=1567997064228) - * [监控日志](files/10093_监控日志.md?t=1567997064228) - * [SDK开发](files/10095_SDK开发.md?t=1567997064228) - * [使用SpringCloudGateway](files/10096_使用SpringCloudGateway.md?t=1567997064228) - * [应用授权](files/10097_应用授权.md?t=1567997064228) - * [传统web开发](files/10100_传统web开发.md?t=1567997064228) - * [文件上传](files/10104_文件上传.md?t=1567997064228) - * [配置Sleuth链路追踪](files/10109_配置Sleuth链路追踪.md?t=1567997064228) - * [预发布灰度发布](files/10110_预发布灰度发布.md?t=1567997064228) - * [动态修改请求参数](files/10111_动态修改请求参数.md?t=1567997064228) + * [快速体验](files/10010_快速体验.md?t=1568619386330) + * [项目接入到SOP](files/10011_项目接入到SOP.md?t=1568619386355) + * [新增接口](files/10020_新增接口.md?t=1568619386355) + * [开发流程](files/10021_开发流程.md?t=1568619386355) + * [业务参数校验](files/10030_业务参数校验.md?t=1568619386355) + * [错误处理](files/10040_错误处理.md?t=1568619386355) + * [编写文档](files/10041_编写文档.md?t=1568619386355) + * [接口交互详解](files/10050_接口交互详解.md?t=1568619386356) + * [easyopen支持](files/10070_easyopen支持.md?t=1568619386356) + * [使用签名校验工具](files/10080_使用签名校验工具.md?t=1568619386356) + * [ISV管理](files/10085_ISV管理.md?t=1568619386356) + * [自定义返回结果](files/10087_自定义返回结果.md?t=1568619386356) + * [自定义过滤器](files/10088_自定义过滤器.md?t=1568619386356) + * [路由授权](files/10090_路由授权.md?t=1568619386356) + * [接口限流](files/10092_接口限流.md?t=1568619386357) + * [监控日志](files/10093_监控日志.md?t=1568619386357) + * [SDK开发](files/10095_SDK开发.md?t=1568619386357) + * [使用SpringCloudGateway](files/10096_使用SpringCloudGateway.md?t=1568619386357) + * [应用授权](files/10097_应用授权.md?t=1568619386357) + * [传统web开发](files/10100_传统web开发.md?t=1568619386357) + * [文件上传](files/10104_文件上传.md?t=1568619386358) + * [配置Sleuth链路追踪](files/10109_配置Sleuth链路追踪.md?t=1568619386358) + * [预发布灰度发布](files/10110_预发布灰度发布.md?t=1568619386358) + * [动态修改请求参数](files/10111_动态修改请求参数.md?t=1568619386358) * 原理分析 - * [原理分析之@ApiMapping](files/90010_原理分析之@ApiMapping.md?t=1567997064229) - * [原理分析之如何存储路由](files/90011_原理分析之如何存储路由.md?t=1567997064229) - * [原理分析之如何路由](files/90012_原理分析之如何路由.md?t=1567997064229) - * [原理分析之文档归纳](files/90013_原理分析之文档归纳.md?t=1567997064229) - * [常见问题](files/90100_常见问题.md?t=1567997064229) + * [原理分析之@ApiMapping](files/90010_原理分析之@ApiMapping.md?t=1568619386358) + * [原理分析之如何存储路由](files/90011_原理分析之如何存储路由.md?t=1568619386358) + * [原理分析之如何路由](files/90012_原理分析之如何路由.md?t=1568619386358) + * [原理分析之文档归纳](files/90013_原理分析之文档归纳.md?t=1568619386358) + * [常见问题](files/90100_常见问题.md?t=1568619386358) diff --git a/doc/docs/files/10011_项目接入到SOP.md b/doc/docs/files/10011_项目接入到SOP.md index b0634c0c..b14adbc6 100644 --- a/doc/docs/files/10011_项目接入到SOP.md +++ b/doc/docs/files/10011_项目接入到SOP.md @@ -78,3 +78,85 @@ public class OpenServiceConfig extends AlipayServiceConfiguration { ``` 到此准备工作就完成了,接下来可前往`新增接口`查看如何新增接口。 + +## 非Java项目接入 + +如果是非Java项目接入,如php,需要做到以下几点: + +1. 提供路由配置接口 +2. 服务注册到nacos,并在nacos的metadata中指定接口路径,metadata的key为:`sop.routes.path` + +- 提供路由配置接口 + +php应用提供的接口需要返回如下json内容: + +```json +{ + "serviceId": "story-service", + "createTime": 1568603471646, + "updateTime": 1568603471646, + "description": null, + "routeDefinitionList": [ + { + "id": "alipay.category.get1.0", + "name": "alipay.category.get", + "version": "1.0", + "uri": "lb://story-service", + "path": "/alipay.category.get/", + "order": 0, + "ignoreValidate": 0, + "status": 1, + "mergeResult": 1, + "permission": 0 + }, + ... + ] +} +``` + +json参数说明 + +|参数名|是否必填|说明| +|:----|:----|:----| +|serviceId |是|serviceId,服务id | +|createTime |是|创建时间,Unix timestamp,毫秒 | +|updateTime |是|修改时间,Unix timestamp,毫秒 | +|description|否|描述| +|routeDefinitionList元素参数说明|是|路由配置,见:routeDefinitionList元素参数说明| + +routeDefinitionList元素参数说明 + +|参数名|是否必填|说明| +|:----|:----|:----| +|id |是|路由id,全局唯一,格式:接口名+版本号 | +|name|是|接口名称| +|version|是|版本号| +|uri|是|格式:lb:// + serviceId,如:lb://order-service| +|path|是|接口path,填端口号后面的path,如你的接口为http://open.domain.com:8080/goods/list_goods,填:/goods/list_goods| +|order|是|固定填:0| +|ignoreValidate|是|忽略签名验证,1:是,0:否| +|status|是|启用状态,1:启用,2:禁用| +|mergeResult|是|是否统一返回结果,1:是,0:否| +|permission|是|是否需要权限访问,1:是,0:否| + +- 服务注册到nacos + +可前往nacos官网,参考[open-api](https://nacos.io/zh-cn/docs/open-api.html),使用nacos提供的接口完成服务注册 + + +- 在nacos的metadata中指定接口路径 + +伪代码如下: + +```java +Instance instance = new Instance(); +instance.setServiceName("order-service"); +instance.setIp("192.168.0.11"); +instance.setPort(8080); +// 在nacos的metadata中指定接口路径 +instance.getMetadata().put("sop.routes.path", "/goods/list_goods"); + +namingService.registerInstance(serviceId, instance); +``` + +完成以上步骤后,php服务注册到nacos,网关会触发监听事件,获取新注册的服务,然后会向你的服务拉取路由配置。 \ No newline at end of file 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 73cac867..8cfd257d 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 @@ -3,6 +3,7 @@ package com.gitee.sop.gatewaycommon.bean; import lombok.Data; import java.util.ArrayList; +import java.util.Collections; import java.util.List; /** @@ -28,12 +29,12 @@ public class RouteDefinition { /** * 路由断言集合配置 */ - private List predicates = new ArrayList<>(); + private List predicates = Collections.emptyList(); /** * 路由过滤器集合配置 */ - private List filters = new ArrayList<>(); + private List filters = Collections.emptyList(); /** * 路由规则转发的目标uri diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/ServiceRouteInfo.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/ServiceRouteInfo.java index 6114d98d..6c817512 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/ServiceRouteInfo.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/ServiceRouteInfo.java @@ -25,11 +25,6 @@ public class ServiceRouteInfo { private String description; - /** - * 路由信息md5,md5(sort(routeIdList)) - */ - private String md5; - private List routeDefinitionList; public String fetchServiceIdLowerCase() { diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/route/GatewayRouteCache.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/route/GatewayRouteCache.java index 3d0ada69..5589d7bc 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/route/GatewayRouteCache.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/route/GatewayRouteCache.java @@ -9,6 +9,7 @@ import org.springframework.cloud.gateway.filter.FilterDefinition; import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition; import java.net.URI; +import java.util.Collections; import java.util.LinkedList; import java.util.List; import java.util.stream.Collectors; @@ -59,4 +60,17 @@ public class GatewayRouteCache extends BaseRouteCache { 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.setOrder(Integer.MIN_VALUE); + + return Collections.singletonList(routeDefinition); + } } 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 4160f5dd..e2dbddd1 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,18 @@ 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; import java.util.Objects; import java.util.function.Consumer; +import java.util.stream.Collectors; /** * @author tanghc @@ -42,14 +48,22 @@ public abstract class BaseRouteCache implements RouteLoad public void load(ServiceRouteInfo serviceRouteInfo, Consumer callback) { try { String serviceId = serviceRouteInfo.getServiceId(); - String newMd5 = serviceRouteInfo.getMd5(); + String newMd5 = buildMd5(serviceRouteInfo.getRouteDefinitionList()); String oldMd5 = serviceIdMd5Map.get(serviceId); if (Objects.equals(newMd5, oldMd5)) { return; } serviceIdMd5Map.put(serviceId, newMd5); + + List extRouteDefinitionList = this.getExtRouteDefinitionList(serviceRouteInfo); List routeDefinitionList = serviceRouteInfo.getRouteDefinitionList(); - for (RouteDefinition routeDefinition : routeDefinitionList) { + 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) { T targetRoute = this.buildTargetRoute(serviceRouteInfo, routeDefinition); routeRepository.add(targetRoute); if (log.isDebugEnabled()) { @@ -62,6 +76,29 @@ public abstract class BaseRouteCache implements RouteLoad } } + /** + * 构建路由id MD5 + * + * @param routeDefinitionList 路由列表 + * @return 返回MD5 + */ + private String buildMd5(List routeDefinitionList) { + List routeIdList = routeDefinitionList.stream() + .map(JSON::toJSONString) + .sorted() + .collect(Collectors.toList()); + String md5Source = org.apache.commons.lang3.StringUtils.join(routeIdList, ""); + 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-service-common/src/main/java/com/gitee/sop/servercommon/manager/ServiceRouteInfoBuilder.java b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/manager/ServiceRouteInfoBuilder.java index 27d1b453..9a68b0a2 100644 --- a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/manager/ServiceRouteInfoBuilder.java +++ b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/manager/ServiceRouteInfoBuilder.java @@ -8,7 +8,6 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.BeanUtils; import org.springframework.core.env.Environment; import org.springframework.util.DigestUtils; -import org.springframework.util.StringUtils; import java.nio.charset.StandardCharsets; import java.util.ArrayList; @@ -31,8 +30,6 @@ public class ServiceRouteInfoBuilder { private static final String DEFAULT_CONTEXT_PATH = "/"; - private static ServiceApiInfo.ApiMeta FIRST_API_META = new ServiceApiInfo.ApiMeta("_first_route_", "/", "1.0.0"); - private Environment environment; public ServiceRouteInfoBuilder(Environment environment) { @@ -51,9 +48,7 @@ public class ServiceRouteInfoBuilder { */ protected ServiceRouteInfo buildServiceGatewayInfo(ServiceApiInfo serviceApiInfo) { List apis = serviceApiInfo.getApis(); - List routeDefinitionList = new ArrayList<>(apis.size() + 1); - // 在第一个位置放一个没用的路由,SpringCloudGateway会从第二个路由开始找,原因不详 - routeDefinitionList.add(this.getFirstRoute(serviceApiInfo)); + List routeDefinitionList = new ArrayList<>(apis.size()); for (ServiceApiInfo.ApiMeta apiMeta : apis) { RouteDefinition gatewayRouteDefinition = this.buildGatewayRouteDefinition(serviceApiInfo, apiMeta); routeDefinitionList.add(gatewayRouteDefinition); @@ -61,36 +56,9 @@ public class ServiceRouteInfoBuilder { ServiceRouteInfo serviceRouteInfo = new ServiceRouteInfo(); serviceRouteInfo.setServiceId(serviceApiInfo.getServiceId()); serviceRouteInfo.setRouteDefinitionList(routeDefinitionList); - String md5 = buildMd5(routeDefinitionList); - serviceRouteInfo.setMd5(md5); return serviceRouteInfo; } - /** - * 添加com.gitee.sop.gatewaycommon.routeDefinition.ReadBodyRoutePredicateFactory,解决form表单获取不到问题 - * - * @return 返回路由定义 - */ - protected RouteDefinition getFirstRoute(ServiceApiInfo serviceApiInfo) { - RouteDefinition firstRoute = this.buildGatewayRouteDefinition(serviceApiInfo, FIRST_API_META); - firstRoute.setOrder(Integer.MIN_VALUE); - return firstRoute; - } - - /** - * 构建路由id MD5 - * - * @param routeDefinitionList 路由列表 - * @return 返回MD5 - */ - protected String buildMd5(List routeDefinitionList) { - List routeIdList = routeDefinitionList.stream() - .map(JSON::toJSONString) - .sorted() - .collect(Collectors.toList()); - String md5Source = org.apache.commons.lang3.StringUtils.join(routeIdList, ""); - return DigestUtils.md5DigestAsHex(md5Source.getBytes(StandardCharsets.UTF_8)); - } protected RouteDefinition buildGatewayRouteDefinition(ServiceApiInfo serviceApiInfo, ServiceApiInfo.ApiMeta apiMeta) { RouteDefinition routeDefinition = new RouteDefinition(); diff --git a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/route/ServiceRouteInfo.java b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/route/ServiceRouteInfo.java index 94371d47..19937466 100644 --- a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/route/ServiceRouteInfo.java +++ b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/route/ServiceRouteInfo.java @@ -25,11 +25,6 @@ public class ServiceRouteInfo { private String description; - /** - * 路由信息md5,md5(sort(routeIdList)) - */ - private String md5; - @JSONField(serialize = false) private List routeDefinitionList;