mirror of
https://gitee.com/durcframework/SOP.git
synced 2025-08-11 21:57:56 +08:00
nacos注册中心
This commit is contained in:
@@ -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)
|
||||
|
113
doc/docs/files/10106_nacos注册中心.md
Normal file
113
doc/docs/files/10106_nacos注册中心.md
Normal file
@@ -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<ServiceInfo> 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
|
||||
<!-- 注册中心【只能用一个,不用的注释掉】 -->
|
||||
<!-- 使用eureka注册中心
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
|
||||
</dependency>
|
||||
-->
|
||||
|
||||
<!-- 使用nacos注册中心
|
||||
版本 0.2.x.RELEASE 对应的是 Spring Boot 2.x 版本,版本 0.1.x.RELEASE 对应的是 Spring Boot 1.x 版本。
|
||||
https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-alibaba-nacos-discovery
|
||||
-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
|
||||
<version>0.2.2.RELEASE</version>
|
||||
</dependency>
|
||||
<!-- 注册中心end -->
|
||||
```
|
||||
|
||||
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)
|
@@ -13,7 +13,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>2.0.3.RELEASE</version>
|
||||
<version>2.1.4.RELEASE</version>
|
||||
<relativePath /> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
|
||||
@@ -27,12 +27,12 @@
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<!-- 将前端页面打包成webjars,然后打开注释
|
||||
<dependency>
|
||||
<groupId>com.gitee.sop</groupId>
|
||||
<artifactId>sop-admin-front</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</dependency>-->
|
||||
<artifactId>sop-registry-api</artifactId>
|
||||
<version>1.11.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<!-- easyopen starter -->
|
||||
<dependency>
|
||||
<groupId>net.oschina.durcframework</groupId>
|
||||
@@ -78,12 +78,6 @@
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.squareup.okhttp3</groupId>
|
||||
<artifactId>okhttp</artifactId>
|
||||
<version>${okhttp.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
@@ -109,6 +103,12 @@
|
||||
<version>1.18.4</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-commons</artifactId>
|
||||
<version>2.1.0.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
|
@@ -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<ServiceInstanceVO> listService(ServiceSearchParam param) {
|
||||
List<ServiceInstanceVO> listService(ServiceSearchParam param) {
|
||||
List<ServiceInfo> 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("上线失败,请查看日志");
|
||||
|
@@ -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 : "";
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -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 {
|
||||
|
||||
}
|
@@ -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:
|
||||
|
@@ -37,7 +37,8 @@
|
||||
<modules>
|
||||
<module>sop-gateway-common</module>
|
||||
<module>sop-service-common</module>
|
||||
</modules>
|
||||
<module>sop-registry-api</module>
|
||||
</modules>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
|
@@ -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`
|
@@ -1,3 +1,3 @@
|
||||
# sop-gateway-common
|
||||
|
||||
zuul通用组件,主要封装网关的一些功能。
|
||||
网关通用组件,主要封装网关的一些功能。
|
||||
|
74
sop-common/sop-registry-api/pom.xml
Normal file
74
sop-common/sop-registry-api/pom.xml
Normal file
@@ -0,0 +1,74 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.gitee.sop</groupId>
|
||||
<artifactId>sop-registry-api</artifactId>
|
||||
<version>1.11.0-SNAPSHOT</version>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
<java.version>1.8</java.version>
|
||||
<okhttp.version>3.11.0</okhttp.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.squareup.okhttp3</groupId>
|
||||
<artifactId>okhttp</artifactId>
|
||||
<version>${okhttp.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- nacos sdk -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba.nacos</groupId>
|
||||
<artifactId>nacos-client</artifactId>
|
||||
<version>1.0.1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
<version>5.1.6.RELEASE</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.6</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-autoconfigure</artifactId>
|
||||
<version>2.1.4.RELEASE</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.11</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.1</version>
|
||||
<configuration>
|
||||
<source>${java.version}</source>
|
||||
<target>${java.version}</target>
|
||||
<encoding>UTF-8</encoding>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
3
sop-common/sop-registry-api/readme.md
Normal file
3
sop-common/sop-registry-api/readme.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# sop-registry-api
|
||||
|
||||
统一各注册中心接口
|
@@ -1,4 +1,4 @@
|
||||
package com.gitee.sop.adminserver.bean;
|
||||
package com.gitee.sop.registryapi.bean;
|
||||
|
||||
import lombok.Data;
|
||||
|
@@ -1,4 +1,4 @@
|
||||
package com.gitee.sop.adminserver.bean;
|
||||
package com.gitee.sop.registryapi.bean;
|
||||
|
||||
import lombok.Data;
|
||||
|
@@ -1,4 +1,4 @@
|
||||
package com.gitee.sop.adminserver.bean;
|
||||
package com.gitee.sop.registryapi.bean;
|
||||
|
||||
import lombok.Data;
|
||||
|
@@ -1,4 +1,4 @@
|
||||
package com.gitee.sop.adminserver.bean;
|
||||
package com.gitee.sop.registryapi.bean;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.util.CollectionUtils;
|
@@ -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);
|
||||
}
|
||||
}
|
@@ -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<ServiceInstance> instances = Collections.emptyList();
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "服务名称: " + serviceId + ", 实例数:" + instances.size();
|
||||
}
|
||||
}
|
@@ -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;
|
||||
|
||||
}
|
@@ -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();
|
||||
}
|
||||
|
||||
}
|
@@ -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 {
|
||||
/**
|
||||
* 获取所有服务列表
|
||||
*
|
@@ -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<ServiceInfo> 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<EurekaInstance> 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;
|
||||
}
|
||||
}
|
@@ -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<ServiceInfo> listAllService(int pageNo, int pageSize) throws Exception {
|
||||
ListView<String> servicesOfServer = namingService.getServicesOfServer(pageNo, pageSize);
|
||||
List<String> serverList = servicesOfServer.getData();
|
||||
List<ServiceInfo> serviceInfoList = new ArrayList<>();
|
||||
for (String serviceName : serverList) {
|
||||
ServiceInfo serviceInfo = new ServiceInfo();
|
||||
serviceInfo.setServiceId(serviceName);
|
||||
List<Instance> 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<String, String> params = new HashMap<>();
|
||||
// 上线,把权重设置成1
|
||||
params.put("weight", "1");
|
||||
this.updateInstance(serviceInstance, params);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void offlineInstance(ServiceInstance serviceInstance) throws Exception {
|
||||
Map<String, String> params = new HashMap<>();
|
||||
// 下线,把权重设置成0
|
||||
params.put("weight", "0");
|
||||
this.updateInstance(serviceInstance, params);
|
||||
}
|
||||
|
||||
private Response updateInstance(ServiceInstance serviceInstance, Map<String, String> params) throws IOException {
|
||||
FormBody.Builder builder = new FormBody.Builder();
|
||||
for (Map.Entry<String, String> 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();
|
||||
}
|
||||
}
|
@@ -36,10 +36,28 @@
|
||||
<artifactId>sop-story-api</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- 注册中心【只能用一个,不用的注释掉】 -->
|
||||
<!-- 使用eureka注册中心
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
|
||||
</dependency>
|
||||
-->
|
||||
|
||||
<!-- 使用nacos注册中心
|
||||
版本 0.2.x.RELEASE 对应的是 Spring Boot 2.x 版本,版本 0.1.x.RELEASE 对应的是 Spring Boot 1.x 版本。
|
||||
https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-alibaba-nacos-discovery
|
||||
-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
|
||||
<version>0.2.2.RELEASE</version>
|
||||
</dependency>
|
||||
<!-- 注册中心end -->
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-openfeign</artifactId>
|
||||
|
@@ -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 {
|
||||
|
||||
|
@@ -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:
|
||||
|
@@ -31,10 +31,26 @@
|
||||
<artifactId>sop-story-api</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 注册中心【只能用一个,不用的注释掉】 -->
|
||||
<!-- 使用eureka注册中心
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
|
||||
</dependency>
|
||||
-->
|
||||
|
||||
<!-- 使用nacos注册中心
|
||||
版本 0.2.x.RELEASE 对应的是 Spring Boot 2.x 版本,版本 0.1.x.RELEASE 对应的是 Spring Boot 1.x 版本。
|
||||
https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-alibaba-nacos-discovery
|
||||
-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
|
||||
<version>0.2.2.RELEASE</version>
|
||||
</dependency>
|
||||
<!-- 注册中心end -->
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-openfeign</artifactId>
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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:
|
||||
|
@@ -65,10 +65,24 @@
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- 注册中心【只能用一个,不用的注释掉】 -->
|
||||
<!-- 使用eureka注册中心
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
|
||||
</dependency>
|
||||
-->
|
||||
|
||||
<!-- 使用nacos注册中心
|
||||
版本 0.2.x.RELEASE 对应的是 Spring Boot 2.x 版本,版本 0.1.x.RELEASE 对应的是 Spring Boot 1.x 版本。
|
||||
https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-alibaba-nacos-discovery
|
||||
-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
|
||||
<version>0.2.2.RELEASE</version>
|
||||
</dependency>
|
||||
<!-- 注册中心end -->
|
||||
|
||||
<!-- test -->
|
||||
<dependency>
|
||||
|
@@ -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:
|
||||
|
64
sop-test/src/test/java/com/gitee/sop/LoadBalanceTest.java
Normal file
64
sop-test/src/test/java/com/gitee/sop/LoadBalanceTest.java
Normal file
@@ -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<String, String> params = new HashMap<String, String>();
|
||||
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<String, String> 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);
|
||||
}
|
||||
|
||||
}
|
@@ -21,6 +21,13 @@
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.gitee.sop</groupId>
|
||||
<artifactId>sop-registry-api</artifactId>
|
||||
<version>1.11.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
|
@@ -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 {
|
||||
|
||||
}
|
@@ -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);
|
||||
|
@@ -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<String, DocItem> 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<String, List<ServiceInfoVO>> listMap = this.getAllServiceList();
|
||||
log.info("服务列表:{}", JSON.toJSONString(listMap.keySet()));
|
||||
listMap.entrySet()
|
||||
List<ServiceInfo> 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<String> 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<String, List<ServiceInfoVO>> getAllServiceList() throws IOException {
|
||||
String json = this.requestEurekaServer(EurekaUri.QUERY_APPS);
|
||||
EurekaApps eurekaApps = JSON.parseObject(json, EurekaApps.class);
|
||||
|
||||
List<ServiceInfoVO> serviceInfoVoList = new ArrayList<>();
|
||||
List<EurekaApplication> applicationList = eurekaApps.getApplications().getApplication();
|
||||
applicationList.stream()
|
||||
.forEach(eurekaApplication -> {
|
||||
List<EurekaInstance> 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<String, List<ServiceInfoVO>> 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();
|
||||
}
|
||||
|
||||
|
@@ -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:
|
||||
|
Reference in New Issue
Block a user