mirror of
https://gitee.com/mirrors/Spring-Cloud-Alibaba.git
synced 2021-06-26 13:25:11 +08:00
Merge branch '1.x' of github.com:spring-cloud-incubator/spring-cloud-alibaba into 1.x
This commit is contained in:
commit
e2bacc4528
1
.gitignore
vendored
1
.gitignore
vendored
@ -28,4 +28,5 @@ hs_err_pid*
|
|||||||
.project
|
.project
|
||||||
.settings
|
.settings
|
||||||
target
|
target
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
# Spring Cloud Alibaba
|
# Spring Cloud Alibaba
|
||||||
|
|
||||||
|
A project maintained by Alibaba.
|
||||||
|
|
||||||
See the [中文文档](https://github.com/spring-cloud-incubator/spring-cloud-alibaba/blob/master/README-zh.md) for Chinese readme.
|
See the [中文文档](https://github.com/spring-cloud-incubator/spring-cloud-alibaba/blob/master/README-zh.md) for Chinese readme.
|
||||||
|
|
||||||
Spring Cloud Alibaba provides a one-stop solution for distributed application development. It contains all the components required to develop distributed applications, making it easy for you to develop your applications using Spring Cloud.
|
Spring Cloud Alibaba provides a one-stop solution for distributed application development. It contains all the components required to develop distributed applications, making it easy for you to develop your applications using Spring Cloud.
|
||||||
|
@ -15,7 +15,7 @@ Spring Cloud Alibaba 致力于提供分布式应用服务开发的一站式解
|
|||||||
**Nacos**
|
**Nacos**
|
||||||
阿里巴巴开源产品,一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。
|
阿里巴巴开源产品,一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。
|
||||||
|
|
||||||
**Aliyun OSS**
|
**AliCloud OSS**
|
||||||
阿里云对象存储服务(Object Storage Service,简称 OSS),是阿里云提供的海量、安全、低成本、高可靠的云存储服务。您可以在任何应用、任何时间、任何地点存储和访问任意类型的数据。
|
阿里云对象存储服务(Object Storage Service,简称 OSS),是阿里云提供的海量、安全、低成本、高可靠的云存储服务。您可以在任何应用、任何时间、任何地点存储和访问任意类型的数据。
|
||||||
|
|
||||||
## 即将加入的组件
|
## 即将加入的组件
|
||||||
|
81
pom.xml
81
pom.xml
@ -8,7 +8,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.springframework.cloud</groupId>
|
<groupId>org.springframework.cloud</groupId>
|
||||||
<artifactId>spring-cloud-build</artifactId>
|
<artifactId>spring-cloud-build</artifactId>
|
||||||
<version>1.3.10.RELEASE</version>
|
<version>1.3.11.RELEASE</version>
|
||||||
<relativePath/>
|
<relativePath/>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
@ -28,12 +28,12 @@
|
|||||||
</licenses>
|
</licenses>
|
||||||
|
|
||||||
<scm>
|
<scm>
|
||||||
<url>https://github.com/spring-cloud-incubator/spring-cloud-alibabacloud</url>
|
<url>https://github.com/spring-cloud-incubator/spring-cloud-alibaba</url>
|
||||||
<connection>
|
<connection>
|
||||||
scm:git:git://github.com/spring-cloud-incubator/spring-cloud-alibabacloud.git
|
scm:git:git://github.com/spring-cloud-incubator/spring-cloud-alibaba.git
|
||||||
</connection>
|
</connection>
|
||||||
<developerConnection>
|
<developerConnection>
|
||||||
scm:git:ssh://git@github.com/spring-cloud-incubator/spring-cloud-alibabacloud.git
|
scm:git:ssh://git@github.com/spring-cloud-incubator/spring-cloud-alibaba.git
|
||||||
</developerConnection>
|
</developerConnection>
|
||||||
<tag>HEAD</tag>
|
<tag>HEAD</tag>
|
||||||
</scm>
|
</scm>
|
||||||
@ -47,6 +47,10 @@
|
|||||||
<name>fangjian</name>
|
<name>fangjian</name>
|
||||||
<email>fangjian0423@gmail.com</email>
|
<email>fangjian0423@gmail.com</email>
|
||||||
</developer>
|
</developer>
|
||||||
|
<developer>
|
||||||
|
<name>xiaolongzuo</name>
|
||||||
|
<email>150349407@qq.com</email>
|
||||||
|
</developer>
|
||||||
<developer>
|
<developer>
|
||||||
<name>hengyunabc</name>
|
<name>hengyunabc</name>
|
||||||
<email>hengyunabc@gmail.com</email>
|
<email>hengyunabc@gmail.com</email>
|
||||||
@ -55,7 +59,7 @@
|
|||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<!-- Dependency Versions -->
|
<!-- Dependency Versions -->
|
||||||
<spring-cloud-commons.version>1.3.3.RELEASE</spring-cloud-commons.version>
|
<spring-cloud-commons.version>1.3.5.RELEASE</spring-cloud-commons.version>
|
||||||
<spring-cloud-netflix.version>1.4.4.RELEASE</spring-cloud-netflix.version>
|
<spring-cloud-netflix.version>1.4.4.RELEASE</spring-cloud-netflix.version>
|
||||||
|
|
||||||
<junit.version>4.12</junit.version>
|
<junit.version>4.12</junit.version>
|
||||||
@ -82,6 +86,8 @@
|
|||||||
<module>spring-cloud-starter-alicloud</module>
|
<module>spring-cloud-starter-alicloud</module>
|
||||||
<module>spring-cloud-alicloud-oss</module>
|
<module>spring-cloud-alicloud-oss</module>
|
||||||
<module>spring-cloud-alicloud-context</module>
|
<module>spring-cloud-alicloud-context</module>
|
||||||
|
<module>spring-cloud-alicloud-acm</module>
|
||||||
|
<module>spring-cloud-alicloud-ans</module>
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
<dependencyManagement>
|
<dependencyManagement>
|
||||||
@ -138,4 +144,69 @@
|
|||||||
</plugin>
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
|
<profiles>
|
||||||
|
<profile>
|
||||||
|
<id>spring</id>
|
||||||
|
<repositories>
|
||||||
|
<repository>
|
||||||
|
<id>spring-snapshots</id>
|
||||||
|
<name>Spring Snapshots</name>
|
||||||
|
<url>https://repo.spring.io/libs-snapshot-local</url>
|
||||||
|
<snapshots>
|
||||||
|
<enabled>true</enabled>
|
||||||
|
</snapshots>
|
||||||
|
<releases>
|
||||||
|
<enabled>false</enabled>
|
||||||
|
</releases>
|
||||||
|
</repository>
|
||||||
|
<repository>
|
||||||
|
<id>spring-milestones</id>
|
||||||
|
<name>Spring Milestones</name>
|
||||||
|
<url>https://repo.spring.io/libs-milestone-local</url>
|
||||||
|
<snapshots>
|
||||||
|
<enabled>false</enabled>
|
||||||
|
</snapshots>
|
||||||
|
</repository>
|
||||||
|
<repository>
|
||||||
|
<id>spring-releases</id>
|
||||||
|
<name>Spring Releases</name>
|
||||||
|
<url>https://repo.spring.io/release</url>
|
||||||
|
<snapshots>
|
||||||
|
<enabled>false</enabled>
|
||||||
|
</snapshots>
|
||||||
|
</repository>
|
||||||
|
</repositories>
|
||||||
|
<pluginRepositories>
|
||||||
|
<pluginRepository>
|
||||||
|
<id>spring-snapshots</id>
|
||||||
|
<name>Spring Snapshots</name>
|
||||||
|
<url>https://repo.spring.io/libs-snapshot-local</url>
|
||||||
|
<snapshots>
|
||||||
|
<enabled>true</enabled>
|
||||||
|
</snapshots>
|
||||||
|
<releases>
|
||||||
|
<enabled>false</enabled>
|
||||||
|
</releases>
|
||||||
|
</pluginRepository>
|
||||||
|
<pluginRepository>
|
||||||
|
<id>spring-milestones</id>
|
||||||
|
<name>Spring Milestones</name>
|
||||||
|
<url>https://repo.spring.io/libs-milestone-local</url>
|
||||||
|
<snapshots>
|
||||||
|
<enabled>false</enabled>
|
||||||
|
</snapshots>
|
||||||
|
</pluginRepository>
|
||||||
|
<pluginRepository>
|
||||||
|
<id>spring-releases</id>
|
||||||
|
<name>Spring Releases</name>
|
||||||
|
<url>https://repo.spring.io/libs-release-local</url>
|
||||||
|
<snapshots>
|
||||||
|
<enabled>false</enabled>
|
||||||
|
</snapshots>
|
||||||
|
</pluginRepository>
|
||||||
|
</pluginRepositories>
|
||||||
|
</profile>
|
||||||
|
</profiles>
|
||||||
|
|
||||||
</project>
|
</project>
|
@ -6,7 +6,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>spring-cloud-dependencies-parent</artifactId>
|
<artifactId>spring-cloud-dependencies-parent</artifactId>
|
||||||
<groupId>org.springframework.cloud</groupId>
|
<groupId>org.springframework.cloud</groupId>
|
||||||
<version>1.3.10.RELEASE</version>
|
<version>1.3.11.RELEASE</version>
|
||||||
<relativePath/>
|
<relativePath/>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
|
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
|
||||||
@ -117,7 +117,7 @@
|
|||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
<!-- Aliyun storage dependencies -->
|
<!-- Aliyun OSS dependencies -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.aliyun.oss</groupId>
|
<groupId>com.aliyun.oss</groupId>
|
||||||
<artifactId>aliyun-sdk-oss</artifactId>
|
<artifactId>aliyun-sdk-oss</artifactId>
|
||||||
@ -125,7 +125,7 @@
|
|||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
<!-- Own dependencies autoconfigure -->
|
<!-- Own dependencies -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.cloud</groupId>
|
<groupId>org.springframework.cloud</groupId>
|
||||||
<artifactId>spring-cloud-alibaba-sentinel</artifactId>
|
<artifactId>spring-cloud-alibaba-sentinel</artifactId>
|
||||||
@ -151,6 +151,21 @@
|
|||||||
<artifactId>spring-cloud-alibaba-nacos-config</artifactId>
|
<artifactId>spring-cloud-alibaba-nacos-config</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-alicloud-acm</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-alicloud-ans</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-alicloud-context</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- Own dependencies - Starters -->
|
<!-- Own dependencies - Starters -->
|
||||||
<dependency>
|
<dependency>
|
||||||
@ -176,7 +191,17 @@
|
|||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-starter-alicloud-ans</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-starter-alicloud-acm</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
<!-- Testing Dependencies -->
|
<!-- Testing Dependencies -->
|
||||||
|
|
||||||
|
|
||||||
|
@ -0,0 +1,27 @@
|
|||||||
|
<?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">
|
||||||
|
<parent>
|
||||||
|
<artifactId>spring-cloud-alibaba-examples</artifactId>
|
||||||
|
<groupId>org.springframework.cloud</groupId>
|
||||||
|
<version>0.1.0.BUILD-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<artifactId>acm-local-example</artifactId>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-starter-alicloud-acm</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.cloud.alibaba.cloud.examples;
|
||||||
|
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author xiaolongzuo
|
||||||
|
*/
|
||||||
|
@SpringBootApplication
|
||||||
|
@EnableDiscoveryClient
|
||||||
|
public class AcmApplication {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SpringApplication.run(AcmApplication.class, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.cloud.alibaba.cloud.examples;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author xiaolongzuo
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
public class EchoController {
|
||||||
|
|
||||||
|
private static final Logger LOGGER = LoggerFactory.getLogger(EchoController.class);
|
||||||
|
|
||||||
|
@Value("${user.id}")
|
||||||
|
private String userId;
|
||||||
|
|
||||||
|
@RequestMapping(value = "/")
|
||||||
|
public String echo() {
|
||||||
|
LOGGER.info("User id is " + userId);
|
||||||
|
return userId;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,5 @@
|
|||||||
|
spring.application.group=com.alibaba.acm
|
||||||
|
spring.application.name=acm-local
|
||||||
|
server.port=18089
|
||||||
|
spring.cloud.alicloud.acm.server-list=127.0.0.1
|
||||||
|
spring.cloud.alicloud.acm.server-port=8080
|
@ -0,0 +1,31 @@
|
|||||||
|
<?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">
|
||||||
|
<parent>
|
||||||
|
<artifactId>spring-cloud-alibaba-examples</artifactId>
|
||||||
|
<groupId>org.springframework.cloud</groupId>
|
||||||
|
<version>0.1.0.BUILD-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<artifactId>ans-consumer-feign-example</artifactId>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-starter-alicloud-ans</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-starter-feign</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.cloud.alibaba.cloud.examples;
|
||||||
|
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
import org.springframework.cloud.netflix.feign.EnableFeignClients;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author xiaolongzuo
|
||||||
|
*/
|
||||||
|
@SpringBootApplication
|
||||||
|
@EnableFeignClients(basePackages = { "org.springframework.cloud.alibaba.cloud.examples" })
|
||||||
|
public class ConsumerApplication {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SpringApplication.run(ConsumerApplication.class, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.cloud.alibaba.cloud.examples;
|
||||||
|
|
||||||
|
import org.springframework.cloud.netflix.feign.FeignClient;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author xiaolongzuo
|
||||||
|
*/
|
||||||
|
@FeignClient(value = "ans-provider")
|
||||||
|
public interface EchoService {
|
||||||
|
|
||||||
|
@RequestMapping(path = "echo/{str}")
|
||||||
|
String echo(@RequestParam("str") String param);
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.cloud.alibaba.cloud.examples;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMethod;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author xiaolongzuo
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
public class
|
||||||
|
HomeController {
|
||||||
|
|
||||||
|
private static final Logger LOGGER = LoggerFactory.getLogger(HomeController.class);
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private EchoService echoService;
|
||||||
|
|
||||||
|
@RequestMapping(value = "/", method = RequestMethod.GET, produces = "application/json")
|
||||||
|
public String home() {
|
||||||
|
LOGGER.info("-----------------consumer调用开始-----------------");
|
||||||
|
String param = "Nice to meet you.";
|
||||||
|
LOGGER.info("消费者传递参数:" + param);
|
||||||
|
String result = echoService.echo(param);
|
||||||
|
LOGGER.info("收到提供者响应:" + result);
|
||||||
|
return param + "<br>" + result;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,4 @@
|
|||||||
|
server.port=18083
|
||||||
|
# The following configuration can be omitted.
|
||||||
|
spring.cloud.alicloud.ans.server.list=127.0.0.1
|
||||||
|
spring.cloud.alicloud.ans.server.port=8080
|
@ -0,0 +1,27 @@
|
|||||||
|
<?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">
|
||||||
|
<parent>
|
||||||
|
<artifactId>spring-cloud-alibaba-examples</artifactId>
|
||||||
|
<groupId>org.springframework.cloud</groupId>
|
||||||
|
<version>0.1.0.BUILD-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<artifactId>ans-consumer-ribbon-example</artifactId>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-starter-alicloud-ans</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.cloud.alibaba.cloud.examples;
|
||||||
|
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
|
||||||
|
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.web.client.RestTemplate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author xiaolongzuo
|
||||||
|
*/
|
||||||
|
@SpringBootApplication
|
||||||
|
@EnableDiscoveryClient
|
||||||
|
public class ConsumerApplication {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@LoadBalanced
|
||||||
|
public RestTemplate restTemplate() {
|
||||||
|
return new RestTemplate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SpringApplication.run(ConsumerApplication.class, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.cloud.alibaba.cloud.examples;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMethod;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
import org.springframework.web.client.RestTemplate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author xiaolongzuo
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
public class HomeController {
|
||||||
|
|
||||||
|
private static final Logger LOGGER = LoggerFactory.getLogger(HomeController.class);
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private RestTemplate restTemplate;
|
||||||
|
|
||||||
|
@RequestMapping(value = "/", method = RequestMethod.GET, produces = "application/json")
|
||||||
|
public String home() {
|
||||||
|
LOGGER.info("-----------------consumer调用开始-----------------");
|
||||||
|
String param = "Nice to meet you.";
|
||||||
|
LOGGER.info("消费者传递参数:" + param);
|
||||||
|
String result = restTemplate.getForObject("http://ans-provider/echo/" + param, String.class);
|
||||||
|
LOGGER.info("收到提供者响应:" + result);
|
||||||
|
return param + "<br>" + result;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,4 @@
|
|||||||
|
server.port=18082
|
||||||
|
# The following configuration can be omitted.
|
||||||
|
spring.cloud.alicloud.ans.server.list=127.0.0.1
|
||||||
|
spring.cloud.alicloud.ans.server.port=8080
|
@ -0,0 +1,27 @@
|
|||||||
|
<?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">
|
||||||
|
<parent>
|
||||||
|
<artifactId>spring-cloud-alibaba-examples</artifactId>
|
||||||
|
<groupId>org.springframework.cloud</groupId>
|
||||||
|
<version>0.1.0.BUILD-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<artifactId>ans-provider-example</artifactId>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-starter-alicloud-ans</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.cloud.alibaba.cloud.examples;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMethod;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author xiaolongzuo
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
public class EchoController {
|
||||||
|
|
||||||
|
private static final Logger LOGGER = LoggerFactory.getLogger(EchoController.class);
|
||||||
|
|
||||||
|
@RequestMapping(value = "/echo/{str}", method = RequestMethod.GET, produces = "application/json")
|
||||||
|
public String echo(@PathVariable String str) {
|
||||||
|
LOGGER.info("-----------收到消费者请求-----------");
|
||||||
|
LOGGER.info("收到消费者传递的参数:" + str);
|
||||||
|
String result = "Nice to meet you, too.";
|
||||||
|
LOGGER.info("提供者返回结果:" + result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.cloud.alibaba.cloud.examples;
|
||||||
|
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author xiaolongzuo
|
||||||
|
*/
|
||||||
|
@SpringBootApplication
|
||||||
|
@EnableDiscoveryClient
|
||||||
|
public class ProviderApplication {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SpringApplication.run(ProviderApplication.class, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,4 @@
|
|||||||
|
spring.application.name=ans-provider
|
||||||
|
server.port=18081
|
||||||
|
spring.cloud.alicloud.ans.server.list=127.0.0.1
|
||||||
|
spring.cloud.alicloud.ans.server.port=8080
|
@ -19,8 +19,9 @@
|
|||||||
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
|
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
2. 在应用的 /src/main/resources/bootstrap.properties 配置文件中配置 Nacos Config 地址
|
2. 在应用的 /src/main/resources/bootstrap.properties 配置文件中配置 Nacos Config 元数据
|
||||||
|
|
||||||
|
spring.application.name=nacos-config-example
|
||||||
spring.cloud.nacos.config.server-addr=127.0.0.1:8848
|
spring.cloud.nacos.config.server-addr=127.0.0.1:8848
|
||||||
|
|
||||||
3. 完成上述两步后,应用会从 Nacos Config 中获取相应的配置,并添加在 Spring Environment 的 PropertySources 中。这里我们使用 @Value 注解来将对应的配置注入到 SampleController 的 userName 和 age 字段,并添加 @RefreshScope 打开动态刷新功能
|
3. 完成上述两步后,应用会从 Nacos Config 中获取相应的配置,并添加在 Spring Environment 的 PropertySources 中。这里我们使用 @Value 注解来将对应的配置注入到 SampleController 的 userName 和 age 字段,并添加 @RefreshScope 打开动态刷新功能
|
||||||
@ -70,8 +71,8 @@
|
|||||||
|
|
||||||
1. 增加配置,在应用的 /src/main/resources/application.properties 中添加基本配置信息
|
1. 增加配置,在应用的 /src/main/resources/application.properties 中添加基本配置信息
|
||||||
|
|
||||||
spring.application.name=nacos-config-example
|
|
||||||
server.port=18084
|
server.port=18084
|
||||||
|
management.endpoints.web.exposure.include=*
|
||||||
|
|
||||||
|
|
||||||
2. 启动应用,支持 IDE 直接启动和编译打包后启动。
|
2. 启动应用,支持 IDE 直接启动和编译打包后启动。
|
||||||
|
@ -19,8 +19,9 @@ Before we start the demo, let's learn how to connect Nacos Config to a Spring Cl
|
|||||||
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
|
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
2. Add Nacos server address configurations to file /src/main/resources/bootstrap.properties
|
2. Add Nacos config metadata configurations to file /src/main/resources/bootstrap.properties
|
||||||
|
|
||||||
|
spring.application.name=nacos-config-example
|
||||||
spring.cloud.nacos.config.server-addr=127.0.0.1:8848
|
spring.cloud.nacos.config.server-addr=127.0.0.1:8848
|
||||||
|
|
||||||
3. After completing the above two steps, the application will get the externalized configuration from Nacos Server and put it in the Spring Environment's PropertySources.We use the @Value annotation to inject the corresponding configuration into the userName and age fields of the SampleController, and add @RefreshScope to turn on dynamic refresh .
|
3. After completing the above two steps, the application will get the externalized configuration from Nacos Server and put it in the Spring Environment's PropertySources.We use the @Value annotation to inject the corresponding configuration into the userName and age fields of the SampleController, and add @RefreshScope to turn on dynamic refresh .
|
||||||
@ -70,8 +71,8 @@ Before we start the demo, let's learn how to connect Nacos Config to a Spring Cl
|
|||||||
|
|
||||||
1. Add necessary configurations to file /src/main/resources/application.properties
|
1. Add necessary configurations to file /src/main/resources/application.properties
|
||||||
|
|
||||||
spring.application.name=nacos-config-example
|
|
||||||
server.port=18084
|
server.port=18084
|
||||||
|
management.endpoints.web.exposure.include=*
|
||||||
|
|
||||||
|
|
||||||
2. Start the application in IDE or by building a fatjar.
|
2. Start the application in IDE or by building a fatjar.
|
||||||
|
@ -1,3 +1,2 @@
|
|||||||
spring.application.name=nacos-config-example
|
|
||||||
server.port=18084
|
server.port=18084
|
||||||
management.endpoints.web.exposure.include=*
|
management.endpoints.web.exposure.include=*
|
@ -1 +1,2 @@
|
|||||||
|
spring.application.name=nacos-config-example
|
||||||
spring.cloud.nacos.config.server-addr=127.0.0.1:8848
|
spring.cloud.nacos.config.server-addr=127.0.0.1:8848
|
@ -23,6 +23,10 @@
|
|||||||
<module>nacos-example/nacos-discovery-example</module>
|
<module>nacos-example/nacos-discovery-example</module>
|
||||||
<module>nacos-example/nacos-config-example</module>
|
<module>nacos-example/nacos-config-example</module>
|
||||||
<module>oss-example</module>
|
<module>oss-example</module>
|
||||||
|
<module>ans-example/ans-consumer-feign-example</module>
|
||||||
|
<module>ans-example/ans-consumer-ribbon-example</module>
|
||||||
|
<module>ans-example/ans-provider-example</module>
|
||||||
|
<module>acm-example/acm-local-example</module>
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
@ -16,8 +16,6 @@
|
|||||||
|
|
||||||
package org.springframework.cloud.alibaba.nacos;
|
package org.springframework.cloud.alibaba.nacos;
|
||||||
|
|
||||||
import com.alibaba.nacos.api.config.ConfigService;
|
|
||||||
|
|
||||||
import org.springframework.beans.BeansException;
|
import org.springframework.beans.BeansException;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.cloud.alibaba.nacos.refresh.NacosContextRefresher;
|
import org.springframework.cloud.alibaba.nacos.refresh.NacosContextRefresher;
|
||||||
@ -43,14 +41,6 @@ public class NacosConfigAutoConfiguration implements ApplicationContextAware {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private NacosRefreshProperties nacosRefreshProperties;
|
private NacosRefreshProperties nacosRefreshProperties;
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private ConfigService configService;
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public NacosConfigProperties nacosConfigProperties() {
|
|
||||||
return new NacosConfigProperties();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public NacosPropertySourceRepository nacosPropertySourceRepository() {
|
public NacosPropertySourceRepository nacosPropertySourceRepository() {
|
||||||
return new NacosPropertySourceRepository(applicationContext);
|
return new NacosPropertySourceRepository(applicationContext);
|
||||||
@ -69,10 +59,10 @@ public class NacosConfigAutoConfiguration implements ApplicationContextAware {
|
|||||||
@Bean
|
@Bean
|
||||||
public NacosContextRefresher nacosContextRefresher(ContextRefresher contextRefresher,
|
public NacosContextRefresher nacosContextRefresher(ContextRefresher contextRefresher,
|
||||||
NacosRefreshHistory refreshHistory,
|
NacosRefreshHistory refreshHistory,
|
||||||
NacosPropertySourceRepository propertySourceRepository,
|
NacosPropertySourceRepository propertySourceRepository) {
|
||||||
ConfigService configService) {
|
|
||||||
return new NacosContextRefresher(contextRefresher, nacosConfigProperties,
|
return new NacosContextRefresher(contextRefresher, nacosConfigProperties,
|
||||||
nacosRefreshProperties, refreshHistory, propertySourceRepository,configService);
|
nacosRefreshProperties, refreshHistory, propertySourceRepository,
|
||||||
|
nacosConfigProperties.configServiceInstance());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package org.springframework.cloud.alibaba.nacos;
|
package org.springframework.cloud.alibaba.nacos;
|
||||||
|
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
import org.springframework.cloud.alibaba.nacos.client.NacosPropertySourceLocator;
|
import org.springframework.cloud.alibaba.nacos.client.NacosPropertySourceLocator;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
@ -32,6 +33,7 @@ public class NacosConfigBootstrapConfiguration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
|
@ConditionalOnMissingBean
|
||||||
public NacosConfigProperties nacosConfigProperties() {
|
public NacosConfigProperties nacosConfigProperties() {
|
||||||
return new NacosConfigProperties();
|
return new NacosConfigProperties();
|
||||||
}
|
}
|
||||||
|
@ -16,9 +16,30 @@
|
|||||||
|
|
||||||
package org.springframework.cloud.alibaba.nacos;
|
package org.springframework.cloud.alibaba.nacos;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
import javax.annotation.PostConstruct;
|
||||||
|
|
||||||
|
import com.alibaba.nacos.api.NacosFactory;
|
||||||
|
import com.alibaba.nacos.api.config.ConfigService;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
import org.springframework.core.env.Environment;
|
import org.springframework.core.env.Environment;
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
|
import static com.alibaba.nacos.api.PropertyKeyConst.ACCESS_KEY;
|
||||||
|
import static com.alibaba.nacos.api.PropertyKeyConst.CLUSTER_NAME;
|
||||||
|
import static com.alibaba.nacos.api.PropertyKeyConst.CONTEXT_PATH;
|
||||||
|
import static com.alibaba.nacos.api.PropertyKeyConst.ENCODE;
|
||||||
|
import static com.alibaba.nacos.api.PropertyKeyConst.ENDPOINT;
|
||||||
|
import static com.alibaba.nacos.api.PropertyKeyConst.NAMESPACE;
|
||||||
|
import static com.alibaba.nacos.api.PropertyKeyConst.SECRET_KEY;
|
||||||
|
import static com.alibaba.nacos.api.PropertyKeyConst.SERVER_ADDR;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* nacos properties
|
* nacos properties
|
||||||
@ -29,6 +50,9 @@ import org.springframework.util.StringUtils;
|
|||||||
@ConfigurationProperties("spring.cloud.nacos.config")
|
@ConfigurationProperties("spring.cloud.nacos.config")
|
||||||
public class NacosConfigProperties {
|
public class NacosConfigProperties {
|
||||||
|
|
||||||
|
private static final Logger LOGGER = LoggerFactory
|
||||||
|
.getLogger(NacosConfigProperties.class);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* nacos config server address
|
* nacos config server address
|
||||||
*/
|
*/
|
||||||
@ -89,6 +113,21 @@ public class NacosConfigProperties {
|
|||||||
*/
|
*/
|
||||||
private String clusterName;
|
private String clusterName;
|
||||||
|
|
||||||
|
@Value("${spring.application.name}")
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
private String[] activeProfiles;
|
||||||
|
|
||||||
|
private ConfigService configService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private Environment environment;
|
||||||
|
|
||||||
|
@PostConstruct
|
||||||
|
public void init() {
|
||||||
|
this.activeProfiles = environment.getActiveProfiles();
|
||||||
|
}
|
||||||
|
|
||||||
// todo sts support
|
// todo sts support
|
||||||
|
|
||||||
public String getServerAddr() {
|
public String getServerAddr() {
|
||||||
@ -187,6 +226,14 @@ public class NacosConfigProperties {
|
|||||||
this.clusterName = clusterName;
|
this.clusterName = clusterName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String[] getActiveProfiles() {
|
||||||
|
return activeProfiles;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "NacosConfigProperties{" + "serverAddr='" + serverAddr + '\''
|
return "NacosConfigProperties{" + "serverAddr='" + serverAddr + '\''
|
||||||
@ -195,46 +242,32 @@ public class NacosConfigProperties {
|
|||||||
+ ", timeout=" + timeout + ", endpoint='" + endpoint + '\''
|
+ ", timeout=" + timeout + ", endpoint='" + endpoint + '\''
|
||||||
+ ", namespace='" + namespace + '\'' + ", accessKey='" + accessKey + '\''
|
+ ", namespace='" + namespace + '\'' + ", accessKey='" + accessKey + '\''
|
||||||
+ ", secretKey='" + secretKey + '\'' + ", contextPath='" + contextPath
|
+ ", secretKey='" + secretKey + '\'' + ", contextPath='" + contextPath
|
||||||
+ '\'' + ", clusterName='" + clusterName + '\'' + '}';
|
+ '\'' + ", clusterName='" + clusterName + '\'' + ", name='" + name + '\''
|
||||||
|
+ ", activeProfiles=" + Arrays.toString(activeProfiles) + '}';
|
||||||
}
|
}
|
||||||
|
|
||||||
public void overrideFromEnv(Environment env) {
|
public ConfigService configServiceInstance() {
|
||||||
|
|
||||||
if (StringUtils.isEmpty(this.getServerAddr())) {
|
if (null != configService) {
|
||||||
this.setServerAddr(
|
return configService;
|
||||||
env.resolvePlaceholders("${spring.cloud.nacos.config.server-addr:}"));
|
|
||||||
}
|
}
|
||||||
if (StringUtils.isEmpty(this.getEncode())) {
|
|
||||||
this.setEncode(
|
Properties properties = new Properties();
|
||||||
env.resolvePlaceholders("${spring.cloud.nacos.config.encode:}"));
|
properties.put(SERVER_ADDR, Objects.toString(this.serverAddr, ""));
|
||||||
|
properties.put(ENCODE, Objects.toString(this.encode, ""));
|
||||||
|
properties.put(NAMESPACE, Objects.toString(this.namespace, ""));
|
||||||
|
properties.put(ACCESS_KEY, Objects.toString(this.accessKey, ""));
|
||||||
|
properties.put(SECRET_KEY, Objects.toString(this.secretKey, ""));
|
||||||
|
properties.put(CONTEXT_PATH, Objects.toString(this.contextPath, ""));
|
||||||
|
properties.put(CLUSTER_NAME, Objects.toString(this.clusterName, ""));
|
||||||
|
properties.put(ENDPOINT, Objects.toString(this.endpoint, ""));
|
||||||
|
try {
|
||||||
|
configService = NacosFactory.createConfigService(properties);
|
||||||
|
return configService;
|
||||||
}
|
}
|
||||||
if (StringUtils.isEmpty(this.getNamespace())) {
|
catch (Exception e) {
|
||||||
this.setNamespace(
|
LOGGER.error("create config service error!properties={},e=,", this, e);
|
||||||
env.resolvePlaceholders("${spring.cloud.nacos.config.namespace:}"));
|
return null;
|
||||||
}
|
|
||||||
if (StringUtils.isEmpty(this.getAccessKey())) {
|
|
||||||
this.setAccessKey(
|
|
||||||
env.resolvePlaceholders("${spring.cloud.nacos.config.access-key:}"));
|
|
||||||
}
|
|
||||||
if (StringUtils.isEmpty(this.getSecretKey())) {
|
|
||||||
this.setSecretKey(
|
|
||||||
env.resolvePlaceholders("${spring.cloud.nacos.config.secret-key:}"));
|
|
||||||
}
|
|
||||||
if (StringUtils.isEmpty(this.getContextPath())) {
|
|
||||||
this.setContextPath(env
|
|
||||||
.resolvePlaceholders("${spring.cloud.nacos.config.context-path:}"));
|
|
||||||
}
|
|
||||||
if (StringUtils.isEmpty(this.getClusterName())) {
|
|
||||||
this.setClusterName(env
|
|
||||||
.resolvePlaceholders("${spring.cloud.nacos.config.cluster-name:}"));
|
|
||||||
}
|
|
||||||
if (StringUtils.isEmpty(this.getEndpoint())) {
|
|
||||||
this.setEndpoint(
|
|
||||||
env.resolvePlaceholders("${spring.cloud.nacos.config.endpoint:}"));
|
|
||||||
}
|
|
||||||
if (StringUtils.isEmpty(this.getPrefix())) {
|
|
||||||
this.setPrefix(
|
|
||||||
env.resolvePlaceholders("${spring.cloud.nacos.config.prefix:}"));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -83,7 +83,6 @@ public class NacosPropertySourceBuilder {
|
|||||||
String data = null;
|
String data = null;
|
||||||
try {
|
try {
|
||||||
data = configService.getConfig(dataId, group, timeout);
|
data = configService.getConfig(dataId, group, timeout);
|
||||||
// todo add file extension yaml support
|
|
||||||
if (!StringUtils.isEmpty(data)) {
|
if (!StringUtils.isEmpty(data)) {
|
||||||
logger.info(String.format("Loading nacos data, dataId: '%s', group: '%s'",
|
logger.info(String.format("Loading nacos data, dataId: '%s', group: '%s'",
|
||||||
dataId, group));
|
dataId, group));
|
||||||
|
@ -16,12 +16,9 @@
|
|||||||
|
|
||||||
package org.springframework.cloud.alibaba.nacos.client;
|
package org.springframework.cloud.alibaba.nacos.client;
|
||||||
|
|
||||||
import java.util.Properties;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
|
||||||
import org.springframework.cloud.alibaba.nacos.NacosConfigProperties;
|
import org.springframework.cloud.alibaba.nacos.NacosConfigProperties;
|
||||||
import org.springframework.cloud.bootstrap.config.PropertySourceLocator;
|
import org.springframework.cloud.bootstrap.config.PropertySourceLocator;
|
||||||
import org.springframework.core.annotation.Order;
|
import org.springframework.core.annotation.Order;
|
||||||
@ -30,11 +27,7 @@ import org.springframework.core.env.Environment;
|
|||||||
import org.springframework.core.env.PropertySource;
|
import org.springframework.core.env.PropertySource;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
import com.alibaba.nacos.api.NacosFactory;
|
|
||||||
import com.alibaba.nacos.api.config.ConfigService;
|
import com.alibaba.nacos.api.config.ConfigService;
|
||||||
import com.alibaba.nacos.api.exception.NacosException;
|
|
||||||
|
|
||||||
import static com.alibaba.nacos.api.PropertyKeyConst.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author xiaojing
|
* @author xiaojing
|
||||||
@ -48,47 +41,15 @@ public class NacosPropertySourceLocator implements PropertySourceLocator {
|
|||||||
private static final String SEP1 = "-";
|
private static final String SEP1 = "-";
|
||||||
private static final String DOT = ".";
|
private static final String DOT = ".";
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private ConfigurableListableBeanFactory beanFactory;
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private NacosConfigProperties nacosConfigProperties;
|
private NacosConfigProperties nacosConfigProperties;
|
||||||
|
|
||||||
private ConfigService configService;
|
|
||||||
|
|
||||||
private NacosPropertySourceBuilder nacosPropertySourceBuilder;
|
private NacosPropertySourceBuilder nacosPropertySourceBuilder;
|
||||||
|
|
||||||
private Properties getPropertiesFromEnv(Environment env) {
|
|
||||||
|
|
||||||
nacosConfigProperties.overrideFromEnv(env);
|
|
||||||
|
|
||||||
Properties properties = new Properties();
|
|
||||||
properties.put(SERVER_ADDR, nacosConfigProperties.getServerAddr());
|
|
||||||
properties.put(ENCODE, nacosConfigProperties.getEncode());
|
|
||||||
properties.put(NAMESPACE, nacosConfigProperties.getNamespace());
|
|
||||||
properties.put(ACCESS_KEY, nacosConfigProperties.getAccessKey());
|
|
||||||
properties.put(SECRET_KEY, nacosConfigProperties.getSecretKey());
|
|
||||||
properties.put(CONTEXT_PATH, nacosConfigProperties.getContextPath());
|
|
||||||
properties.put(CLUSTER_NAME, nacosConfigProperties.getClusterName());
|
|
||||||
properties.put(ENDPOINT, nacosConfigProperties.getEndpoint());
|
|
||||||
return properties;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PropertySource<?> locate(Environment env) {
|
public PropertySource<?> locate(Environment env) {
|
||||||
|
|
||||||
Properties properties = getPropertiesFromEnv(env);
|
ConfigService configService = nacosConfigProperties.configServiceInstance();
|
||||||
|
|
||||||
try {
|
|
||||||
configService = NacosFactory.createConfigService(properties);
|
|
||||||
}
|
|
||||||
catch (NacosException e) {
|
|
||||||
logger.error("create config service error, nacosConfigProperties:{}, ",
|
|
||||||
properties, e);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
beanFactory.registerSingleton("configService", configService);
|
|
||||||
|
|
||||||
if (null == configService) {
|
if (null == configService) {
|
||||||
logger.warn(
|
logger.warn(
|
||||||
@ -99,13 +60,12 @@ public class NacosPropertySourceLocator implements PropertySourceLocator {
|
|||||||
nacosPropertySourceBuilder = new NacosPropertySourceBuilder(configService,
|
nacosPropertySourceBuilder = new NacosPropertySourceBuilder(configService,
|
||||||
timeout);
|
timeout);
|
||||||
|
|
||||||
String applicationName = env.getProperty("spring.application.name");
|
String name = nacosConfigProperties.getName();
|
||||||
logger.info("Initialize spring.application.name '" + applicationName + "'.");
|
|
||||||
|
|
||||||
String nacosGroup = nacosConfigProperties.getGroup();
|
String nacosGroup = nacosConfigProperties.getGroup();
|
||||||
String dataIdPrefix = nacosConfigProperties.getPrefix();
|
String dataIdPrefix = nacosConfigProperties.getPrefix();
|
||||||
if (StringUtils.isEmpty(dataIdPrefix)) {
|
if (StringUtils.isEmpty(dataIdPrefix)) {
|
||||||
dataIdPrefix = applicationName;
|
dataIdPrefix = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
String fileExtension = nacosConfigProperties.getFileExtension();
|
String fileExtension = nacosConfigProperties.getFileExtension();
|
||||||
@ -113,23 +73,21 @@ public class NacosPropertySourceLocator implements PropertySourceLocator {
|
|||||||
CompositePropertySource composite = new CompositePropertySource(
|
CompositePropertySource composite = new CompositePropertySource(
|
||||||
NACOS_PROPERTY_SOURCE_NAME);
|
NACOS_PROPERTY_SOURCE_NAME);
|
||||||
|
|
||||||
loadApplicationConfiguration(composite, env, nacosGroup, dataIdPrefix,
|
loadApplicationConfiguration(composite, nacosGroup, dataIdPrefix, fileExtension);
|
||||||
fileExtension);
|
|
||||||
|
|
||||||
return composite;
|
return composite;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadApplicationConfiguration(
|
private void loadApplicationConfiguration(
|
||||||
CompositePropertySource compositePropertySource, Environment environment,
|
CompositePropertySource compositePropertySource, String nacosGroup,
|
||||||
String nacosGroup, String dataIdPrefix, String fileExtension) {
|
String dataIdPrefix, String fileExtension) {
|
||||||
loadNacosDataIfPresent(compositePropertySource,
|
loadNacosDataIfPresent(compositePropertySource,
|
||||||
dataIdPrefix + DOT + fileExtension, nacosGroup, fileExtension);
|
dataIdPrefix + DOT + fileExtension, nacosGroup, fileExtension);
|
||||||
for (String profile : environment.getActiveProfiles()) {
|
for (String profile : nacosConfigProperties.getActiveProfiles()) {
|
||||||
String dataId = dataIdPrefix + SEP1 + profile + DOT + fileExtension;
|
String dataId = dataIdPrefix + SEP1 + profile + DOT + fileExtension;
|
||||||
loadNacosDataIfPresent(compositePropertySource, dataId, nacosGroup,
|
loadNacosDataIfPresent(compositePropertySource, dataId, nacosGroup,
|
||||||
fileExtension);
|
fileExtension);
|
||||||
}
|
}
|
||||||
// todo multi profile active order and priority
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadNacosDataIfPresent(final CompositePropertySource composite,
|
private void loadNacosDataIfPresent(final CompositePropertySource composite,
|
||||||
|
@ -44,15 +44,6 @@ public class NacosConfigEndpointAutoConfiguration {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private NacosPropertySourceRepository nacosPropertySourceRepository;
|
private NacosPropertySourceRepository nacosPropertySourceRepository;
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private ConfigService configService;
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
@ConditionalOnBean
|
|
||||||
public NacosConfigProperties nacosConfigProperties() {
|
|
||||||
return new NacosConfigProperties();
|
|
||||||
}
|
|
||||||
|
|
||||||
@ConditionalOnMissingBean
|
@ConditionalOnMissingBean
|
||||||
@Bean
|
@Bean
|
||||||
public NacosConfigEndpoint nacosConfigEndpoint() {
|
public NacosConfigEndpoint nacosConfigEndpoint() {
|
||||||
@ -64,6 +55,7 @@ public class NacosConfigEndpointAutoConfiguration {
|
|||||||
public NacosConfigHealthIndicator nacosConfigHealthIndicator(
|
public NacosConfigHealthIndicator nacosConfigHealthIndicator(
|
||||||
NacosPropertySourceRepository nacosPropertySourceRepository) {
|
NacosPropertySourceRepository nacosPropertySourceRepository) {
|
||||||
return new NacosConfigHealthIndicator(nacosConfigProperties,
|
return new NacosConfigHealthIndicator(nacosConfigProperties,
|
||||||
nacosPropertySourceRepository, configService);
|
nacosPropertySourceRepository,
|
||||||
|
nacosConfigProperties.configServiceInstance());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,12 +44,11 @@ public class NacosConfigAutoConfigurationTests {
|
|||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
this.context = new SpringApplicationBuilder(
|
this.context = new SpringApplicationBuilder(
|
||||||
NacosConfigBootstrapConfiguration.class,
|
NacosConfigBootstrapConfiguration.class,
|
||||||
NacosConfigAutoConfiguration.class,
|
NacosConfigAutoConfiguration.class, TestConfiguration.class).web(false)
|
||||||
TestConfiguration.class)
|
.run("--spring.application.name=myapp",
|
||||||
.web(false).run(
|
|
||||||
"--spring.cloud.config.enabled=true",
|
"--spring.cloud.config.enabled=true",
|
||||||
"--spring.cloud.nacos.config.server-addr=127.0.0.1:8080",
|
"--spring.cloud.nacos.config.server-addr=127.0.0.1:8080",
|
||||||
"--spring.cloud.nacos.config.prefix=myapp");
|
"--spring.cloud.nacos.config.prefix=test");
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
@ -61,40 +60,32 @@ public class NacosConfigAutoConfigurationTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testNacosConfigProperties() {
|
public void testNacosConfigProperties() {
|
||||||
|
NacosConfigProperties nacosConfigProperties = this.context.getParent()
|
||||||
NacosPropertySourceLocator nacosPropertySourceLocator = this.context.getBean(NacosPropertySourceLocator.class);
|
.getBean(NacosConfigProperties.class);
|
||||||
Environment environment = this.context.getEnvironment();
|
|
||||||
try{
|
|
||||||
nacosPropertySourceLocator.locate(environment);
|
|
||||||
}catch (Exception e){
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
NacosConfigProperties nacosConfigProperties = this.context.getBean(NacosConfigProperties.class);
|
|
||||||
assertThat(nacosConfigProperties.getFileExtension()).isEqualTo("properties");
|
assertThat(nacosConfigProperties.getFileExtension()).isEqualTo("properties");
|
||||||
assertThat(nacosConfigProperties.getPrefix()).isEqualTo("myapp");
|
assertThat(nacosConfigProperties.getPrefix()).isEqualTo("test");
|
||||||
|
assertThat(nacosConfigProperties.getName()).isEqualTo("myapp");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testNacosRefreshProperties() {
|
public void testNacosRefreshProperties() {
|
||||||
|
|
||||||
NacosRefreshProperties nacosRefreshProperties = this.context.getBean(NacosRefreshProperties.class);
|
NacosRefreshProperties nacosRefreshProperties = this.context
|
||||||
|
.getBean(NacosRefreshProperties.class);
|
||||||
assertThat(nacosRefreshProperties.isEnabled()).isEqualTo(true);
|
assertThat(nacosRefreshProperties.isEnabled()).isEqualTo(true);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@AutoConfigureBefore(NacosConfigAutoConfiguration.class)
|
@AutoConfigureBefore(NacosConfigAutoConfiguration.class)
|
||||||
static class TestConfiguration{
|
static class TestConfiguration {
|
||||||
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
ConfigurableApplicationContext context;
|
ConfigurableApplicationContext context;
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
ContextRefresher contextRefresher(){
|
ContextRefresher contextRefresher() {
|
||||||
return new ContextRefresher(context, new RefreshScope());
|
return new ContextRefresher(context, new RefreshScope());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,6 +42,7 @@ public class NacosConfigBootstrapConfigurationTests {
|
|||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
this.context = new SpringApplicationBuilder(
|
this.context = new SpringApplicationBuilder(
|
||||||
NacosConfigBootstrapConfiguration.class).web(false).run(
|
NacosConfigBootstrapConfiguration.class).web(false).run(
|
||||||
|
"--spring.application.name=true",
|
||||||
"--spring.cloud.config.enabled=true",
|
"--spring.cloud.config.enabled=true",
|
||||||
"--spring.cloud.nacos.config.server-addr=127.0.0.1:8080",
|
"--spring.cloud.nacos.config.server-addr=127.0.0.1:8080",
|
||||||
"--spring.cloud.nacos.config.prefix=myapp");
|
"--spring.cloud.nacos.config.prefix=myapp");
|
||||||
@ -67,15 +68,14 @@ public class NacosConfigBootstrapConfigurationTests {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Field configServiceField = ReflectionUtils
|
Field nacosConfigPropertiesField = ReflectionUtils
|
||||||
.findField(NacosPropertySourceLocator.class, "configService");
|
.findField(NacosPropertySourceLocator.class, "nacosConfigProperties");
|
||||||
configServiceField.setAccessible(true);
|
nacosConfigPropertiesField.setAccessible(true);
|
||||||
|
|
||||||
ConfigService configService = (ConfigService) ReflectionUtils
|
NacosConfigProperties configService = (NacosConfigProperties) ReflectionUtils
|
||||||
.getField(configServiceField, locator);
|
.getField(nacosConfigPropertiesField, locator);
|
||||||
|
|
||||||
assertThat(configService).isNotNull();
|
assertThat(configService).isNotNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -195,30 +195,44 @@ public class SentinelDataSourcePostProcessor
|
|||||||
|
|
||||||
@EventListener(classes = ApplicationReadyEvent.class)
|
@EventListener(classes = ApplicationReadyEvent.class)
|
||||||
public void appStartedListener(ApplicationReadyEvent event) throws Exception {
|
public void appStartedListener(ApplicationReadyEvent event) throws Exception {
|
||||||
|
logger.info("[Sentinel Starter] Start to find ReadableDataSource");
|
||||||
Map<String, ReadableDataSource> dataSourceMap = event.getApplicationContext().getBeansOfType(
|
Map<String, ReadableDataSource> dataSourceMap = event.getApplicationContext().getBeansOfType(
|
||||||
ReadableDataSource.class);
|
ReadableDataSource.class);
|
||||||
if (dataSourceMap.size() == 1) {
|
if (dataSourceMap.size() == 1) {
|
||||||
|
logger.info("[Sentinel Starter] There exists only one ReadableDataSource named {}, start to load rules",
|
||||||
|
dataSourceMap.keySet().iterator().next());
|
||||||
ReadableDataSource dataSource = dataSourceMap.values().iterator().next();
|
ReadableDataSource dataSource = dataSourceMap.values().iterator().next();
|
||||||
Object ruleConfig = dataSource.loadConfig();
|
Object ruleConfig = dataSource.loadConfig();
|
||||||
SentinelProperty sentinelProperty = dataSource.getProperty();
|
SentinelProperty sentinelProperty = dataSource.getProperty();
|
||||||
if (checkRuleType(ruleConfig, FlowRule.class)) {
|
Integer rulesNum;
|
||||||
|
if ((rulesNum = checkRuleType(ruleConfig, FlowRule.class)) > 0) {
|
||||||
FlowRuleManager.register2Property(sentinelProperty);
|
FlowRuleManager.register2Property(sentinelProperty);
|
||||||
|
logger.info("[Sentinel Starter] load {} flow rules", rulesNum);
|
||||||
}
|
}
|
||||||
if (checkRuleType(ruleConfig, DegradeRule.class)) {
|
if ((rulesNum = checkRuleType(ruleConfig, DegradeRule.class)) > 0) {
|
||||||
DegradeRuleManager.register2Property(sentinelProperty);
|
DegradeRuleManager.register2Property(sentinelProperty);
|
||||||
|
logger.info("[Sentinel Starter] load {} degrade rules", rulesNum);
|
||||||
}
|
}
|
||||||
if (checkRuleType(ruleConfig, SystemRule.class)) {
|
if ((rulesNum = checkRuleType(ruleConfig, SystemRule.class)) > 0) {
|
||||||
SystemRuleManager.register2Property(sentinelProperty);
|
SystemRuleManager.register2Property(sentinelProperty);
|
||||||
|
logger.info("[Sentinel Starter] load {} system rules", rulesNum);
|
||||||
}
|
}
|
||||||
if (checkRuleType(ruleConfig, AuthorityRule.class)) {
|
if ((rulesNum = checkRuleType(ruleConfig, AuthorityRule.class)) > 0) {
|
||||||
AuthorityRuleManager.register2Property(sentinelProperty);
|
AuthorityRuleManager.register2Property(sentinelProperty);
|
||||||
|
logger.info("[Sentinel Starter] load {} authority rules", rulesNum);
|
||||||
}
|
}
|
||||||
|
} else if (dataSourceMap.size() > 1) {
|
||||||
|
logger.warn(
|
||||||
|
"[Sentinel Starter] There exists more than one ReadableDataSource, can not choose which one to load");
|
||||||
|
} else {
|
||||||
|
logger.warn(
|
||||||
|
"[Sentinel Starter] No ReadableDataSource exists");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean checkRuleType(Object ruleConfig, Class type) {
|
private Integer checkRuleType(Object ruleConfig, Class type) {
|
||||||
if (ruleConfig.getClass() == type) {
|
if (ruleConfig.getClass() == type) {
|
||||||
return true;
|
return 1;
|
||||||
} else if (ruleConfig instanceof List) {
|
} else if (ruleConfig instanceof List) {
|
||||||
List ruleList = (List)ruleConfig;
|
List ruleList = (List)ruleConfig;
|
||||||
List checkList = new ArrayList();
|
List checkList = new ArrayList();
|
||||||
@ -228,10 +242,10 @@ public class SentinelDataSourcePostProcessor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ruleList.size() == checkList.size()) {
|
if (ruleList.size() == checkList.size()) {
|
||||||
return true;
|
return ruleList.size();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
class SentinelDataSourceField {
|
class SentinelDataSourceField {
|
||||||
|
71
spring-cloud-alicloud-acm/pom.xml
Normal file
71
spring-cloud-alicloud-acm/pom.xml
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
<?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>
|
||||||
|
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>org.springframework.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-alibaba</artifactId>
|
||||||
|
<version>0.1.0.BUILD-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>spring-cloud-alicloud-acm</artifactId>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-alicloud-context</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.aliyun</groupId>
|
||||||
|
<artifactId>aliyun-java-sdk-core</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.aliyun</groupId>
|
||||||
|
<artifactId>aliyun-java-sdk-edas</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba.edas.acm</groupId>
|
||||||
|
<artifactId>acm-sdk</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-autoconfigure</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Spring Cloud -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-context</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-commons</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
||||||
|
|
@ -0,0 +1,73 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.cloud.alicloud.acm;
|
||||||
|
|
||||||
|
import com.taobao.diamond.client.Diamond;
|
||||||
|
import org.springframework.beans.BeansException;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||||
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
|
import org.springframework.cloud.alicloud.acm.endpoint.AcmHealthIndicator;
|
||||||
|
import org.springframework.cloud.alicloud.acm.refresh.AcmContextRefresher;
|
||||||
|
import org.springframework.cloud.alicloud.acm.refresh.AcmRefreshHistory;
|
||||||
|
import org.springframework.cloud.alicloud.context.acm.AcmProperties;
|
||||||
|
import org.springframework.cloud.context.refresh.ContextRefresher;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.context.ApplicationContextAware;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created on 01/10/2017.
|
||||||
|
*
|
||||||
|
* @author juven.xuxb
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
@ConditionalOnClass({Diamond.class})
|
||||||
|
@EnableConfigurationProperties(AcmProperties.class)
|
||||||
|
public class AcmAutoConfiguration implements ApplicationContextAware {
|
||||||
|
|
||||||
|
private ApplicationContext applicationContext;
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public AcmPropertySourceRepository acmPropertySourceRepository() {
|
||||||
|
return new AcmPropertySourceRepository(applicationContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public AcmHealthIndicator acmHealthIndicator(AcmProperties acmProperties,
|
||||||
|
AcmPropertySourceRepository acmPropertySourceRepository) {
|
||||||
|
return new AcmHealthIndicator(acmProperties, acmPropertySourceRepository);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public AcmRefreshHistory acmRefreshHistory() {
|
||||||
|
return new AcmRefreshHistory();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public AcmContextRefresher acmContextRefresher(AcmProperties acmProperties, ContextRefresher contextRefresher,
|
||||||
|
AcmRefreshHistory refreshHistory,
|
||||||
|
AcmPropertySourceRepository propertySourceRepository) {
|
||||||
|
return new AcmContextRefresher(contextRefresher, acmProperties, refreshHistory, propertySourceRepository);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setApplicationContext(ApplicationContext applicationContext)
|
||||||
|
throws BeansException {
|
||||||
|
this.applicationContext = applicationContext;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.cloud.alicloud.acm;
|
||||||
|
|
||||||
|
import org.springframework.cloud.alicloud.acm.bootstrap.AcmPropertySource;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
|
import org.springframework.core.env.CompositePropertySource;
|
||||||
|
import org.springframework.core.env.PropertySource;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author juven.xuxb, 5/17/16.
|
||||||
|
*/
|
||||||
|
public class AcmPropertySourceRepository {
|
||||||
|
|
||||||
|
private final ApplicationContext applicationContext;
|
||||||
|
|
||||||
|
public AcmPropertySourceRepository(ApplicationContext applicationContext) {
|
||||||
|
this.applicationContext = applicationContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get all acm properties from application context
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public List<AcmPropertySource> getAll() {
|
||||||
|
List<AcmPropertySource> result = new ArrayList<>();
|
||||||
|
ConfigurableApplicationContext ctx = (ConfigurableApplicationContext) applicationContext;
|
||||||
|
for (PropertySource p : ctx.getEnvironment().getPropertySources()) {
|
||||||
|
if (p instanceof AcmPropertySource) {
|
||||||
|
result.add((AcmPropertySource) p);
|
||||||
|
}
|
||||||
|
else if (p instanceof CompositePropertySource) {
|
||||||
|
collectAcmPropertySources((CompositePropertySource) p, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void collectAcmPropertySources(CompositePropertySource composite,
|
||||||
|
List<AcmPropertySource> result) {
|
||||||
|
for (PropertySource p : composite.getPropertySources()) {
|
||||||
|
if (p instanceof AcmPropertySource) {
|
||||||
|
result.add((AcmPropertySource) p);
|
||||||
|
}
|
||||||
|
else if (p instanceof CompositePropertySource) {
|
||||||
|
collectAcmPropertySources((CompositePropertySource) p, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.cloud.alicloud.acm.bootstrap;
|
||||||
|
|
||||||
|
import org.springframework.core.env.MapPropertySource;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author juven.xuxb
|
||||||
|
* @author xiaolongzuo
|
||||||
|
*/
|
||||||
|
public class AcmPropertySource extends MapPropertySource {
|
||||||
|
|
||||||
|
private final String dataId;
|
||||||
|
|
||||||
|
private final Date timestamp;
|
||||||
|
|
||||||
|
private final boolean groupLevel;
|
||||||
|
|
||||||
|
AcmPropertySource(String dataId, Map<String, Object> source, Date timestamp,
|
||||||
|
boolean groupLevel) {
|
||||||
|
super(dataId, source);
|
||||||
|
this.dataId = dataId;
|
||||||
|
this.timestamp = timestamp;
|
||||||
|
this.groupLevel = groupLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDataId() {
|
||||||
|
return dataId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getTimestamp() {
|
||||||
|
return timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isGroupLevel() {
|
||||||
|
return groupLevel;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,96 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.cloud.alicloud.acm.bootstrap;
|
||||||
|
|
||||||
|
import com.alibaba.edas.acm.ConfigService;
|
||||||
|
import com.alibaba.edas.acm.exception.ConfigException;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
|
||||||
|
import org.springframework.core.io.ByteArrayResource;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import java.io.StringReader;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author juven.xuxb
|
||||||
|
* @author xiaolongzuo
|
||||||
|
*/
|
||||||
|
class AcmPropertySourceBuilder {
|
||||||
|
|
||||||
|
private Logger logger = LoggerFactory.getLogger(AcmPropertySourceBuilder.class);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 传入 ACM 的 DataId 和 groupID,获取到解析后的 AcmProperty 对象
|
||||||
|
*
|
||||||
|
* @param dataId
|
||||||
|
* @param diamondGroup
|
||||||
|
* @param groupLevel
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
AcmPropertySource build(String dataId, String diamondGroup, boolean groupLevel) {
|
||||||
|
Properties properties = loadDiamondData(dataId, diamondGroup);
|
||||||
|
if (properties == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return new AcmPropertySource(dataId, toMap(properties), new Date(), groupLevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Properties loadDiamondData(String dataId, String diamondGroup) {
|
||||||
|
try {
|
||||||
|
String data = ConfigService.getConfig(dataId, diamondGroup, 3000L);
|
||||||
|
if (StringUtils.isEmpty(data)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (dataId.endsWith(".properties")) {
|
||||||
|
Properties properties = new Properties();
|
||||||
|
logger.info(String.format("Loading acm data, dataId: '%s', group: '%s'",
|
||||||
|
dataId, diamondGroup));
|
||||||
|
properties.load(new StringReader(data));
|
||||||
|
return properties;
|
||||||
|
} else if (dataId.endsWith(".yaml") || dataId.endsWith(".yml")) {
|
||||||
|
YamlPropertiesFactoryBean yamlFactory = new YamlPropertiesFactoryBean();
|
||||||
|
yamlFactory.setResources(new ByteArrayResource(data.getBytes()));
|
||||||
|
return yamlFactory.getObject();
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
if (e instanceof ConfigException) {
|
||||||
|
logger.error("DIAMOND-100500:" + dataId + ", " + e.toString(), e);
|
||||||
|
} else {
|
||||||
|
logger.error("DIAMOND-100500:" + dataId, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private Map<String, Object> toMap(Properties properties) {
|
||||||
|
Map<String, Object> result = new HashMap<>();
|
||||||
|
Enumeration<String> keys = (Enumeration<String>)properties.propertyNames();
|
||||||
|
while (keys.hasMoreElements()) {
|
||||||
|
String key = keys.nextElement();
|
||||||
|
Object value = properties.getProperty(key);
|
||||||
|
if (value != null) {
|
||||||
|
result.put(key, ((String)value).trim());
|
||||||
|
} else {
|
||||||
|
result.put(key, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,69 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.cloud.alicloud.acm.bootstrap;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.cloud.alicloud.context.acm.AcmIntegrationProperties;
|
||||||
|
import org.springframework.cloud.bootstrap.config.PropertySourceLocator;
|
||||||
|
import org.springframework.core.env.CompositePropertySource;
|
||||||
|
import org.springframework.core.env.Environment;
|
||||||
|
import org.springframework.core.env.PropertySource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author juven.xuxb
|
||||||
|
* @author xiaolongzuo
|
||||||
|
*/
|
||||||
|
public class AcmPropertySourceLocator implements PropertySourceLocator {
|
||||||
|
|
||||||
|
private static final String DIAMOND_PROPERTY_SOURCE_NAME = "diamond";
|
||||||
|
|
||||||
|
private static String defaultDiamondGroup = "DEFAULT_GROUP";
|
||||||
|
|
||||||
|
private AcmPropertySourceBuilder acmPropertySourceBuilder = new AcmPropertySourceBuilder();
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private AcmIntegrationProperties acmIntegrationProperties;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PropertySource<?> locate(Environment environment) {
|
||||||
|
|
||||||
|
CompositePropertySource compositePropertySource = new CompositePropertySource(
|
||||||
|
DIAMOND_PROPERTY_SOURCE_NAME);
|
||||||
|
|
||||||
|
for (String dataId : acmIntegrationProperties.getGroupConfigurationDataIds()) {
|
||||||
|
loadDiamondDataIfPresent(compositePropertySource, dataId, defaultDiamondGroup,
|
||||||
|
true);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (String dataId : acmIntegrationProperties
|
||||||
|
.getApplicationConfigurationDataIds()) {
|
||||||
|
loadDiamondDataIfPresent(compositePropertySource, dataId, defaultDiamondGroup,
|
||||||
|
false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return compositePropertySource;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadDiamondDataIfPresent(final CompositePropertySource composite,
|
||||||
|
final String dataId, final String diamondGroup, final boolean groupLevel) {
|
||||||
|
AcmPropertySource ps = acmPropertySourceBuilder.build(dataId, diamondGroup,
|
||||||
|
groupLevel);
|
||||||
|
if (ps != null) {
|
||||||
|
composite.addFirstPropertySource(ps);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.cloud.alicloud.acm.diagnostics.analyzer;
|
||||||
|
|
||||||
|
import org.springframework.boot.diagnostics.AbstractFailureAnalyzer;
|
||||||
|
import org.springframework.boot.diagnostics.FailureAnalysis;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A {@code FailureAnalyzer} that performs analysis of failures caused by a
|
||||||
|
* {@code DiamondConnectionFailureException}.
|
||||||
|
*
|
||||||
|
* @author juven.xuxb, 07/11/2016.
|
||||||
|
*/
|
||||||
|
public class DiamondConnectionFailureAnalyzer
|
||||||
|
extends AbstractFailureAnalyzer<DiamondConnectionFailureException> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected FailureAnalysis analyze(Throwable rootFailure,
|
||||||
|
DiamondConnectionFailureException cause) {
|
||||||
|
return new FailureAnalysis(
|
||||||
|
"Application failed to connect to Diamond, unable to access http://"
|
||||||
|
+ cause.getDomain() + ":" + cause.getPort()
|
||||||
|
+ "/diamond-server/diamond",
|
||||||
|
"config the right endpoint", cause);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.cloud.alicloud.acm.diagnostics.analyzer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A {@code DiamondConnectionFailureException} is thrown when the application fails to
|
||||||
|
* connect to Diamond Server.
|
||||||
|
*
|
||||||
|
* @author juven.xuxb, 07/11/2016.
|
||||||
|
*/
|
||||||
|
public class DiamondConnectionFailureException extends RuntimeException {
|
||||||
|
|
||||||
|
private final String domain;
|
||||||
|
|
||||||
|
private final String port;
|
||||||
|
|
||||||
|
public DiamondConnectionFailureException(String domain, String port, String message) {
|
||||||
|
super(message);
|
||||||
|
this.domain = domain;
|
||||||
|
this.port = port;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DiamondConnectionFailureException(String domain, String port, String message,
|
||||||
|
Throwable cause) {
|
||||||
|
super(message, cause);
|
||||||
|
this.domain = domain;
|
||||||
|
this.port = port;
|
||||||
|
}
|
||||||
|
|
||||||
|
String getDomain() {
|
||||||
|
return domain;
|
||||||
|
}
|
||||||
|
|
||||||
|
String getPort() {
|
||||||
|
return port;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,76 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.cloud.alicloud.acm.endpoint;
|
||||||
|
|
||||||
|
import org.springframework.boot.actuate.endpoint.AbstractEndpoint;
|
||||||
|
import org.springframework.cloud.alicloud.acm.AcmPropertySourceRepository;
|
||||||
|
import org.springframework.cloud.alicloud.acm.bootstrap.AcmPropertySource;
|
||||||
|
import org.springframework.cloud.alicloud.acm.refresh.AcmRefreshHistory;
|
||||||
|
import org.springframework.cloud.alicloud.context.acm.AcmProperties;
|
||||||
|
|
||||||
|
import java.text.DateFormat;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created on 01/10/2017.
|
||||||
|
*
|
||||||
|
* @author juven.xuxb
|
||||||
|
*/
|
||||||
|
public class AcmEndpoint extends AbstractEndpoint<Map<String, Object>> {
|
||||||
|
|
||||||
|
private final AcmProperties properties;
|
||||||
|
|
||||||
|
private final AcmRefreshHistory refreshHistory;
|
||||||
|
|
||||||
|
private final AcmPropertySourceRepository propertySourceRepository;
|
||||||
|
|
||||||
|
private DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||||
|
|
||||||
|
public AcmEndpoint(AcmProperties properties, AcmRefreshHistory refreshHistory,
|
||||||
|
AcmPropertySourceRepository propertySourceRepository) {
|
||||||
|
super("acm", false);
|
||||||
|
this.properties = properties;
|
||||||
|
this.refreshHistory = refreshHistory;
|
||||||
|
this.propertySourceRepository = propertySourceRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, Object> invoke() {
|
||||||
|
Map<String, Object> result = new HashMap<>();
|
||||||
|
result.put("config", properties);
|
||||||
|
|
||||||
|
Map<String, Object> runtime = new HashMap<>();
|
||||||
|
List<AcmPropertySource> all = propertySourceRepository.getAll();
|
||||||
|
|
||||||
|
List<Map<String, Object>> sources = new ArrayList<>();
|
||||||
|
for (AcmPropertySource ps : all) {
|
||||||
|
Map<String, Object> source = new HashMap<>();
|
||||||
|
source.put("dataId", ps.getDataId());
|
||||||
|
source.put("lastSynced", dateFormat.format(ps.getTimestamp()));
|
||||||
|
sources.add(source);
|
||||||
|
}
|
||||||
|
runtime.put("sources", sources);
|
||||||
|
runtime.put("refreshHistory", refreshHistory.getRecords());
|
||||||
|
|
||||||
|
result.put("runtime", runtime);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.cloud.alicloud.acm.endpoint;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
|
||||||
|
import org.springframework.cloud.alicloud.acm.AcmPropertySourceRepository;
|
||||||
|
import org.springframework.cloud.alicloud.acm.refresh.AcmRefreshHistory;
|
||||||
|
import org.springframework.cloud.alicloud.context.acm.AcmProperties;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author xiaojing
|
||||||
|
*/
|
||||||
|
@ConditionalOnWebApplication
|
||||||
|
@ConditionalOnClass(name = "org.springframework.boot.actuate.endpoint.AbstractEndpoint")
|
||||||
|
public class AcmEndpointAutoConfiguration {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private AcmProperties acmProperties;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private AcmRefreshHistory acmRefreshHistory;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private AcmPropertySourceRepository acmPropertySourceRepository;
|
||||||
|
|
||||||
|
@ConditionalOnMissingBean
|
||||||
|
@Bean
|
||||||
|
public AcmEndpoint acmEndpoint() {
|
||||||
|
return new AcmEndpoint(acmProperties, acmRefreshHistory,
|
||||||
|
acmPropertySourceRepository);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.cloud.alicloud.acm.endpoint;
|
||||||
|
|
||||||
|
import com.alibaba.edas.acm.ConfigService;
|
||||||
|
import org.springframework.boot.actuate.health.AbstractHealthIndicator;
|
||||||
|
import org.springframework.boot.actuate.health.Health;
|
||||||
|
import org.springframework.cloud.alicloud.acm.AcmPropertySourceRepository;
|
||||||
|
import org.springframework.cloud.alicloud.acm.bootstrap.AcmPropertySource;
|
||||||
|
import org.springframework.cloud.alicloud.context.acm.AcmProperties;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author leijuan
|
||||||
|
* @author juven
|
||||||
|
*/
|
||||||
|
public class AcmHealthIndicator extends AbstractHealthIndicator {
|
||||||
|
|
||||||
|
private final AcmProperties acmProperties;
|
||||||
|
|
||||||
|
private final AcmPropertySourceRepository acmPropertySourceRepository;
|
||||||
|
|
||||||
|
private final List<String> dataIds;
|
||||||
|
|
||||||
|
public AcmHealthIndicator(AcmProperties acmProperties,
|
||||||
|
AcmPropertySourceRepository acmPropertySourceRepository) {
|
||||||
|
this.acmProperties = acmProperties;
|
||||||
|
this.acmPropertySourceRepository = acmPropertySourceRepository;
|
||||||
|
|
||||||
|
this.dataIds = new ArrayList<>();
|
||||||
|
for (AcmPropertySource acmPropertySource : this.acmPropertySourceRepository
|
||||||
|
.getAll()) {
|
||||||
|
this.dataIds.add(acmPropertySource.getDataId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doHealthCheck(Health.Builder builder) throws Exception {
|
||||||
|
for (String dataId : dataIds) {
|
||||||
|
try {
|
||||||
|
String config = ConfigService.getConfig(dataId, acmProperties.getGroup(),
|
||||||
|
acmProperties.getTimeout());
|
||||||
|
if (StringUtils.isEmpty(config)) {
|
||||||
|
builder.down().withDetail(String.format("dataId: '%s', group: '%s'",
|
||||||
|
dataId, acmProperties.getGroup()), "config is empty");
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
builder.down().withDetail(String.format("dataId: '%s', group: '%s'",
|
||||||
|
dataId, acmProperties.getGroup()), e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
builder.up().withDetail("dataIds", dataIds);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,127 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.cloud.alicloud.acm.refresh;
|
||||||
|
|
||||||
|
import com.alibaba.edas.acm.ConfigService;
|
||||||
|
import com.alibaba.edas.acm.listener.ConfigChangeListener;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.context.event.ApplicationReadyEvent;
|
||||||
|
import org.springframework.cloud.alicloud.acm.AcmPropertySourceRepository;
|
||||||
|
import org.springframework.cloud.alicloud.acm.bootstrap.AcmPropertySource;
|
||||||
|
import org.springframework.cloud.alicloud.context.acm.AcmProperties;
|
||||||
|
import org.springframework.cloud.context.refresh.ContextRefresher;
|
||||||
|
import org.springframework.context.ApplicationListener;
|
||||||
|
import org.springframework.core.env.Environment;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.math.BigInteger;
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* On application start up, AcmContextRefresher add diamond listeners to all application
|
||||||
|
* level dataIds, when there is a change in the data, listeners will refresh
|
||||||
|
* configurations.
|
||||||
|
*
|
||||||
|
* @author juven.xuxb, 5/13/16.
|
||||||
|
*/
|
||||||
|
public class AcmContextRefresher implements ApplicationListener<ApplicationReadyEvent> {
|
||||||
|
|
||||||
|
private Logger logger = LoggerFactory.getLogger(AcmContextRefresher.class);
|
||||||
|
|
||||||
|
private final ContextRefresher contextRefresher;
|
||||||
|
|
||||||
|
private final AcmProperties properties;
|
||||||
|
|
||||||
|
private final AcmRefreshHistory refreshHistory;
|
||||||
|
|
||||||
|
private final AcmPropertySourceRepository acmPropertySourceRepository;
|
||||||
|
|
||||||
|
private Map<String, ConfigChangeListener> listenerMap = new ConcurrentHashMap<>(16);
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private Environment environment;
|
||||||
|
|
||||||
|
public AcmContextRefresher(ContextRefresher contextRefresher,
|
||||||
|
AcmProperties properties, AcmRefreshHistory refreshHistory,
|
||||||
|
AcmPropertySourceRepository acmPropertySourceRepository) {
|
||||||
|
this.contextRefresher = contextRefresher;
|
||||||
|
this.properties = properties;
|
||||||
|
this.refreshHistory = refreshHistory;
|
||||||
|
this.acmPropertySourceRepository = acmPropertySourceRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onApplicationEvent(ApplicationReadyEvent event) {
|
||||||
|
this.registerDiamondListenersForApplications();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void registerDiamondListenersForApplications() {
|
||||||
|
if (properties.isRefreshEnabled()) {
|
||||||
|
for (AcmPropertySource acmPropertySource : acmPropertySourceRepository
|
||||||
|
.getAll()) {
|
||||||
|
if (acmPropertySource.isGroupLevel()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
String dataId = acmPropertySource.getDataId();
|
||||||
|
registerDiamondListener(dataId);
|
||||||
|
}
|
||||||
|
if (acmPropertySourceRepository.getAll().isEmpty()) {
|
||||||
|
|
||||||
|
String applicationName = environment
|
||||||
|
.getProperty("spring.application.name");
|
||||||
|
String dataId = applicationName + "." + properties.getFileExtension();
|
||||||
|
|
||||||
|
registerDiamondListener(dataId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void registerDiamondListener(final String dataId) {
|
||||||
|
|
||||||
|
ConfigChangeListener listener = listenerMap.get(dataId);
|
||||||
|
if (listener == null) {
|
||||||
|
listener = new ConfigChangeListener() {
|
||||||
|
@Override
|
||||||
|
public void receiveConfigInfo(String configInfo) {
|
||||||
|
String md5 = "";
|
||||||
|
if (!StringUtils.isEmpty(configInfo)) {
|
||||||
|
try {
|
||||||
|
MessageDigest md = MessageDigest.getInstance("MD5");
|
||||||
|
md5 = new BigInteger(1,
|
||||||
|
md.digest(configInfo.getBytes("UTF-8"))).toString(16);
|
||||||
|
}
|
||||||
|
catch (NoSuchAlgorithmException
|
||||||
|
| UnsupportedEncodingException e) {
|
||||||
|
logger.warn("unable to get md5 for dataId: " + dataId, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
refreshHistory.add(dataId, md5);
|
||||||
|
contextRefresher.refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
listenerMap.put(dataId, listener);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,72 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.cloud.alicloud.acm.refresh;
|
||||||
|
|
||||||
|
import java.text.DateFormat;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author juven.xuxb, 5/16/16.
|
||||||
|
*/
|
||||||
|
public class AcmRefreshHistory {
|
||||||
|
|
||||||
|
private static final int MAX_SIZE = 20;
|
||||||
|
|
||||||
|
private LinkedList<Record> records = new LinkedList<>();
|
||||||
|
|
||||||
|
private DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||||
|
|
||||||
|
public void add(String dataId, String md5) {
|
||||||
|
records.addFirst(new Record(dateFormat.format(new Date()), dataId, md5));
|
||||||
|
if (records.size() > MAX_SIZE) {
|
||||||
|
records.removeLast();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public LinkedList<Record> getRecords() {
|
||||||
|
return records;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Record {
|
||||||
|
|
||||||
|
private final String timestamp;
|
||||||
|
|
||||||
|
private final String dataId;
|
||||||
|
|
||||||
|
private final String md5;
|
||||||
|
|
||||||
|
public Record(String timestamp, String dataId, String md5) {
|
||||||
|
this.timestamp = timestamp;
|
||||||
|
this.dataId = dataId;
|
||||||
|
this.md5 = md5;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTimestamp() {
|
||||||
|
return timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDataId() {
|
||||||
|
return dataId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMd5() {
|
||||||
|
return md5;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"properties": [
|
||||||
|
{
|
||||||
|
"name": "spring.application.group",
|
||||||
|
"type": "java.lang.String",
|
||||||
|
"description": "spring application group."
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
org.springframework.cloud.bootstrap.BootstrapConfiguration=\
|
||||||
|
org.springframework.cloud.alicloud.acm.bootstrap.AcmPropertySourceLocator
|
||||||
|
|
||||||
|
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
||||||
|
org.springframework.cloud.alicloud.acm.AcmAutoConfiguration,\
|
||||||
|
org.springframework.cloud.alicloud.acm.endpoint.AcmEndpointAutoConfiguration
|
||||||
|
|
||||||
|
org.springframework.boot.diagnostics.FailureAnalyzer=\
|
||||||
|
org.springframework.cloud.alicloud.acm.diagnostics.analyzer.DiamondConnectionFailureAnalyzer
|
87
spring-cloud-alicloud-ans/pom.xml
Normal file
87
spring-cloud-alicloud-ans/pom.xml
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
<?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">
|
||||||
|
<parent>
|
||||||
|
<artifactId>spring-cloud-alibaba</artifactId>
|
||||||
|
<groupId>org.springframework.cloud</groupId>
|
||||||
|
<version>0.1.0.BUILD-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<groupId>org.springframework.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-alicloud-ans</artifactId>
|
||||||
|
<name>Spring Cloud Alibaba Cloud ANS</name>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba.ans</groupId>
|
||||||
|
<artifactId>ans-sdk</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.aliyun</groupId>
|
||||||
|
<artifactId>aliyun-java-sdk-core</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.aliyun</groupId>
|
||||||
|
<artifactId>aliyun-java-sdk-edas</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-alicloud-context</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework</groupId>
|
||||||
|
<artifactId>spring-context</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-commons</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-actuator</artifactId>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-autoconfigure</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.cloud.alicloud.ans;
|
||||||
|
|
||||||
|
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
|
import org.springframework.cloud.alicloud.ans.registry.AnsAutoServiceRegistration;
|
||||||
|
import org.springframework.cloud.alicloud.ans.registry.AnsRegistration;
|
||||||
|
import org.springframework.cloud.alicloud.ans.registry.AnsServiceRegistry;
|
||||||
|
import org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationAutoConfiguration;
|
||||||
|
import org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationProperties;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author xiaolongzuo
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
@EnableConfigurationProperties
|
||||||
|
@ConditionalOnClass(name = "org.springframework.boot.context.embedded.EmbeddedServletContainerInitializedEvent")
|
||||||
|
@ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled", matchIfMissing = true)
|
||||||
|
@ConditionalOnAnsEnabled
|
||||||
|
@AutoConfigureBefore({ AutoServiceRegistrationAutoConfiguration.class,
|
||||||
|
AnsDiscoveryClientAutoConfiguration.class })
|
||||||
|
public class AnsAutoConfiguration {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public AnsServiceRegistry ansServiceRegistry() {
|
||||||
|
return new AnsServiceRegistry();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnBean(AutoServiceRegistrationProperties.class)
|
||||||
|
@ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled", matchIfMissing = true)
|
||||||
|
public AnsRegistration ansRegistration() {
|
||||||
|
return new AnsRegistration();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnBean(AutoServiceRegistrationProperties.class)
|
||||||
|
@ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled", matchIfMissing = true)
|
||||||
|
public AnsAutoServiceRegistration ansAutoServiceRegistration(
|
||||||
|
AnsServiceRegistry registry,
|
||||||
|
AutoServiceRegistrationProperties autoServiceRegistrationProperties,
|
||||||
|
AnsRegistration registration) {
|
||||||
|
return new AnsAutoServiceRegistration(registry, autoServiceRegistrationProperties,
|
||||||
|
registration);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,103 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.cloud.alicloud.ans;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.cloud.alicloud.context.ans.AnsProperties;
|
||||||
|
import org.springframework.cloud.client.DefaultServiceInstance;
|
||||||
|
import org.springframework.cloud.client.ServiceInstance;
|
||||||
|
import org.springframework.cloud.client.discovery.DiscoveryClient;
|
||||||
|
|
||||||
|
import com.alibaba.ans.core.NamingService;
|
||||||
|
import com.alibaba.ans.shaded.com.taobao.vipserver.client.core.Host;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author xiaolongzuo
|
||||||
|
*/
|
||||||
|
public class AnsDiscoveryClient implements DiscoveryClient {
|
||||||
|
|
||||||
|
public static final String DESCRIPTION = "Spring Cloud ANS Discovery Client";
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private AnsProperties ansProperties;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String description() {
|
||||||
|
return DESCRIPTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ServiceInstance getLocalServiceInstance() {
|
||||||
|
String serviceId = ansProperties.getClientDomains();
|
||||||
|
String host = ansProperties.getClientIp();
|
||||||
|
int port = ansProperties.getClientPort();
|
||||||
|
boolean secure = ansProperties.isSecure();
|
||||||
|
Map<String, String> metadata = ansProperties.getClientMetadata();
|
||||||
|
return new DefaultServiceInstance(serviceId, host, port, secure, metadata);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<ServiceInstance> getInstances(String serviceId) {
|
||||||
|
try {
|
||||||
|
List<Host> hosts = NamingService.getHosts(serviceId);
|
||||||
|
return hostToServiceInstanceList(hosts, serviceId);
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
throw new RuntimeException(
|
||||||
|
"Can not get hosts from ans server. serviceId: " + serviceId, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ServiceInstance hostToServiceInstance(Host host, String serviceId) {
|
||||||
|
AnsServiceInstance ansServiceInstance = new AnsServiceInstance();
|
||||||
|
ansServiceInstance.setHost(host.getIp());
|
||||||
|
ansServiceInstance.setPort(host.getPort());
|
||||||
|
ansServiceInstance.setServiceId(serviceId);
|
||||||
|
Map<String, String> metadata = new HashMap<String, String>(5);
|
||||||
|
metadata.put("appUseType", host.getAppUseType());
|
||||||
|
metadata.put("site", host.getSite());
|
||||||
|
metadata.put("unit", host.getUnit());
|
||||||
|
metadata.put("doubleWeight", "" + host.getDoubleWeight());
|
||||||
|
metadata.put("weight", "" + host.getWeight());
|
||||||
|
ansServiceInstance.setMetadata(metadata);
|
||||||
|
|
||||||
|
return ansServiceInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<ServiceInstance> hostToServiceInstanceList(List<Host> hosts,
|
||||||
|
String serviceId) {
|
||||||
|
List<ServiceInstance> result = new ArrayList<ServiceInstance>(hosts.size());
|
||||||
|
for (Host host : hosts) {
|
||||||
|
result.add(hostToServiceInstance(host, serviceId));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getServices() {
|
||||||
|
|
||||||
|
Set<String> doms = NamingService.getDomsSubscribed();
|
||||||
|
List<String> result = new LinkedList<>();
|
||||||
|
for (String service : doms) {
|
||||||
|
result.add(service);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.cloud.alicloud.ans;
|
||||||
|
|
||||||
|
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
|
import org.springframework.cloud.client.discovery.DiscoveryClient;
|
||||||
|
import org.springframework.cloud.client.discovery.simple.SimpleDiscoveryClientAutoConfiguration;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author xiaolongzuo
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
@ConditionalOnMissingBean(DiscoveryClient.class)
|
||||||
|
@EnableConfigurationProperties
|
||||||
|
@AutoConfigureBefore(SimpleDiscoveryClientAutoConfiguration.class)
|
||||||
|
public class AnsDiscoveryClientAutoConfiguration {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public DiscoveryClient ansDiscoveryClient() {
|
||||||
|
return new AnsDiscoveryClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,90 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.cloud.alicloud.ans;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.springframework.cloud.client.DefaultServiceInstance;
|
||||||
|
import org.springframework.cloud.client.ServiceInstance;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author xiaolongzuo
|
||||||
|
*/
|
||||||
|
public class AnsServiceInstance implements ServiceInstance {
|
||||||
|
|
||||||
|
private String serviceId;
|
||||||
|
|
||||||
|
private String host;
|
||||||
|
|
||||||
|
private int port;
|
||||||
|
|
||||||
|
private boolean secure;
|
||||||
|
|
||||||
|
private Map<String, String> metadata;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getServiceId() {
|
||||||
|
return serviceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getHost() {
|
||||||
|
return host;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getPort() {
|
||||||
|
return port;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isSecure() {
|
||||||
|
return secure;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public URI getUri() {
|
||||||
|
return DefaultServiceInstance.getUri(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, String> getMetadata() {
|
||||||
|
return metadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setServiceId(String serviceId) {
|
||||||
|
this.serviceId = serviceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHost(String host) {
|
||||||
|
this.host = host;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPort(int port) {
|
||||||
|
this.port = port;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSecure(boolean secure) {
|
||||||
|
this.secure = secure;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMetadata(Map<String, String> metadata) {
|
||||||
|
this.metadata = metadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.cloud.alicloud.ans;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author xiaolongzuo
|
||||||
|
*/
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target({ ElementType.TYPE, ElementType.METHOD })
|
||||||
|
@ConditionalOnProperty(value = "spring.cloud.ans.enabled", matchIfMissing = true)
|
||||||
|
public @interface ConditionalOnAnsEnabled {
|
||||||
|
}
|
@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.cloud.alicloud.ans.endpoint;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.boot.actuate.endpoint.AbstractEndpoint;
|
||||||
|
import org.springframework.cloud.alicloud.context.ans.AnsProperties;
|
||||||
|
|
||||||
|
import com.alibaba.ans.core.NamingService;
|
||||||
|
import com.alibaba.ans.shaded.com.taobao.vipserver.client.core.Host;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author xiaolongzuo
|
||||||
|
*/
|
||||||
|
public class AnsEndpoint extends AbstractEndpoint<Map<String, Object>> {
|
||||||
|
|
||||||
|
private static final Logger LOGGER = LoggerFactory.getLogger(AnsEndpoint.class);
|
||||||
|
|
||||||
|
private AnsProperties ansProperties;
|
||||||
|
|
||||||
|
public AnsEndpoint(AnsProperties ansProperties) {
|
||||||
|
super("ans", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return ans endpoint
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Map<String, Object> invoke() {
|
||||||
|
Map<String, Object> ansEndpoint = new HashMap<>();
|
||||||
|
LOGGER.info("ANS endpoint invoke, ansProperties is {}", ansProperties);
|
||||||
|
ansEndpoint.put("ansProperties", ansProperties);
|
||||||
|
|
||||||
|
Map<String, Object> subscribes = new HashMap<>();
|
||||||
|
Set<String> subscribeServices = NamingService.getDomsSubscribed();
|
||||||
|
for (String service : subscribeServices) {
|
||||||
|
try {
|
||||||
|
List<Host> hosts = NamingService.getHosts(service);
|
||||||
|
subscribes.put(service, hosts);
|
||||||
|
}
|
||||||
|
catch (Exception ignoreException) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ansEndpoint.put("subscribes", subscribes);
|
||||||
|
LOGGER.info("ANS endpoint invoke, subscribes is {}", subscribes);
|
||||||
|
return ansEndpoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.cloud.alicloud.ans.endpoint;
|
||||||
|
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
|
||||||
|
import org.springframework.cloud.alicloud.context.ans.AnsProperties;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author xiaolongzuo
|
||||||
|
*/
|
||||||
|
@ConditionalOnWebApplication
|
||||||
|
@ConditionalOnClass(name = "org.springframework.boot.actuate.endpoint.AbstractEndpoint")
|
||||||
|
public class AnsEndpointAutoConfiguration {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public AnsEndpoint ansEndpoint(AnsProperties ansProperties) {
|
||||||
|
return new AnsEndpoint(ansProperties);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,113 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.cloud.alicloud.ans.registry;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.cloud.client.serviceregistry.AbstractAutoServiceRegistration;
|
||||||
|
import org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationProperties;
|
||||||
|
import org.springframework.cloud.client.serviceregistry.ServiceRegistry;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author xiaolongzuo
|
||||||
|
*/
|
||||||
|
public class AnsAutoServiceRegistration
|
||||||
|
extends AbstractAutoServiceRegistration<AnsRegistration> {
|
||||||
|
private static final Logger LOGGER = LoggerFactory
|
||||||
|
.getLogger(AnsAutoServiceRegistration.class);
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private AnsRegistration registration;
|
||||||
|
|
||||||
|
public AnsAutoServiceRegistration(ServiceRegistry<AnsRegistration> serviceRegistry,
|
||||||
|
AutoServiceRegistrationProperties autoServiceRegistrationProperties,
|
||||||
|
AnsRegistration registration) {
|
||||||
|
super(serviceRegistry, autoServiceRegistrationProperties);
|
||||||
|
this.registration = registration;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
public void setPort(int port) {
|
||||||
|
getPort().set(port);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected AnsRegistration getRegistration() {
|
||||||
|
if (this.registration.getPort() < 0 && this.getPort().get() > 0) {
|
||||||
|
this.registration.setPort(this.getPort().get());
|
||||||
|
}
|
||||||
|
Assert.isTrue(this.registration.getPort() > 0, "service.port has not been set");
|
||||||
|
return this.registration;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected AnsRegistration getManagementRegistration() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void register() {
|
||||||
|
if (!this.registration.getAnsProperties().isRegisterEnabled()) {
|
||||||
|
LOGGER.debug("Registration disabled.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (this.registration.getPort() < 0) {
|
||||||
|
this.registration.setPort(getPort().get());
|
||||||
|
}
|
||||||
|
super.register();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void registerManagement() {
|
||||||
|
if (!this.registration.getAnsProperties().isRegisterEnabled()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
super.registerManagement();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getConfiguredPort() {
|
||||||
|
return this.getPort().get();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setConfiguredPort(int port) {
|
||||||
|
this.getPort().set(port);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Object getConfiguration() {
|
||||||
|
return this.registration.getAnsProperties();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean isEnabled() {
|
||||||
|
return this.registration.getAnsProperties().isRegisterEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
protected String getAppName() {
|
||||||
|
String appName = registration.getServiceId();
|
||||||
|
return StringUtils.isEmpty(appName) ? super.getAppName() : appName;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,130 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.cloud.alicloud.ans.registry;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.annotation.PostConstruct;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.cloud.alicloud.context.ans.AnsProperties;
|
||||||
|
import org.springframework.cloud.client.DefaultServiceInstance;
|
||||||
|
import org.springframework.cloud.client.ServiceInstance;
|
||||||
|
import org.springframework.cloud.client.discovery.ManagementServerPortUtils;
|
||||||
|
import org.springframework.cloud.client.serviceregistry.Registration;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.core.env.Environment;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author xiaolongzuo
|
||||||
|
*/
|
||||||
|
public class AnsRegistration implements Registration, ServiceInstance {
|
||||||
|
|
||||||
|
private static final String MANAGEMENT_PORT = "management.port";
|
||||||
|
private static final String MANAGEMENT_CONTEXT_PATH = "management.context-path";
|
||||||
|
private static final String MANAGEMENT_ADDRESS = "management.address";
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private AnsProperties ansProperties;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ApplicationContext context;
|
||||||
|
|
||||||
|
@PostConstruct
|
||||||
|
public void init() {
|
||||||
|
|
||||||
|
Environment env = context.getEnvironment();
|
||||||
|
Integer managementPort = ManagementServerPortUtils.getPort(context);
|
||||||
|
if (null != managementPort) {
|
||||||
|
Map<String, String> metadata = ansProperties.getClientMetadata();
|
||||||
|
metadata.put(MANAGEMENT_PORT, managementPort.toString());
|
||||||
|
String contextPath = env.getProperty("management.context-path");
|
||||||
|
String address = env.getProperty("management.address");
|
||||||
|
if (!StringUtils.isEmpty(contextPath)) {
|
||||||
|
metadata.put(MANAGEMENT_CONTEXT_PATH, contextPath);
|
||||||
|
}
|
||||||
|
if (!StringUtils.isEmpty(address)) {
|
||||||
|
metadata.put(MANAGEMENT_ADDRESS, address);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getServiceId() {
|
||||||
|
return ansProperties.getClientDomains();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getHost() {
|
||||||
|
return ansProperties.getClientIp();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getPort() {
|
||||||
|
return ansProperties.getClientPort();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPort(int port) {
|
||||||
|
// if spring.cloud.ans.port is not set,use the port detected from context
|
||||||
|
if (ansProperties.getClientPort() < 0) {
|
||||||
|
this.ansProperties.setClientPort(port);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isSecure() {
|
||||||
|
return ansProperties.isSecure();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public URI getUri() {
|
||||||
|
return DefaultServiceInstance.getUri(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, String> getMetadata() {
|
||||||
|
return ansProperties.getClientMetadata();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isRegisterEnabled() {
|
||||||
|
return ansProperties.isRegisterEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCluster() {
|
||||||
|
return ansProperties.getClientCluster();
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getRegisterWeight(String dom) {
|
||||||
|
if (null != ansProperties.getClientWeights().get(dom)
|
||||||
|
&& ansProperties.getClientWeights().get(dom) > 0) {
|
||||||
|
return ansProperties.getClientWeights().get(dom);
|
||||||
|
}
|
||||||
|
return ansProperties.getClientWeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
public AnsProperties getAnsProperties() {
|
||||||
|
return ansProperties;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "AnsRegistration{" + "ansProperties=" + ansProperties + '}';
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,114 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.cloud.alicloud.ans.registry;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.commons.lang.StringUtils;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.cloud.client.serviceregistry.ServiceRegistry;
|
||||||
|
|
||||||
|
import com.alibaba.ans.core.NamingService;
|
||||||
|
import com.alibaba.ans.shaded.com.taobao.vipserver.client.ipms.NodeReactor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author xiaolongzuo
|
||||||
|
*/
|
||||||
|
public class AnsServiceRegistry implements ServiceRegistry<AnsRegistration> {
|
||||||
|
|
||||||
|
private static Logger logger = LoggerFactory.getLogger(AnsServiceRegistry.class);
|
||||||
|
|
||||||
|
private static final String SEPARATOR = ",";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void register(AnsRegistration registration) {
|
||||||
|
|
||||||
|
if (!registration.isRegisterEnabled()) {
|
||||||
|
logger.info("Registration is disabled...");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (StringUtils.isEmpty(registration.getServiceId())) {
|
||||||
|
logger.info("No service to register for client...");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<NodeReactor.Tag> tags = new ArrayList<>();
|
||||||
|
for (Map.Entry<String, String> entry : registration.getAnsProperties().getTags()
|
||||||
|
.entrySet()) {
|
||||||
|
NodeReactor.Tag tag = new NodeReactor.Tag();
|
||||||
|
tag.setName(entry.getKey());
|
||||||
|
tag.setValue(entry.getValue());
|
||||||
|
tags.add(tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (String dom : registration.getServiceId().split(SEPARATOR)) {
|
||||||
|
try {
|
||||||
|
NamingService.regDom(dom, registration.getHost(), registration.getPort(),
|
||||||
|
registration.getRegisterWeight(dom), registration.getCluster(),
|
||||||
|
tags);
|
||||||
|
logger.info("INFO_ANS_REGISTER, {} {}:{} register finished", dom,
|
||||||
|
registration.getAnsProperties().getClientIp(),
|
||||||
|
registration.getAnsProperties().getClientPort());
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
logger.error("ERR_ANS_REGISTER, {} register failed...{},", dom,
|
||||||
|
registration.toString(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deregister(AnsRegistration registration) {
|
||||||
|
|
||||||
|
logger.info("De-registering from ANSServer now...");
|
||||||
|
|
||||||
|
if (StringUtils.isEmpty(registration.getServiceId())) {
|
||||||
|
logger.info("No dom to de-register for client...");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
NamingService.deRegDom(registration.getServiceId(), registration.getHost(),
|
||||||
|
registration.getPort(), registration.getCluster());
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
logger.error("ERR_ANS_DEREGISTER, de-register failed...{},",
|
||||||
|
registration.toString(), e);
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.info("De-registration finished.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setStatus(AnsRegistration registration, String status) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> T getStatus(AnsRegistration registration) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.cloud.alicloud.ans.ribbon;
|
||||||
|
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
import com.netflix.client.config.IClientConfig;
|
||||||
|
import com.netflix.loadbalancer.ServerList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author xiaolongzuo
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
public class AnsRibbonClientConfiguration {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnMissingBean
|
||||||
|
public ServerList<?> ribbonServerList(IClientConfig config) {
|
||||||
|
AnsServerList serverList = new AnsServerList(config.getClientName());
|
||||||
|
return serverList;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,74 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.cloud.alicloud.ans.ribbon;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.alibaba.ans.shaded.com.taobao.vipserver.client.core.Host;
|
||||||
|
import com.netflix.loadbalancer.Server;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author xiaolongzuo
|
||||||
|
*/
|
||||||
|
public class AnsServer extends Server {
|
||||||
|
|
||||||
|
private final MetaInfo metaInfo;
|
||||||
|
private final Host host;
|
||||||
|
private final Map<String, String> metadata;
|
||||||
|
|
||||||
|
public AnsServer(final Host host, final String dom) {
|
||||||
|
super(host.getIp(), host.getPort());
|
||||||
|
this.host = host;
|
||||||
|
this.metadata = Collections.emptyMap();
|
||||||
|
metaInfo = new MetaInfo() {
|
||||||
|
@Override
|
||||||
|
public String getAppName() {
|
||||||
|
return dom;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getServerGroup() {
|
||||||
|
return getMetadata().get("group");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getServiceIdForDiscovery() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getInstanceId() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MetaInfo getMetaInfo() {
|
||||||
|
return metaInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Host getHealthService() {
|
||||||
|
return this.host;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, String> getMetadata() {
|
||||||
|
return metadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,78 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.cloud.alicloud.ans.ribbon;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.alibaba.ans.core.NamingService;
|
||||||
|
import com.alibaba.ans.shaded.com.taobao.vipserver.client.core.Host;
|
||||||
|
import com.netflix.client.config.IClientConfig;
|
||||||
|
import com.netflix.loadbalancer.AbstractServerList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author xiaolongzuo
|
||||||
|
*/
|
||||||
|
public class AnsServerList extends AbstractServerList<AnsServer> {
|
||||||
|
|
||||||
|
private String dom;
|
||||||
|
|
||||||
|
public AnsServerList(String dom) {
|
||||||
|
this.dom = dom;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<AnsServer> getInitialListOfServers() {
|
||||||
|
try {
|
||||||
|
List<Host> hosts = NamingService.getHosts(getDom());
|
||||||
|
return hostsToServerList(hosts);
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
throw new IllegalStateException("Can not get ans hosts, dom=" + getDom(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<AnsServer> getUpdatedListOfServers() {
|
||||||
|
return getInitialListOfServers();
|
||||||
|
}
|
||||||
|
|
||||||
|
private AnsServer hostToServer(Host host) {
|
||||||
|
AnsServer server = new AnsServer(host, getDom());
|
||||||
|
return server;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<AnsServer> hostsToServerList(List<Host> hosts) {
|
||||||
|
List<AnsServer> result = new ArrayList<AnsServer>(hosts.size());
|
||||||
|
for (Host host : hosts) {
|
||||||
|
if (host.isValid()) {
|
||||||
|
result.add(hostToServer(host));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDom() {
|
||||||
|
return dom;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initWithNiwsConfig(IClientConfig iClientConfig) {
|
||||||
|
this.dom = iClientConfig.getClientName();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.cloud.alicloud.ans.ribbon;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author xiaolongzuo
|
||||||
|
*/
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target({ ElementType.TYPE, ElementType.METHOD })
|
||||||
|
@ConditionalOnProperty(value = "ribbon.ans.enabled", matchIfMissing = true)
|
||||||
|
public @interface ConditionalOnRibbonAns {
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.cloud.alicloud.ans.ribbon;
|
||||||
|
|
||||||
|
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||||
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
|
import org.springframework.cloud.alicloud.ans.ConditionalOnAnsEnabled;
|
||||||
|
import org.springframework.cloud.netflix.ribbon.RibbonAutoConfiguration;
|
||||||
|
import org.springframework.cloud.netflix.ribbon.RibbonClients;
|
||||||
|
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author xiaolongzuo
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
@EnableConfigurationProperties
|
||||||
|
@ConditionalOnAnsEnabled
|
||||||
|
@ConditionalOnBean(SpringClientFactory.class)
|
||||||
|
@ConditionalOnRibbonAns
|
||||||
|
@AutoConfigureAfter(RibbonAutoConfiguration.class)
|
||||||
|
@RibbonClients(defaultConfiguration = AnsRibbonClientConfiguration.class)
|
||||||
|
public class RibbonAnsAutoConfiguration {
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
||||||
|
org.springframework.cloud.alicloud.ans.endpoint.AnsEndpointAutoConfiguration,\
|
||||||
|
org.springframework.cloud.alicloud.ans.ribbon.RibbonAnsAutoConfiguration,\
|
||||||
|
org.springframework.cloud.alicloud.ans.AnsAutoConfiguration
|
||||||
|
org.springframework.cloud.client.discovery.EnableDiscoveryClient=\
|
||||||
|
org.springframework.cloud.alicloud.ans.AnsDiscoveryClientAutoConfiguration
|
@ -0,0 +1,78 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.cloud.alibaba.ans.ribbon;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
import static org.mockito.BDDMockito.given;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.springframework.cloud.alicloud.ans.ribbon.AnsServer;
|
||||||
|
import org.springframework.cloud.alicloud.ans.ribbon.AnsServerList;
|
||||||
|
|
||||||
|
import com.alibaba.ans.shaded.com.taobao.vipserver.client.core.Host;
|
||||||
|
import com.netflix.loadbalancer.Server;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author xiaolongzuo
|
||||||
|
*/
|
||||||
|
public class AnsServiceListTests {
|
||||||
|
|
||||||
|
static final String IP_ADDR = "10.0.0.2";
|
||||||
|
|
||||||
|
static final int PORT = 8080;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAnsServer() {
|
||||||
|
AnsServerList serverList = getAnsServerList();
|
||||||
|
List<AnsServer> servers = serverList.getInitialListOfServers();
|
||||||
|
assertNotNull("servers was null", servers);
|
||||||
|
assertEquals("servers was not size 1", 1, servers.size());
|
||||||
|
Server des = assertAnsServer(servers);
|
||||||
|
assertEquals("hostPort was wrong", IP_ADDR + ":" + PORT, des.getHostPort());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Server assertAnsServer(List<AnsServer> servers) {
|
||||||
|
Server actualServer = servers.get(0);
|
||||||
|
assertTrue("server was not a DomainExtractingServer",
|
||||||
|
actualServer instanceof AnsServer);
|
||||||
|
AnsServer des = AnsServer.class.cast(actualServer);
|
||||||
|
assertNotNull("host is null", des.getHealthService());
|
||||||
|
assertEquals("unit was wrong", "DEFAULT", des.getHealthService().getUnit());
|
||||||
|
return des;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected AnsServerList getAnsServerList() {
|
||||||
|
Host host = mock(Host.class);
|
||||||
|
given(host.getIp()).willReturn(IP_ADDR);
|
||||||
|
given(host.getDoubleWeight()).willReturn(1.0);
|
||||||
|
given(host.getPort()).willReturn(PORT);
|
||||||
|
given(host.getWeight()).willReturn(1);
|
||||||
|
given(host.getUnit()).willReturn("DEFAULT");
|
||||||
|
|
||||||
|
AnsServer server = new AnsServer(host, "testDom");
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
AnsServerList originalServerList = mock(AnsServerList.class);
|
||||||
|
given(originalServerList.getInitialListOfServers())
|
||||||
|
.willReturn(Arrays.asList(server));
|
||||||
|
return originalServerList;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -61,13 +61,6 @@
|
|||||||
<artifactId>spring-cloud-commons</artifactId>
|
<artifactId>spring-cloud-commons</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-configuration-processor</artifactId>
|
|
||||||
<scope>provided</scope>
|
|
||||||
<optional>true</optional>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-logging</artifactId>
|
<artifactId>spring-boot-starter-logging</artifactId>
|
||||||
@ -89,6 +82,13 @@
|
|||||||
<optional>true</optional>
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-test</artifactId>
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
|
@ -14,6 +14,8 @@
|
|||||||
<description>Spring Cloud Alibaba Cloud Starters</description>
|
<description>Spring Cloud Alibaba Cloud Starters</description>
|
||||||
<modules>
|
<modules>
|
||||||
<module>spring-cloud-starter-alicloud-oss</module>
|
<module>spring-cloud-starter-alicloud-oss</module>
|
||||||
|
<module>spring-cloud-starter-alicloud-acm</module>
|
||||||
|
<module>spring-cloud-starter-alicloud-ans</module>
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
|
|
||||||
|
@ -0,0 +1,20 @@
|
|||||||
|
<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>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>org.springframework.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-starter-alicloud</artifactId>
|
||||||
|
<version>0.1.0.BUILD-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
<artifactId>spring-cloud-starter-alicloud-acm</artifactId>
|
||||||
|
<name>Spring Cloud Starter Alibaba Cloud ACM</name>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-alicloud-acm</artifactId>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
@ -0,0 +1,21 @@
|
|||||||
|
<?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">
|
||||||
|
<parent>
|
||||||
|
<groupId>org.springframework.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-starter-alicloud</artifactId>
|
||||||
|
<version>0.1.0.BUILD-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<artifactId>spring-cloud-starter-alicloud-ans</artifactId>
|
||||||
|
<name>Spring Cloud Starter Alibaba Cloud ANS</name>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-alicloud-ans</artifactId>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
Loading…
x
Reference in New Issue
Block a user