diff --git a/doc/docs/_sidebar.md b/doc/docs/_sidebar.md index c18e4b3a..63118b5d 100644 --- a/doc/docs/_sidebar.md +++ b/doc/docs/_sidebar.md @@ -1,29 +1,30 @@ -* [首页](/?t=1561689549009) +* [首页](/?t=1561970396914) * 开发文档 - * [快速体验](files/10010_快速体验.md?t=1561689549011) - * [项目接入到SOP](files/10011_项目接入到SOP.md?t=1561689549027) - * [新增接口](files/10020_新增接口.md?t=1561689549027) - * [业务参数校验](files/10030_业务参数校验.md?t=1561689549028) - * [错误处理](files/10040_错误处理.md?t=1561689549028) - * [编写文档](files/10041_编写文档.md?t=1561689549028) - * [接口交互详解](files/10050_接口交互详解.md?t=1561689549028) - * [easyopen支持](files/10070_easyopen支持.md?t=1561689549028) - * [使用签名校验工具](files/10080_使用签名校验工具.md?t=1561689549028) - * [ISV管理](files/10085_ISV管理.md?t=1561689549028) - * [自定义路由](files/10086_自定义路由.md?t=1561689549028) - * [路由授权](files/10090_路由授权.md?t=1561689549028) - * [接口限流](files/10092_接口限流.md?t=1561689549029) - * [监控日志](files/10093_监控日志.md?t=1561689549029) - * [SDK开发](files/10095_SDK开发.md?t=1561689549029) - * [使用SpringCloudGateway](files/10096_使用SpringCloudGateway.md?t=1561689549029) - * [应用授权](files/10097_应用授权.md?t=1561689549029) - * [更改数据节点名称](files/10099_更改数据节点名称.md?t=1561689549029) - * [对接前端](files/10100_对接前端.md?t=1561689549029) - * [自定义过滤器](files/10102_自定义过滤器.md?t=1561689549029) - * [文件上传](files/10104_文件上传.md?t=1561689549029) + * [快速体验](files/10010_快速体验.md?t=1561970396914) + * [项目接入到SOP](files/10011_项目接入到SOP.md?t=1561970396931) + * [新增接口](files/10020_新增接口.md?t=1561970396931) + * [业务参数校验](files/10030_业务参数校验.md?t=1561970396931) + * [错误处理](files/10040_错误处理.md?t=1561970396931) + * [编写文档](files/10041_编写文档.md?t=1561970396931) + * [接口交互详解](files/10050_接口交互详解.md?t=1561970396931) + * [easyopen支持](files/10070_easyopen支持.md?t=1561970396932) + * [使用签名校验工具](files/10080_使用签名校验工具.md?t=1561970396932) + * [ISV管理](files/10085_ISV管理.md?t=1561970396932) + * [自定义路由](files/10086_自定义路由.md?t=1561970396932) + * [路由授权](files/10090_路由授权.md?t=1561970396932) + * [接口限流](files/10092_接口限流.md?t=1561970396932) + * [监控日志](files/10093_监控日志.md?t=1561970396932) + * [SDK开发](files/10095_SDK开发.md?t=1561970396932) + * [使用SpringCloudGateway](files/10096_使用SpringCloudGateway.md?t=1561970396932) + * [应用授权](files/10097_应用授权.md?t=1561970396932) + * [更改数据节点名称](files/10099_更改数据节点名称.md?t=1561970396932) + * [对接前端](files/10100_对接前端.md?t=1561970396933) + * [自定义过滤器](files/10102_自定义过滤器.md?t=1561970396933) + * [文件上传](files/10104_文件上传.md?t=1561970396933) + * [nacos注册中心](files/10106_nacos注册中心.md?t=1561970396933) * 原理分析 - * [原理分析之@ApiMapping](files/90010_原理分析之@ApiMapping.md?t=1561689549029) - * [原理分析之路由存储](files/90011_原理分析之路由存储.md?t=1561689549030) - * [原理分析之如何路由](files/90012_原理分析之如何路由.md?t=1561689549030) - * [原理分析之文档归纳](files/90013_原理分析之文档归纳.md?t=1561689549030) - * [常见问题](files/90100_常见问题.md?t=1561689549030) + * [原理分析之@ApiMapping](files/90010_原理分析之@ApiMapping.md?t=1561970396933) + * [原理分析之路由存储](files/90011_原理分析之路由存储.md?t=1561970396933) + * [原理分析之如何路由](files/90012_原理分析之如何路由.md?t=1561970396933) + * [原理分析之文档归纳](files/90013_原理分析之文档归纳.md?t=1561970396933) + * [常见问题](files/90100_常见问题.md?t=1561970396933) diff --git a/doc/docs/files/10106_nacos注册中心.md b/doc/docs/files/10106_nacos注册中心.md new file mode 100644 index 00000000..a06a4f5a --- /dev/null +++ b/doc/docs/files/10106_nacos注册中心.md @@ -0,0 +1,113 @@ +# nacos注册中心 + +完整代码在`registry-nacos`分支 + +SOP默认使用eureka注册中心,如果要换成nacos注册中心,步骤如下: + +- 实现`com.gitee.sop.registryapi.service.RegistryService`接口 + +1.找到`SOP/sop-common/sop-registry-api`工程,在service.impl包下新建一个类,实现RegistryService接口 + +```java +public class RegistryServiceNacos implements RegistryService { + + @Override + public List listAllService(int pageNo, int pageSize) throws Exception { + // TODO: 返回服务实例 + } + + @Override + public void onlineInstance(ServiceInstance serviceInstance) throws Exception { + // TODO: 实例上线 + } + + @Override + public void offlineInstance(ServiceInstance serviceInstance) throws Exception { + // TODO: 实例下线 + } +} +``` + +2.在`com.gitee.sop.registryapi.config.BaseRegistryConfig`中新增 + +```java +/** + * 当配置了registry.name=nacos生效 + * + * @return + */ +@Bean +@ConditionalOnProperty(prefix = "registry", name = "name", havingValue = "nacos") +RegistryService registryServiceNacos() { + return new RegistryServiceNacos(); +} +``` + +其中`@ConditionalOnProperty(prefix = "registry", name = "name", havingValue = "nacos")` +表示`application.properties`配置了`registry.name=nacos`参数才能生效,registry.name=nacos下文会讲到。 + + +- 微服务端修改 + +1.修改微服务应用pom.xml,注释eureka服务发现依赖,添加nacos服务发现依赖 + +```xml + + + + + + org.springframework.cloud + spring-cloud-starter-alibaba-nacos-discovery + 0.2.2.RELEASE + + +``` + +2.yml文件新增nacos配置,并注释掉eureka相关配置 + +```yaml +spring: + cloud: + # nacos注册中心,和eureka只能用一个 + nacos: + discovery: + server-addr: 127.0.0.1:8848 +``` + +- 网关修改 + +找到`sop-gateway`工程,步骤同上 + +- SOP-admin修改 + + +修改yml文件,新增nacos服务器地址,`registry.name`填nacos + +```yaml +# 注册中心地址,根据实际情况改,这里只是参数,并不会去注册 +registry: + # 使用哪个配置中心,使用eureka,填eureka;使用nacos填nacos + name: nacos + eureka-server-addr: http://localhost:1111/eureka/ + nacos-server-addr: 127.0.0.1:8848 +``` + +- website-server修改 + +步骤同`SOP-admin修改` + +如果要改成consul注册中心,可参照以上步骤。 + +- 参考资料 + +1.[nacos介绍及安装](https://nacos.io/zh-cn/docs/quick-start.html) +2.[nacos spring cloud注册发现](https://nacos.io/zh-cn/docs/quick-start-spring-cloud.html) diff --git a/sop-admin/sop-admin-server/pom.xml b/sop-admin/sop-admin-server/pom.xml index 6ddcf87f..97c43720 100644 --- a/sop-admin/sop-admin-server/pom.xml +++ b/sop-admin/sop-admin-server/pom.xml @@ -13,7 +13,7 @@ org.springframework.boot spring-boot-starter-parent - 2.0.3.RELEASE + 2.1.4.RELEASE @@ -27,12 +27,12 @@ - + sop-registry-api + 1.11.0-SNAPSHOT + + net.oschina.durcframework @@ -78,12 +78,6 @@ - - com.squareup.okhttp3 - okhttp - ${okhttp.version} - - org.springframework.boot spring-boot-starter-web @@ -109,6 +103,12 @@ 1.18.4 provided + + org.springframework.cloud + spring-cloud-commons + 2.1.0.RELEASE + compile + diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/ServiceApi.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/ServiceApi.java index cdf2ba86..05f6c147 100644 --- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/ServiceApi.java +++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/ServiceApi.java @@ -10,22 +10,21 @@ import com.gitee.sop.adminserver.api.service.param.ServiceSearchParam; import com.gitee.sop.adminserver.api.service.result.RouteServiceInfo; import com.gitee.sop.adminserver.api.service.result.ServiceInfoVo; import com.gitee.sop.adminserver.api.service.result.ServiceInstanceVO; -import com.gitee.sop.adminserver.bean.ServiceInfo; -import com.gitee.sop.adminserver.bean.ServiceInstance; import com.gitee.sop.adminserver.bean.ServiceRouteInfo; import com.gitee.sop.adminserver.bean.ZookeeperContext; import com.gitee.sop.adminserver.common.BizException; import com.gitee.sop.adminserver.common.ZookeeperPathExistException; import com.gitee.sop.adminserver.common.ZookeeperPathNotExistException; -import com.gitee.sop.adminserver.service.RegistrationService; -import com.gitee.sop.adminserver.service.impl.RegistrationServiceEureka; +import com.gitee.sop.registryapi.bean.ServiceInfo; +import com.gitee.sop.registryapi.bean.ServiceInstance; +import com.gitee.sop.registryapi.service.RegistryService; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang.BooleanUtils; import org.apache.commons.lang.StringUtils; import org.apache.curator.framework.recipes.cache.ChildData; import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; -import javax.annotation.Resource; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; @@ -42,8 +41,8 @@ import java.util.stream.Collectors; @Slf4j public class ServiceApi { - @Resource(type = RegistrationServiceEureka.class) - private RegistrationService registrationService; + @Autowired + private RegistryService registryService; @Api(name = "zookeeper.service.list") @ApiDocMethod(description = "zk中的服务列表", elementClass = RouteServiceInfo.class) @@ -113,10 +112,10 @@ public class ServiceApi { @Api(name = "service.instance.list") @ApiDocMethod(description = "获取注册中心的服务列表", elementClass = ServiceInfoVo.class) - List listService(ServiceSearchParam param) { + List listService(ServiceSearchParam param) { List serviceInfos; try { - serviceInfos = registrationService.listAllService(1, 99999/* 获取所有实例 */); + serviceInfos = registryService.listAllService(1, 99999/* 获取所有实例 */); } catch (Exception e) { log.error("获取服务实例失败", e); return Collections.emptyList(); @@ -156,7 +155,7 @@ public class ServiceApi { @ApiDocMethod(description = "服务下线") void serviceOffline(ServiceInstance param) { try { - registrationService.offlineInstance(param); + registryService.offlineInstance(param); } catch (Exception e) { log.error("下线失败,param:{}", param, e); throw new BizException("下线失败,请查看日志"); @@ -167,7 +166,7 @@ public class ServiceApi { @ApiDocMethod(description = "服务上线") void serviceOnline(ServiceInstance param) throws IOException { try { - registrationService.onlineInstance(param); + registryService.onlineInstance(param); } catch (Exception e) { log.error("上线失败,param:{}", param, e); throw new BizException("上线失败,请查看日志"); diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/result/ServiceInstanceVO.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/result/ServiceInstanceVO.java index 86656dd3..e7280367 100644 --- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/result/ServiceInstanceVO.java +++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/result/ServiceInstanceVO.java @@ -24,6 +24,12 @@ public class ServiceInstanceVO { @ApiDocField(description = "ipPort") private String ipPort; + @ApiDocField(description = "ip") + private String ip; + + @ApiDocField(description = "port") + private int port; + @ApiDocField(description = "status,服务状态,UP:已上线,OUT_OF_SERVICE:已下线") private String status; @@ -41,4 +47,8 @@ public class ServiceInstanceVO { return new Date(Long.valueOf(lastUpdatedTimestamp)); } + public String getIpPort() { + return ip != null && port > 0 ? ip + ":" + port : ""; + } + } diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/config/RegistryConfig.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/config/RegistryConfig.java new file mode 100644 index 00000000..57b9e819 --- /dev/null +++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/config/RegistryConfig.java @@ -0,0 +1,12 @@ +package com.gitee.sop.adminserver.config; + +import com.gitee.sop.registryapi.config.BaseRegistryConfig; +import org.springframework.context.annotation.Configuration; + +/** + * @author tanghc + */ +@Configuration +public class RegistryConfig extends BaseRegistryConfig { + +} diff --git a/sop-admin/sop-admin-server/src/main/resources/application-dev.yml b/sop-admin/sop-admin-server/src/main/resources/application-dev.yml index bd7864c9..af585325 100644 --- a/sop-admin/sop-admin-server/src/main/resources/application-dev.yml +++ b/sop-admin/sop-admin-server/src/main/resources/application-dev.yml @@ -12,6 +12,8 @@ spring: name: sop-admin cloud: + + # zookeeper地址,根据实际情况修改 zookeeper: connect-string: localhost:2181 baseSleepTimeMs: 3000 @@ -31,12 +33,12 @@ easyopen: ignore-validate: true # 注册中心地址,根据实际情况改,这里只是参数,并不会去注册 -eureka: - port: 1111 - host: localhost - client: - serviceUrl: - defaultZone: http://${eureka.host}:${eureka.port}/eureka/ +registry: + eureka-server-addr: http://localhost:1111/eureka/ + nacos-server-addr: 127.0.0.1:8848 + # 使用哪个配置中心,使用eureka,填eureka;使用nacos填nacos + name: nacos + # 根据实际情况改 logging: diff --git a/sop-common/pom.xml b/sop-common/pom.xml index a906e604..3a5a7675 100644 --- a/sop-common/pom.xml +++ b/sop-common/pom.xml @@ -37,7 +37,8 @@ sop-gateway-common sop-service-common - + sop-registry-api + diff --git a/sop-common/readme.md b/sop-common/readme.md index 2db2642a..293c40bc 100644 --- a/sop-common/readme.md +++ b/sop-common/readme.md @@ -1,8 +1,11 @@ # sop-common - sop-gateway-common:提供给网关使用 +- sop-registry-api:注册中心API - sop-service-common:提供给微服务端使用,需要打成jar +正式开发请将这些模块上传的maven私服 + - 打包成jar:`mvn clean package` - 上传到本机仓库:`mvn clean install` - 上传到maven私服:`mvn clean deploy` \ No newline at end of file diff --git a/sop-common/sop-gateway-common/readme.md b/sop-common/sop-gateway-common/readme.md index 05c58128..3bcf9b86 100644 --- a/sop-common/sop-gateway-common/readme.md +++ b/sop-common/sop-gateway-common/readme.md @@ -1,3 +1,3 @@ # sop-gateway-common -zuul通用组件,主要封装网关的一些功能。 +网关通用组件,主要封装网关的一些功能。 diff --git a/sop-common/sop-registry-api/pom.xml b/sop-common/sop-registry-api/pom.xml new file mode 100644 index 00000000..3a46bfea --- /dev/null +++ b/sop-common/sop-registry-api/pom.xml @@ -0,0 +1,74 @@ + + + + 4.0.0 + com.gitee.sop + sop-registry-api + 1.11.0-SNAPSHOT + + + UTF-8 + UTF-8 + 1.8 + 3.11.0 + + + + + com.squareup.okhttp3 + okhttp + ${okhttp.version} + + + + + com.alibaba.nacos + nacos-client + 1.0.1 + + + + org.springframework + spring-context + 5.1.6.RELEASE + true + + + org.projectlombok + lombok + 1.18.6 + true + + + org.springframework.boot + spring-boot-autoconfigure + 2.1.4.RELEASE + true + + + + junit + junit + 4.11 + test + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.1 + + ${java.version} + ${java.version} + UTF-8 + + + + + + diff --git a/sop-common/sop-registry-api/readme.md b/sop-common/sop-registry-api/readme.md new file mode 100644 index 00000000..8c55f465 --- /dev/null +++ b/sop-common/sop-registry-api/readme.md @@ -0,0 +1,3 @@ +# sop-registry-api + +统一各注册中心接口 \ No newline at end of file diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/EurekaApplication.java b/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/bean/EurekaApplication.java similarity index 81% rename from sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/EurekaApplication.java rename to sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/bean/EurekaApplication.java index 91d73122..21fdcb3d 100644 --- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/EurekaApplication.java +++ b/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/bean/EurekaApplication.java @@ -1,4 +1,4 @@ -package com.gitee.sop.adminserver.bean; +package com.gitee.sop.registryapi.bean; import lombok.Data; diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/EurekaApplications.java b/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/bean/EurekaApplications.java similarity index 80% rename from sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/EurekaApplications.java rename to sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/bean/EurekaApplications.java index 7dc08e21..7baa0fbf 100644 --- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/EurekaApplications.java +++ b/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/bean/EurekaApplications.java @@ -1,4 +1,4 @@ -package com.gitee.sop.adminserver.bean; +package com.gitee.sop.registryapi.bean; import lombok.Data; diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/EurekaApps.java b/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/bean/EurekaApps.java similarity index 76% rename from sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/EurekaApps.java rename to sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/bean/EurekaApps.java index f52440d2..653e7e64 100644 --- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/EurekaApps.java +++ b/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/bean/EurekaApps.java @@ -1,4 +1,4 @@ -package com.gitee.sop.adminserver.bean; +package com.gitee.sop.registryapi.bean; import lombok.Data; diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/EurekaInstance.java b/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/bean/EurekaInstance.java similarity index 93% rename from sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/EurekaInstance.java rename to sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/bean/EurekaInstance.java index acc37d9c..60cddf34 100644 --- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/EurekaInstance.java +++ b/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/bean/EurekaInstance.java @@ -1,4 +1,4 @@ -package com.gitee.sop.adminserver.bean; +package com.gitee.sop.registryapi.bean; import lombok.Data; import org.springframework.util.CollectionUtils; diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/EurekaUri.java b/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/bean/EurekaUri.java similarity index 64% rename from sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/EurekaUri.java rename to sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/bean/EurekaUri.java index 5f70f86b..1d7b39e8 100644 --- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/EurekaUri.java +++ b/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/bean/EurekaUri.java @@ -1,11 +1,9 @@ -package com.gitee.sop.adminserver.bean; +package com.gitee.sop.registryapi.bean; import okhttp3.MediaType; import okhttp3.Request; import okhttp3.RequestBody; import okhttp3.internal.http.HttpMethod; -import org.apache.commons.lang.ArrayUtils; -import org.springframework.web.bind.annotation.RequestMethod; /** * https://github.com/Netflix/eureka/wiki/Eureka-REST-operations @@ -17,22 +15,22 @@ public enum EurekaUri { /** * 查询所有实例 Query for all instances */ - QUERY_APPS(RequestMethod.GET, "/apps"), + QUERY_APPS("GET", "/apps"), /** * 下线 Take instance out of service */ - OFFLINE_SERVICE(RequestMethod.PUT, "/apps/%s/%s/status?value=OUT_OF_SERVICE"), + OFFLINE_SERVICE("PUT", "/apps/%s/%s/status?value=OUT_OF_SERVICE"), /** * 上线 Move instance back into service (remove override) */ - ONLINE_SERVICE(RequestMethod.DELETE, "/apps/%s/%s/status?value=UP"), + ONLINE_SERVICE("DELETE", "/apps/%s/%s/status?value=UP"), ; public static final String URL_PREFIX = "/"; String uri; - RequestMethod requestMethod; + String requestMethod; - EurekaUri(RequestMethod httpMethod, String uri) { + EurekaUri(String httpMethod, String uri) { if (!uri.startsWith(URL_PREFIX)) { uri = "/" + uri; } @@ -41,10 +39,13 @@ public enum EurekaUri { } public String getUri(String... args) { - if (ArrayUtils.isEmpty(args)) { + if (args == null || args.length == 0) { return uri; } - Object[] param = ArrayUtils.clone(args); + Object[] param = new Object[args.length]; + for (int i = 0; i < args.length; i++) { + param[i] = args[i]; + } return String.format(uri, param); } @@ -59,12 +60,12 @@ public enum EurekaUri { } public Request.Builder getBuilder() { - String method = requestMethod.name(); + String method = requestMethod; RequestBody requestBody = null; if (HttpMethod.requiresRequestBody(method)) { - MediaType contentType = MediaType.parse(org.springframework.http.MediaType.APPLICATION_JSON_VALUE); + MediaType contentType = MediaType.parse("application/json"); requestBody = RequestBody.create(contentType, "{}"); } - return new Request.Builder().method(requestMethod.name(), requestBody); + return new Request.Builder().method(requestMethod, requestBody); } } diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/ServiceInfo.java b/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/bean/ServiceInfo.java similarity index 52% rename from sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/ServiceInfo.java rename to sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/bean/ServiceInfo.java index 5344a601..2d19dd58 100644 --- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/ServiceInfo.java +++ b/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/bean/ServiceInfo.java @@ -1,6 +1,7 @@ -package com.gitee.sop.adminserver.bean; +package com.gitee.sop.registryapi.bean; -import lombok.Data; +import lombok.Getter; +import lombok.Setter; import java.util.Collections; import java.util.List; @@ -8,10 +9,16 @@ import java.util.List; /** * @author tanghc */ -@Data +@Getter +@Setter public class ServiceInfo { /** 服务名称 */ private String serviceId; /** 实例列表 */ private List instances = Collections.emptyList(); + + @Override + public String toString() { + return "服务名称: " + serviceId + ", 实例数:" + instances.size(); + } } diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/ServiceInstance.java b/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/bean/ServiceInstance.java similarity index 56% rename from sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/ServiceInstance.java rename to sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/bean/ServiceInstance.java index 42e8f865..9017dbaa 100644 --- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/ServiceInstance.java +++ b/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/bean/ServiceInstance.java @@ -1,4 +1,4 @@ -package com.gitee.sop.adminserver.bean; +package com.gitee.sop.registryapi.bean; import lombok.Data; @@ -15,12 +15,18 @@ public class ServiceInstance { private String serviceId; /** - * IP 端口 + * ip */ - private String ipPort; + private String ip; /** - * 状态,1:上线,2:下线 + * port + */ + private int port; + + /** + * 服务状态,UP:已上线,OUT_OF_SERVICE:已下线 */ private String status; + } \ No newline at end of file diff --git a/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/config/BaseRegistryConfig.java b/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/config/BaseRegistryConfig.java new file mode 100644 index 00000000..047eb03d --- /dev/null +++ b/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/config/BaseRegistryConfig.java @@ -0,0 +1,36 @@ +package com.gitee.sop.registryapi.config; + +import com.gitee.sop.registryapi.service.RegistryService; +import com.gitee.sop.registryapi.service.impl.RegistryServiceEureka; +import com.gitee.sop.registryapi.service.impl.RegistryServiceNacos; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; + +/** + * @author tanghc + */ +public class BaseRegistryConfig { + + /** + * 当配置了registry.name=eureka生效 + * + * @return + */ + @Bean + @ConditionalOnProperty(prefix = "registry", name = "name", havingValue = "eureka") + RegistryService registryServiceEureka() { + return new RegistryServiceEureka(); + } + + /** + * 当配置了registry.name=nacos生效 + * + * @return + */ + @Bean + @ConditionalOnProperty(prefix = "registry", name = "name", havingValue = "nacos") + RegistryService registryServiceNacos() { + return new RegistryServiceNacos(); + } + +} diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/service/RegistrationService.java b/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/service/RegistryService.java similarity index 76% rename from sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/service/RegistrationService.java rename to sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/service/RegistryService.java index 7aa2aa02..974e724e 100644 --- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/service/RegistrationService.java +++ b/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/service/RegistryService.java @@ -1,14 +1,14 @@ -package com.gitee.sop.adminserver.service; +package com.gitee.sop.registryapi.service; -import com.gitee.sop.adminserver.bean.ServiceInfo; -import com.gitee.sop.adminserver.bean.ServiceInstance; +import com.gitee.sop.registryapi.bean.ServiceInfo; +import com.gitee.sop.registryapi.bean.ServiceInstance; import java.util.List; /** * @author tanghc */ -public interface RegistrationService { +public interface RegistryService { /** * 获取所有服务列表 * diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/service/impl/RegistrationServiceEureka.java b/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/service/impl/RegistryServiceEureka.java similarity index 61% rename from sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/service/impl/RegistrationServiceEureka.java rename to sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/service/impl/RegistryServiceEureka.java index d16ebd2e..64eada4e 100644 --- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/service/impl/RegistrationServiceEureka.java +++ b/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/service/impl/RegistryServiceEureka.java @@ -1,45 +1,43 @@ -package com.gitee.sop.adminserver.service.impl; +package com.gitee.sop.registryapi.service.impl; import com.alibaba.fastjson.JSON; -import com.gitee.sop.adminserver.bean.EurekaApplication; -import com.gitee.sop.adminserver.bean.EurekaApps; -import com.gitee.sop.adminserver.bean.EurekaInstance; -import com.gitee.sop.adminserver.bean.EurekaUri; -import com.gitee.sop.adminserver.bean.ServiceInfo; -import com.gitee.sop.adminserver.bean.ServiceInstance; -import com.gitee.sop.adminserver.common.BizException; -import com.gitee.sop.adminserver.service.RegistrationService; +import com.gitee.sop.registryapi.bean.EurekaApplication; +import com.gitee.sop.registryapi.bean.EurekaApps; +import com.gitee.sop.registryapi.bean.EurekaInstance; +import com.gitee.sop.registryapi.bean.EurekaUri; +import com.gitee.sop.registryapi.bean.ServiceInfo; +import com.gitee.sop.registryapi.bean.ServiceInstance; +import com.gitee.sop.registryapi.service.RegistryService; import lombok.extern.slf4j.Slf4j; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; -import org.apache.commons.collections.CollectionUtils; -import org.apache.commons.lang.StringUtils; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.core.env.Environment; -import org.springframework.stereotype.Service; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.util.CollectionUtils; -import javax.annotation.PostConstruct; import java.io.IOException; import java.util.ArrayList; +import java.util.Collections; import java.util.List; /** + * eureka接口实现 * @author tanghc */ @Slf4j -@Service -public class RegistrationServiceEureka implements RegistrationService { +public class RegistryServiceEureka implements RegistryService { OkHttpClient client = new OkHttpClient(); - @Autowired - private Environment environment; - + @Value("${registry.eureka-server-addr:}") private String eurekaUrl; @Override public List listAllService(int pageNo, int pageSize) throws Exception { + if (StringUtils.isBlank(eurekaUrl)) { + return Collections.emptyList(); + } String json = this.requestEurekaServer(EurekaUri.QUERY_APPS); EurekaApps eurekaApps = JSON.parseObject(json, EurekaApps.class); @@ -49,13 +47,14 @@ public class RegistrationServiceEureka implements RegistrationService { ServiceInfo serviceInfo = new ServiceInfo(); serviceInfo.setServiceId(eurekaApplication.getName()); List instanceList = eurekaApplication.getInstance(); - if (CollectionUtils.isNotEmpty(instanceList)) { + if (!CollectionUtils.isEmpty(instanceList)) { serviceInfo.setInstances(new ArrayList<>(instanceList.size())); for (EurekaInstance eurekaInstance : instanceList) { ServiceInstance serviceInstance = new ServiceInstance(); serviceInstance.setInstanceId(eurekaInstance.getInstanceId()); serviceInstance.setServiceId(serviceInfo.getServiceId()); - serviceInstance.setIpPort(eurekaInstance.getIpAddr() + ":" + eurekaInstance.fetchPort()); + serviceInstance.setIp(eurekaInstance.getIpAddr()); + serviceInstance.setPort(Integer.valueOf(eurekaInstance.fetchPort())); serviceInstance.setStatus(eurekaInstance.getStatus()); serviceInfo.getInstances().add(serviceInstance); } @@ -84,21 +83,8 @@ public class RegistrationServiceEureka implements RegistrationService { return response.body().string(); } else { log.error("操作失败,url:{}, msg:{}, code:{}", eurekaUri.getUri(args), response.message(), response.code()); - throw new BizException("操作失败", String.valueOf(response.code())); + throw new RuntimeException("操作失败"); } } - @PostConstruct - protected void after() { - String eurekaUrls = environment.getProperty("eureka.client.serviceUrl.defaultZone"); - if (StringUtils.isBlank(eurekaUrls)) { - throw new BizException("未指定eureka.client.serviceUrl.defaultZone参数"); - } - // 取第一个 - String url = eurekaUrls.split("\\,")[0]; - if (url.endsWith("/")) { - url = eurekaUrls.substring(0, eurekaUrls.length() - 1); - } - this.eurekaUrl = url; - } } diff --git a/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/service/impl/RegistryServiceNacos.java b/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/service/impl/RegistryServiceNacos.java new file mode 100644 index 00000000..4d72b98b --- /dev/null +++ b/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/service/impl/RegistryServiceNacos.java @@ -0,0 +1,106 @@ +package com.gitee.sop.registryapi.service.impl; + +import com.alibaba.nacos.api.exception.NacosException; +import com.alibaba.nacos.api.naming.NamingFactory; +import com.alibaba.nacos.api.naming.NamingService; +import com.alibaba.nacos.api.naming.pojo.Instance; +import com.alibaba.nacos.api.naming.pojo.ListView; +import com.gitee.sop.registryapi.bean.ServiceInfo; +import com.gitee.sop.registryapi.bean.ServiceInstance; +import com.gitee.sop.registryapi.service.RegistryService; +import okhttp3.FormBody; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.util.CollectionUtils; + +import javax.annotation.PostConstruct; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * nacos接口实现 + * @author tanghc + */ +public class RegistryServiceNacos implements RegistryService { + + OkHttpClient client = new OkHttpClient(); + + @Value("${registry.nacos-server-addr:}") + private String nacosAddr; + + private NamingService namingService; + + @PostConstruct + public void after() throws NacosException { + if (StringUtils.isNotBlank(nacosAddr)) { + namingService = NamingFactory.createNamingService(nacosAddr); + } + } + + @Override + public List listAllService(int pageNo, int pageSize) throws Exception { + ListView servicesOfServer = namingService.getServicesOfServer(pageNo, pageSize); + List serverList = servicesOfServer.getData(); + List serviceInfoList = new ArrayList<>(); + for (String serviceName : serverList) { + ServiceInfo serviceInfo = new ServiceInfo(); + serviceInfo.setServiceId(serviceName); + List instanceList = namingService.getAllInstances(serviceName); + if (!CollectionUtils.isEmpty(instanceList)) { + serviceInfo.setInstances(new ArrayList<>(instanceList.size())); + for (Instance instance : instanceList) { + ServiceInstance serviceInstance = new ServiceInstance(); + serviceInstance.setInstanceId(instance.getInstanceId()); + serviceInstance.setServiceId(serviceInfo.getServiceId()); + serviceInstance.setIp(instance.getIp()); + serviceInstance.setPort(instance.getPort()); + boolean isOnline = instance.getWeight() > 0; + String status = isOnline ? "UP" : "OUT_OF_SERVICE"; + serviceInstance.setStatus(status); + serviceInfo.getInstances().add(serviceInstance); + } + } + serviceInfoList.add(serviceInfo); + } + return serviceInfoList; + } + + @Override + public void onlineInstance(ServiceInstance serviceInstance) throws Exception { + Map params = new HashMap<>(); + // 上线,把权重设置成1 + params.put("weight", "1"); + this.updateInstance(serviceInstance, params); + } + + @Override + public void offlineInstance(ServiceInstance serviceInstance) throws Exception { + Map params = new HashMap<>(); + // 下线,把权重设置成0 + params.put("weight", "0"); + this.updateInstance(serviceInstance, params); + } + + private Response updateInstance(ServiceInstance serviceInstance, Map params) throws IOException { + FormBody.Builder builder = new FormBody.Builder(); + for (Map.Entry entry : params.entrySet()) { + builder.add(entry.getKey(), String.valueOf(entry.getValue())); + } + builder.add("serviceName", serviceInstance.getServiceId()) + .add("ip", serviceInstance.getIp()) + .add("port", String.valueOf(serviceInstance.getPort())); + FormBody formBody = builder.build(); + final Request request = new Request.Builder() + .url("http://" + nacosAddr + "/nacos/v1/ns/instance") + .put(formBody) + .build(); + + return client.newCall(request).execute(); + } +} diff --git a/sop-example/sop-book/sop-book-web/pom.xml b/sop-example/sop-book/sop-book-web/pom.xml index 8e1e2e1b..60606be9 100644 --- a/sop-example/sop-book/sop-book-web/pom.xml +++ b/sop-example/sop-book/sop-book-web/pom.xml @@ -36,10 +36,28 @@ sop-story-api 1.0-SNAPSHOT + + + + + + + + org.springframework.cloud + spring-cloud-starter-alibaba-nacos-discovery + 0.2.2.RELEASE + + + + org.springframework.cloud spring-cloud-starter-openfeign diff --git a/sop-example/sop-book/sop-book-web/src/main/java/com/gitee/sop/bookweb/controller/ApiResult.java b/sop-example/sop-book/sop-book-web/src/main/java/com/gitee/sop/bookweb/controller/ApiResult.java index a39434b8..a102dfa8 100644 --- a/sop-example/sop-book/sop-book-web/src/main/java/com/gitee/sop/bookweb/controller/ApiResult.java +++ b/sop-example/sop-book/sop-book-web/src/main/java/com/gitee/sop/bookweb/controller/ApiResult.java @@ -1,6 +1,5 @@ package com.gitee.sop.bookweb.controller; -import com.thoughtworks.xstream.annotations.XStreamAlias; import lombok.Data; /** @@ -48,7 +47,6 @@ import lombok.Data; * * @author tanghc */ -@XStreamAlias("response") @Data public class ApiResult { diff --git a/sop-example/sop-book/sop-book-web/src/main/resources/application-dev.yml b/sop-example/sop-book/sop-book-web/src/main/resources/application-dev.yml index edb92dec..4f39516a 100644 --- a/sop-example/sop-book/sop-book-web/src/main/resources/application-dev.yml +++ b/sop-example/sop-book/sop-book-web/src/main/resources/application-dev.yml @@ -10,12 +10,16 @@ spring: # zookeeper配置 connect-string: localhost:2181 -eureka: - port: 1111 - host: localhost - client: - serviceUrl: - defaultZone: http://${eureka.host}:${eureka.port}/eureka/ + # nacos注册中心,和eureka只能用一个 + nacos: + discovery: + server-addr: 127.0.0.1:8848 + +# eureka注册中心,如果使用nacos注册中心,这里要注释掉 +#eureka: +# client: +# serviceUrl: +# defaultZone: http://localhost:1111/eureka/ # dubbo consumer demo: diff --git a/sop-example/sop-story/sop-story-web/pom.xml b/sop-example/sop-story/sop-story-web/pom.xml index ce13c01c..003081e0 100644 --- a/sop-example/sop-story/sop-story-web/pom.xml +++ b/sop-example/sop-story/sop-story-web/pom.xml @@ -31,10 +31,26 @@ sop-story-api 1.0-SNAPSHOT + + + + + + + org.springframework.cloud + spring-cloud-starter-alibaba-nacos-discovery + 0.2.2.RELEASE + + + org.springframework.cloud spring-cloud-starter-openfeign 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 ae690ad4..083cdc50 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 @@ -87,7 +87,7 @@ public class AlipayController { public Story getStory() { Story story = new Story(); story.setId(1); - story.setName("海底小纵队(alipay.story.get)"); + story.setName("海底小纵队(alipay.story.get),2222"); return story; } diff --git a/sop-example/sop-story/sop-story-web/src/main/resources/application-dev.yml b/sop-example/sop-story/sop-story-web/src/main/resources/application-dev.yml index 3a06f369..62354b7a 100644 --- a/sop-example/sop-story/sop-story-web/src/main/resources/application-dev.yml +++ b/sop-example/sop-story/sop-story-web/src/main/resources/application-dev.yml @@ -10,13 +10,16 @@ spring: zookeeper: connect-string: localhost:2181 -# 注册中心 -eureka: - port: 1111 - host: localhost - client: - serviceUrl: - defaultZone: http://${eureka.host}:${eureka.port}/eureka/ + # nacos注册中心,和eureka只能用一个 + nacos: + discovery: + server-addr: 127.0.0.1:8848 + +# eureka注册中心,如果使用nacos注册中心,这里要注释掉 +#eureka: +# client: +# serviceUrl: +# defaultZone: http://localhost:1111/eureka/ # dubbo provider dubbo: diff --git a/sop-gateway/pom.xml b/sop-gateway/pom.xml index 04d45bef..78edce77 100644 --- a/sop-gateway/pom.xml +++ b/sop-gateway/pom.xml @@ -65,10 +65,24 @@ runtime + + + + + + org.springframework.cloud + spring-cloud-starter-alibaba-nacos-discovery + 0.2.2.RELEASE + + diff --git a/sop-gateway/src/main/resources/application-dev.yml b/sop-gateway/src/main/resources/application-dev.yml index 02b73a56..c025fd63 100644 --- a/sop-gateway/src/main/resources/application-dev.yml +++ b/sop-gateway/src/main/resources/application-dev.yml @@ -19,13 +19,6 @@ ribbon: # 请谨慎设置,因为post请求大多都是写入请求,如果要支持重试,确保服务的幂等性 OkToRetryOnAllOperations: false -# 注册中心,根据实际情况修改 -eureka: - serverAddr: localhost:1111 - client: - serviceUrl: - defaultZone: http://${eureka.serverAddr}/eureka/ - spring: application: name: api-gateway @@ -41,6 +34,16 @@ spring: lower-case-service-id: true enabled: true + # nacos注册中心,和eureka只能用一个 + nacos: + discovery: + server-addr: 127.0.0.1:8848 + +# eureka注册中心,如果使用nacos注册中心,这里要注释掉 +#eureka: +# client: +# serviceUrl: +# defaultZone: http://localhost:1111/eureka/ # 数据源,根据实际情况修改 datasource: diff --git a/sop-test/src/test/java/com/gitee/sop/LoadBalanceTest.java b/sop-test/src/test/java/com/gitee/sop/LoadBalanceTest.java new file mode 100644 index 00000000..f9bbaa3b --- /dev/null +++ b/sop-test/src/test/java/com/gitee/sop/LoadBalanceTest.java @@ -0,0 +1,64 @@ +package com.gitee.sop; + +import com.alibaba.fastjson.JSON; +import com.gitee.sop.alipay.AlipayApiException; +import com.gitee.sop.alipay.AlipaySignature; +import org.junit.Test; + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + + +public class LoadBalanceTest extends TestBase { + + String url = "http://localhost:8081/api"; // zuul + String appId = "2019032617262200001"; + // 支付宝私钥 + String privateKey = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCXJv1pQFqWNA/++OYEV7WYXwexZK/J8LY1OWlP9X0T6wHFOvxNKRvMkJ5544SbgsJpVcvRDPrcxmhPbi/sAhdO4x2PiPKIz9Yni2OtYCCeaiE056B+e1O2jXoLeXbfi9fPivJZkxH/tb4xfLkH3bA8ZAQnQsoXA0SguykMRZntF0TndUfvDrLqwhlR8r5iRdZLB6F8o8qXH6UPDfNEnf/K8wX5T4EB1b8x8QJ7Ua4GcIUqeUxGHdQpzNbJdaQvoi06lgccmL+PHzminkFYON7alj1CjDN833j7QMHdPtS9l7B67fOU/p2LAAkPMtoVBfxQt9aFj7B8rEhGCz02iJIBAgMBAAECggEARqOuIpY0v6WtJBfmR3lGIOOokLrhfJrGTLF8CiZMQha+SRJ7/wOLPlsH9SbjPlopyViTXCuYwbzn2tdABigkBHYXxpDV6CJZjzmRZ+FY3S/0POlTFElGojYUJ3CooWiVfyUMhdg5vSuOq0oCny53woFrf32zPHYGiKdvU5Djku1onbDU0Lw8w+5tguuEZ76kZ/lUcccGy5978FFmYpzY/65RHCpvLiLqYyWTtaNT1aQ/9pw4jX9HO9NfdJ9gYFK8r/2f36ZE4hxluAfeOXQfRC/WhPmiw/ReUhxPznG/WgKaa/OaRtAx3inbQ+JuCND7uuKeRe4osP2jLPHPP6AUwQKBgQDUNu3BkLoKaimjGOjCTAwtp71g1oo+k5/uEInAo7lyEwpV0EuUMwLA/HCqUgR4K9pyYV+Oyb8d6f0+Hz0BMD92I2pqlXrD7xV2WzDvyXM3s63NvorRooKcyfd9i6ccMjAyTR2qfLkxv0hlbBbsPHz4BbU63xhTJp3Ghi0/ey/1HQKBgQC2VsgqC6ykfSidZUNLmQZe3J0p/Qf9VLkfrQ+xaHapOs6AzDU2H2osuysqXTLJHsGfrwVaTs00ER2z8ljTJPBUtNtOLrwNRlvgdnzyVAKHfOgDBGwJgiwpeE9voB1oAV/mXqSaUWNnuwlOIhvQEBwekqNyWvhLqC7nCAIhj3yvNQKBgQCqYbeec56LAhWP903Zwcj9VvG7sESqXUhIkUqoOkuIBTWFFIm54QLTA1tJxDQGb98heoCIWf5x/A3xNI98RsqNBX5JON6qNWjb7/dobitti3t99v/ptDp9u8JTMC7penoryLKK0Ty3bkan95Kn9SC42YxaSghzqkt+uvfVQgiNGQKBgGxU6P2aDAt6VNwWosHSe+d2WWXt8IZBhO9d6dn0f7ORvcjmCqNKTNGgrkewMZEuVcliueJquR47IROdY8qmwqcBAN7Vg2K7r7CPlTKAWTRYMJxCT1Hi5gwJb+CZF3+IeYqsJk2NF2s0w5WJTE70k1BSvQsfIzAIDz2yE1oPHvwVAoGAA6e+xQkVH4fMEph55RJIZ5goI4Y76BSvt2N5OKZKd4HtaV+eIhM3SDsVYRLIm9ZquJHMiZQGyUGnsvrKL6AAVNK7eQZCRDk9KQz+0GKOGqku0nOZjUbAu6A2/vtXAaAuFSFx1rUQVVjFulLexkXR3KcztL1Qu2k5pB6Si0K/uwQ="; + + // 测试稳定性 + @Test + public void testLoadBalance() throws Exception { + int i = 0; + while (i++ < 50) { + doTest(); + Thread.sleep(3000); + } + } + + private void doTest() throws AlipayApiException { + // 公共请求参数 + Map params = new HashMap(); + params.put("app_id", appId); + params.put("method", "alipay.story.get"); + params.put("format", "json"); + params.put("charset", "utf-8"); + params.put("sign_type", "RSA2"); + params.put("timestamp", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())); + params.put("version", "1.0"); + + // 业务参数 + Map bizContent = new HashMap<>(); + bizContent.put("id", "1"); + bizContent.put("name", "葫芦娃"); + + params.put("biz_content", JSON.toJSONString(bizContent)); + +// System.out.println("----------- 请求信息 -----------"); +// System.out.println("请求参数:" + buildParamQuery(params)); +// System.out.println("商户秘钥:" + privateKey); + String content = AlipaySignature.getSignContent(params); +// System.out.println("待签名内容:" + content); + String sign = AlipaySignature.rsa256Sign(content, privateKey, "utf-8"); +// System.out.println("签名(sign):" + sign); + + params.put("sign", sign); + +// System.out.println("----------- 返回结果 -----------"); + String responseData = get(url, params);// 发送请求 + System.out.println(responseData); + } + +} diff --git a/sop-website/website-server/pom.xml b/sop-website/website-server/pom.xml index b181b624..30464050 100644 --- a/sop-website/website-server/pom.xml +++ b/sop-website/website-server/pom.xml @@ -21,6 +21,13 @@ + + + com.gitee.sop + sop-registry-api + 1.11.0-SNAPSHOT + + org.springframework.boot spring-boot-starter-web diff --git a/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/config/RegistryConfig.java b/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/config/RegistryConfig.java new file mode 100644 index 00000000..1721a2d1 --- /dev/null +++ b/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/config/RegistryConfig.java @@ -0,0 +1,12 @@ +package com.gitee.sop.websiteserver.config; + +import com.gitee.sop.registryapi.config.BaseRegistryConfig; +import org.springframework.context.annotation.Configuration; + +/** + * @author tanghc + */ +@Configuration +public class RegistryConfig extends BaseRegistryConfig { + +} \ No newline at end of file diff --git a/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/controller/SandboxController.java b/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/controller/SandboxController.java index 97c8b0bb..2d22ab6d 100644 --- a/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/controller/SandboxController.java +++ b/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/controller/SandboxController.java @@ -3,6 +3,7 @@ package com.gitee.sop.websiteserver.controller; import com.gitee.sop.websiteserver.sign.AlipayApiException; import com.gitee.sop.websiteserver.sign.AlipaySignature; import lombok.Data; +import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang.StringUtils; import org.apache.http.NameValuePair; import org.apache.http.client.entity.UrlEncodedFormEntity; @@ -30,6 +31,7 @@ import java.util.stream.Collectors; * 沙箱环境代理类 * @author tanghc */ +@Slf4j @RestController @RequestMapping("sandbox") public class SandboxController { @@ -45,8 +47,8 @@ public class SandboxController { , @RequestParam String version , @RequestParam String bizContent) throws AlipayApiException { - Assert.isTrue(StringUtils.isNotBlank(appId), "appId不能为空"); - Assert.isTrue(StringUtils.isNotBlank(privateKey), "privateKey不能为空"); + Assert.isTrue(StringUtils.isNotBlank(appId), "AppId不能为空"); + Assert.isTrue(StringUtils.isNotBlank(privateKey), "PrivateKey不能为空"); Assert.isTrue(StringUtils.isNotBlank(method), "method不能为空"); // 公共请求参数 @@ -69,7 +71,12 @@ public class SandboxController { String content = AlipaySignature.getSignContent(params); result.beforeSign = content; - String sign = AlipaySignature.rsa256Sign(content, privateKey, "utf-8"); + String sign = null; + try { + sign = AlipaySignature.rsa256Sign(content, privateKey, "utf-8"); + } catch (AlipayApiException e) { + throw new RuntimeException("构建签名失败"); + } result.sign = sign; params.put("sign", sign); diff --git a/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/manager/DocManagerImpl.java b/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/manager/DocManagerImpl.java index 97c8ad2c..fa3adabb 100644 --- a/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/manager/DocManagerImpl.java +++ b/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/manager/DocManagerImpl.java @@ -3,19 +3,13 @@ package com.gitee.sop.websiteserver.manager; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.parser.Feature; +import com.gitee.sop.registryapi.bean.ServiceInfo; +import com.gitee.sop.registryapi.bean.ServiceInstance; +import com.gitee.sop.registryapi.service.RegistryService; import com.gitee.sop.websiteserver.bean.DocInfo; import com.gitee.sop.websiteserver.bean.DocItem; -import com.gitee.sop.websiteserver.bean.EurekaApplication; -import com.gitee.sop.websiteserver.bean.EurekaApps; -import com.gitee.sop.websiteserver.bean.EurekaInstance; -import com.gitee.sop.websiteserver.bean.EurekaUri; import com.gitee.sop.websiteserver.bean.ZookeeperContext; -import com.gitee.sop.websiteserver.vo.ServiceInfoVO; import lombok.extern.slf4j.Slf4j; -import okhttp3.OkHttpClient; -import okhttp3.Request; -import okhttp3.Response; -import org.apache.commons.lang.StringUtils; import org.apache.curator.framework.recipes.cache.TreeCacheEvent; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.env.Environment; @@ -26,8 +20,6 @@ import org.springframework.util.DigestUtils; import org.springframework.web.client.RestTemplate; import javax.annotation.PostConstruct; -import java.io.IOException; -import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; @@ -53,8 +45,6 @@ public class DocManagerImpl implements DocManager { Map docItemMap = new HashMap<>(); - OkHttpClient client = new OkHttpClient(); - RestTemplate restTemplate = new RestTemplate(); DocParser swaggerDocParser = new SwaggerDocParser(); @@ -70,33 +60,35 @@ public class DocManagerImpl implements DocManager { @Autowired private Environment environment; - private String eurekaUrl; + @Autowired + private RegistryService registryService; private volatile boolean listenInited; @Override public void load() { try { - // {"STORY-SERVICE":[{"ipAddr":"10.1.30.54","name":"STORY-SERVICE","serverPort":"2222"}],"API-GATEWAY":[{"ipAddr":"10.1.30.54","name":"API-GATEWAY","serverPort":"8081"}]} - Map> listMap = this.getAllServiceList(); - log.info("服务列表:{}", JSON.toJSONString(listMap.keySet())); - listMap.entrySet() + List serviceInfoList = registryService.listAllService(1, 9999); + log.info("服务列表:{}", serviceInfoList); + + serviceInfoList .stream() // 网关没有文档提供,需要排除 - .filter(entry -> !"API-GATEWAY".equalsIgnoreCase(entry.getKey())) - .forEach(entry -> { - ServiceInfoVO serviceInfoVo = entry.getValue().get(0); - loadDocInfo(serviceInfoVo); - }); + .filter(serviceInfo -> !"API-GATEWAY".equalsIgnoreCase(serviceInfo.getServiceId())) + .filter(serviceInfo -> !serviceInfo.getInstances().isEmpty()) + .map(serviceInfo -> serviceInfo.getInstances().get(0)) + .collect(Collectors.toList()) + .forEach(this::loadDocInfo); } catch (Exception e) { log.error("加载失败", e); } } - protected void loadDocInfo(ServiceInfoVO serviceInfoVo) { + protected void loadDocInfo(ServiceInstance serviceInstance) { String query = this.buildQuery(); - String url = "http://" + serviceInfoVo.getIpAddr() + ":" + serviceInfoVo.getServerPort() + "/v2/api-docs" + query; + String url = "http://" + serviceInstance.getIpPort() + "/v2/api-docs" + query; try { + log.info("读取swagger文档,url:{}", url); ResponseEntity entity = restTemplate.getForEntity(url, String.class); if (entity.getStatusCode() != HttpStatus.OK) { throw new IllegalAccessException("无权访问"); @@ -144,55 +136,8 @@ public class DocManagerImpl implements DocManager { return docDefinitionMap.values(); } - protected Map> getAllServiceList() throws IOException { - String json = this.requestEurekaServer(EurekaUri.QUERY_APPS); - EurekaApps eurekaApps = JSON.parseObject(json, EurekaApps.class); - - List serviceInfoVoList = new ArrayList<>(); - List applicationList = eurekaApps.getApplications().getApplication(); - applicationList.stream() - .forEach(eurekaApplication -> { - List instanceList = eurekaApplication.getInstance(); - for (EurekaInstance instance : instanceList) { - if ("UP".equals(instance.getStatus())) { - ServiceInfoVO vo = new ServiceInfoVO(); - vo.setName(eurekaApplication.getName()); - vo.setIpAddr(instance.getIpAddr()); - vo.setServerPort(instance.fetchPort()); - serviceInfoVoList.add(vo); - } - } - }); - - Map> listMap = serviceInfoVoList.stream() - .collect(Collectors.groupingBy(ServiceInfoVO::getName)); - - return listMap; - } - - protected String requestEurekaServer(EurekaUri eurekaUri, String... args) throws IOException { - Request request = eurekaUri.getRequest(this.eurekaUrl, args); - Response response = client.newCall(request).execute(); - if (response.isSuccessful()) { - return response.body().string(); - } else { - log.error("操作失败,url:{}, msg:{}, code:{}", eurekaUri.getUri(args), response.message(), response.code()); - throw new RuntimeException("操作失败"); - } - } - @PostConstruct protected void after() throws Exception { - String eurekaUrls = environment.getProperty("eureka.client.serviceUrl.defaultZone"); - if (StringUtils.isBlank(eurekaUrls)) { - throw new IllegalArgumentException("未指定eureka.client.serviceUrl.defaultZone参数"); - } - String url = eurekaUrls.split("\\,")[0]; - if (url.endsWith("/")) { - url = eurekaUrls.substring(0, eurekaUrls.length() - 1); - } - this.eurekaUrl = url; - this.listenServiceId(); } diff --git a/sop-website/website-server/src/main/resources/application-dev.yml b/sop-website/website-server/src/main/resources/application-dev.yml index 3ec0b465..d6181365 100644 --- a/sop-website/website-server/src/main/resources/application-dev.yml +++ b/sop-website/website-server/src/main/resources/application-dev.yml @@ -1,12 +1,12 @@ server: port: 8083 -# 注册中心 -eureka: - serverAddr: localhost:1111 - client: - serviceUrl: - defaultZone: http://${eureka.serverAddr}/eureka/ +# 注册中心地址,根据实际情况改,这里只是参数,并不会去注册 +registry: + # 使用哪个配置中心,使用eureka,填eureka;使用nacos填nacos + name: nacos + eureka-server-addr: http://localhost:1111/eureka/ + nacos-server-addr: 127.0.0.1:8848 spring: application: