mirror of
https://gitee.com/mirrors/Spring-Cloud-Alibaba.git
synced 2021-06-26 13:25:11 +08:00
Merge pull request #941 from eacdy/master
Add module Spring Cloud Alibaba Sidecar
This commit is contained in:
commit
df3d9ce0e8
10
pom.xml
10
pom.xml
@ -79,6 +79,7 @@
|
|||||||
<spring-cloud-bus.version>2.2.0.BUILD-SNAPSHOT</spring-cloud-bus.version>
|
<spring-cloud-bus.version>2.2.0.BUILD-SNAPSHOT</spring-cloud-bus.version>
|
||||||
<spring-cloud-gateway.version>2.2.0.BUILD-SNAPSHOT</spring-cloud-gateway.version>
|
<spring-cloud-gateway.version>2.2.0.BUILD-SNAPSHOT</spring-cloud-gateway.version>
|
||||||
<spring-cloud-stream.version>Horsham.BUILD-SNAPSHOT</spring-cloud-stream.version>
|
<spring-cloud-stream.version>Horsham.BUILD-SNAPSHOT</spring-cloud-stream.version>
|
||||||
|
<spring-cloud-consul.version>2.2.0.BUILD-SNAPSHOT</spring-cloud-consul.version>
|
||||||
|
|
||||||
<junit.version>4.12</junit.version>
|
<junit.version>4.12</junit.version>
|
||||||
<javax-servlet-api>3.0</javax-servlet-api>
|
<javax-servlet-api>3.0</javax-servlet-api>
|
||||||
@ -122,6 +123,7 @@
|
|||||||
<module>spring-cloud-alicloud-schedulerx</module>
|
<module>spring-cloud-alicloud-schedulerx</module>
|
||||||
<module>spring-cloud-alicloud-sms</module>
|
<module>spring-cloud-alicloud-sms</module>
|
||||||
<module>spring-cloud-alibaba-coverage</module>
|
<module>spring-cloud-alibaba-coverage</module>
|
||||||
|
<module>spring-cloud-alibaba-sidecar</module>
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
<dependencyManagement>
|
<dependencyManagement>
|
||||||
@ -199,6 +201,14 @@
|
|||||||
<scope>import</scope>
|
<scope>import</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-consul-dependencies</artifactId>
|
||||||
|
<version>${spring-cloud-consul.version}</version>
|
||||||
|
<type>pom</type>
|
||||||
|
<scope>import</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.dubbo</groupId>
|
<groupId>org.apache.dubbo</groupId>
|
||||||
<artifactId>dubbo-spring-boot-starter</artifactId>
|
<artifactId>dubbo-spring-boot-starter</artifactId>
|
||||||
|
@ -295,6 +295,11 @@
|
|||||||
<artifactId>spring-cloud-alibaba-dubbo</artifactId>
|
<artifactId>spring-cloud-alibaba-dubbo</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-alibaba-sidecar</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- Own dependencies - Starters -->
|
<!-- Own dependencies - Starters -->
|
||||||
<dependency>
|
<dependency>
|
||||||
@ -360,6 +365,11 @@
|
|||||||
<artifactId>spring-cloud-starter-bus-rocketmq</artifactId>
|
<artifactId>spring-cloud-starter-bus-rocketmq</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-starter-alibaba-sidecar</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- SMS -->
|
<!-- SMS -->
|
||||||
<dependency>
|
<dependency>
|
||||||
|
194
spring-cloud-alibaba-docs/src/main/asciidoc-zh/sidecar.adoc
Normal file
194
spring-cloud-alibaba-docs/src/main/asciidoc-zh/sidecar.adoc
Normal file
@ -0,0 +1,194 @@
|
|||||||
|
== Spring Cloud Alibaba Sidecar
|
||||||
|
|
||||||
|
`Spring Cloud Alibaba Sidecar` 是一个用来快速**完美整合** Spring Cloud
|
||||||
|
与 *异构微服务* 的框架,灵感来自
|
||||||
|
https://github.com/spring-cloud/spring-cloud-netflix/tree/master/spring-cloud-netflix-sidecar[Spring
|
||||||
|
Cloud Netflix Sidecar] 。目前支持的服务发现组件:
|
||||||
|
|
||||||
|
* Nacos
|
||||||
|
* Consul
|
||||||
|
|
||||||
|
=== 术语
|
||||||
|
|
||||||
|
==== 异构微服务
|
||||||
|
|
||||||
|
非Spring Cloud应用,统称异构微服务。比如你的遗留项目,或者非JVM应用。
|
||||||
|
|
||||||
|
==== ``完美整合''的三层含义
|
||||||
|
|
||||||
|
* 享受服务发现的优势
|
||||||
|
* 有负载均衡
|
||||||
|
* 有断路器
|
||||||
|
|
||||||
|
=== Why or Why not?
|
||||||
|
|
||||||
|
==== 为什么要编写Alibaba Sidecar?
|
||||||
|
|
||||||
|
原因有两点:
|
||||||
|
|
||||||
|
* Spring Cloud子项目 `Spring Cloud Netflix Sidecar`
|
||||||
|
是可以快速整合异构微服务的。然而,Sidecar只支持使用Eureka作为服务发现,*如果使用其他服务发现组件就抓瞎了*。
|
||||||
|
* *Sidecar是基于Zuul 1.x的*,Spring
|
||||||
|
Cloud官方明确声明,未来将会逐步淘汰Zuul。今年早些时候,我有给Spring
|
||||||
|
Cloud官方提出需求,希望官方实现一个基于Spring Cloud
|
||||||
|
Gateway的新一代Sidecar,然而官方表示并没有该计划。详见:https://github.com/spring-cloud/spring-cloud-gateway/issues/735
|
||||||
|
|
||||||
|
既然没有,索性自己写了。
|
||||||
|
|
||||||
|
==== 为什么不用Service Mesh?
|
||||||
|
|
||||||
|
* 目前Mesh主要使用场景在Kubernetes领域(Istio、Linkerd
|
||||||
|
2等,大多将Kubernetes作为First
|
||||||
|
Class支持,虽然Istio也可部署在非Kubernetes环境),而目前业界,Spring
|
||||||
|
Cloud应用未必有试试Mesh的环境;
|
||||||
|
* 使用Alibaba
|
||||||
|
Sidecar一个小组件就能解决问题了(核心代码不超过200行),引入整套Mesh方案,颇有点屠龙刀杀黄鳝的意思。
|
||||||
|
|
||||||
|
=== 原理
|
||||||
|
|
||||||
|
* Alibaba
|
||||||
|
Sidecar根据配置的异构微服务的IP、端口等信息,*将异构微服务的IP/端口注册到服务发现组件上*
|
||||||
|
。
|
||||||
|
* Alibaba Sidecar实现了 *健康检查* ,Alibaba
|
||||||
|
Sidecar会定时检测异构微服务是否健康。如果发现异构微服务不健康,Alibaba
|
||||||
|
Sidecar会自动将代表异构微服务的Alibaba
|
||||||
|
Sidecar实例下线;如果异构微服务恢复正常,则会自动上线。最长延迟是30秒,详见
|
||||||
|
`Alibaba SidecarChecker#check` 。
|
||||||
|
|
||||||
|
=== 要求
|
||||||
|
|
||||||
|
* 【必须】你的异构微服务需使用HTTP通信。这一点严格来说不算要求,因为Spring
|
||||||
|
Cloud本身就是基于HTTP的;
|
||||||
|
* 【可选】如果微服务配置了 `sidecar.health-check-url`
|
||||||
|
,则表示开启健康检查,此时,你的异构微服务需实现健康检查(可以是空实现,只要暴露一个端点,返回类似
|
||||||
|
`{"status": "UP"}` 的字符串即可)。
|
||||||
|
|
||||||
|
=== 使用示例
|
||||||
|
|
||||||
|
* 如使用Nacos作为服务发现组件,详见`spring-cloud-alibaba-examples/spring-cloud-alibaba-sidecar-examples/spring-cloud-alibaba-sidecar-nacos-example`
|
||||||
|
* 如使用Consul作为服务发现组件,详见`spring-cloud-alibaba-examples/spring-cloud-alibaba-sidecar-examples/spring-cloud-alibaba-sidecar-nacos-example`
|
||||||
|
|
||||||
|
==== 示例代码(以Nacos服务发现为例)
|
||||||
|
|
||||||
|
* 加依赖:
|
||||||
|
+
|
||||||
|
[source,xml]
|
||||||
|
----
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-starter-alibaba-sidecar</artifactId>
|
||||||
|
</dependency>
|
||||||
|
----
|
||||||
|
* 写配置:
|
||||||
|
+
|
||||||
|
[source,yaml]
|
||||||
|
----
|
||||||
|
server:
|
||||||
|
port: 8070
|
||||||
|
spring:
|
||||||
|
cloud:
|
||||||
|
nacos:
|
||||||
|
discovery:
|
||||||
|
server-addr: localhost:8848
|
||||||
|
gateway:
|
||||||
|
discovery:
|
||||||
|
locator:
|
||||||
|
enabled: true
|
||||||
|
application:
|
||||||
|
name: node-service
|
||||||
|
sidecar:
|
||||||
|
# 异构微服务的IP
|
||||||
|
ip: 127.0.0.1
|
||||||
|
# 异构微服务的端口
|
||||||
|
port: 8060
|
||||||
|
# 异构微服务的健康检查URL
|
||||||
|
health-check-url: http://localhost:8060/health.json
|
||||||
|
management:
|
||||||
|
endpoint:
|
||||||
|
health:
|
||||||
|
show-details: always
|
||||||
|
----
|
||||||
|
+
|
||||||
|
配置比较简单,就是把Alibaba Sidecar注册到Nacos上,然后添加了几行Alibaba
|
||||||
|
Sidecar的配置。
|
||||||
|
|
||||||
|
==== 异构微服务
|
||||||
|
|
||||||
|
我准备了一个NodeJS编写的简单微服务。
|
||||||
|
|
||||||
|
[source,javascript]
|
||||||
|
----
|
||||||
|
var http = require('http');
|
||||||
|
var url = require("url");
|
||||||
|
var path = require('path');
|
||||||
|
|
||||||
|
// 创建server
|
||||||
|
var server = http.createServer(function(req, res) {
|
||||||
|
// 获得请求的路径
|
||||||
|
var pathname = url.parse(req.url).pathname;
|
||||||
|
res.writeHead(200, { 'Content-Type' : 'application/json; charset=utf-8' });
|
||||||
|
// 访问http://localhost:8060/,将会返回{"index":"欢迎来到首页"}
|
||||||
|
if (pathname === '/') {
|
||||||
|
res.end(JSON.stringify({ "index" : "欢迎来到首页" }));
|
||||||
|
}
|
||||||
|
// 访问http://localhost:8060/health,将会返回{"status":"UP"}
|
||||||
|
else if (pathname === '/health.json') {
|
||||||
|
res.end(JSON.stringify({ "status" : "UP" }));
|
||||||
|
}
|
||||||
|
// 其他情况返回404
|
||||||
|
else {
|
||||||
|
res.end("404");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// 创建监听,并打印日志
|
||||||
|
server.listen(8060, function() {
|
||||||
|
console.log('listening on localhost:8060');
|
||||||
|
});
|
||||||
|
----
|
||||||
|
|
||||||
|
==== 测试
|
||||||
|
|
||||||
|
===== 测试1:Spring Cloud微服务完美调用异构微服务
|
||||||
|
|
||||||
|
为你的Spring Cloud微服务整合Ribbon,然后构建 `http://node-service/**`
|
||||||
|
,就可以请求到异构微服务的 `/**` 了。
|
||||||
|
|
||||||
|
示例:
|
||||||
|
|
||||||
|
Ribbon请求 `http://node-service/` 会请求到 `http://localhost:8060/`
|
||||||
|
,以此类推。
|
||||||
|
|
||||||
|
至于断路器,正常为你的Spring
|
||||||
|
Cloud微服务整合Sentinel或者Hystirx、Resilience4J即可 。
|
||||||
|
|
||||||
|
===== 测试2:异构微服务完美调用Spring Cloud微服务
|
||||||
|
|
||||||
|
由于Alibaba Sidecar基于Spring Cloud Gateway,而网关自带转发能力。
|
||||||
|
|
||||||
|
示例:
|
||||||
|
|
||||||
|
如果你有一个Spring Cloud微服务叫做 `spring-cloud-microservice`
|
||||||
|
,那么NodeJS应用只需构建
|
||||||
|
`http://localhost:8070/spring-cloud-microservice/**` ,Alibaba
|
||||||
|
Sidecar就会把请求转发到 `spring-cloud-microservice` 的 `/**` 。
|
||||||
|
|
||||||
|
而Spring Cloud Gateway是整合了Ribbon的,所以实现了负载均衡;Spring Cloud
|
||||||
|
Gateway还可以整合Sentinel或者Hystirx、Resilience4J,所以也带有了断路器。
|
||||||
|
|
||||||
|
=== Alibaba Sidecar优缺点分析
|
||||||
|
|
||||||
|
Alibaba
|
||||||
|
Sidecar的设计和Sidecar基本一致,优缺点和Sidecar的优缺点也是一样的。
|
||||||
|
|
||||||
|
优点:
|
||||||
|
|
||||||
|
* 接入简单,几行代码就可以将异构微服务整合到Spring Cloud生态
|
||||||
|
* 不侵入原代码
|
||||||
|
|
||||||
|
缺点:
|
||||||
|
|
||||||
|
* 每接入一个异构微服务实例,都需要额外部署一个Alibaba
|
||||||
|
Sidecar实例,增加了部署成本(虽然这个成本在Kubernetes环境中几乎可以忽略不计(只需将Alibaba
|
||||||
|
Sidecar实例和异构微服务作为一个Pod部署即可));
|
||||||
|
* 异构微服务调用Spring Cloud微服务时,本质是把Alibaba
|
||||||
|
Sidecar当网关在使用,经过了一层转发,性能有一定下降。
|
@ -31,4 +31,6 @@ include::schedulerx.adoc[]
|
|||||||
|
|
||||||
include::sms.adoc[]
|
include::sms.adoc[]
|
||||||
|
|
||||||
|
include::sidecar.adoc[]
|
||||||
|
|
||||||
|
|
||||||
|
@ -43,6 +43,8 @@
|
|||||||
<module>spring-cloud-bus-rocketmq-example</module>
|
<module>spring-cloud-bus-rocketmq-example</module>
|
||||||
<module>schedulerx-example/schedulerx-simple-task-example</module>
|
<module>schedulerx-example/schedulerx-simple-task-example</module>
|
||||||
<module>spring-cloud-alibaba-dubbo-examples</module>
|
<module>spring-cloud-alibaba-dubbo-examples</module>
|
||||||
|
<module>spring-cloud-alibaba-sidecar-examples/spring-cloud-alibaba-sidecar-nacos-example</module>
|
||||||
|
<module>spring-cloud-alibaba-sidecar-examples/spring-cloud-alibaba-sidecar-consul-example</module>
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
@ -0,0 +1,26 @@
|
|||||||
|
var http = require('http');
|
||||||
|
var url = require("url");
|
||||||
|
var path = require('path');
|
||||||
|
|
||||||
|
// 创建server
|
||||||
|
var server = http.createServer(function(req, res) {
|
||||||
|
// 获得请求的路径
|
||||||
|
var pathname = url.parse(req.url).pathname;
|
||||||
|
res.writeHead(200, { 'Content-Type' : 'application/json; charset=utf-8' });
|
||||||
|
// 访问http://localhost:8060/,将会返回{"index":"欢迎来到首页"}
|
||||||
|
if (pathname === '/') {
|
||||||
|
res.end(JSON.stringify({ "index" : "欢迎来到首页" }));
|
||||||
|
}
|
||||||
|
// 访问http://localhost:8060/health,将会返回{"status":"UP"}
|
||||||
|
else if (pathname === '/health.json') {
|
||||||
|
res.end(JSON.stringify({ "status" : "UP" }));
|
||||||
|
}
|
||||||
|
// 其他情况返回404
|
||||||
|
else {
|
||||||
|
res.end("404");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// 创建监听,并打印日志
|
||||||
|
server.listen(8060, function() {
|
||||||
|
console.log('listening on localhost:8060');
|
||||||
|
});
|
@ -0,0 +1,59 @@
|
|||||||
|
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<parent>
|
||||||
|
<groupId>com.alibaba.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-alibaba-examples</artifactId>
|
||||||
|
<version>2.2.0.BUILD-SNAPSHOT</version>
|
||||||
|
<relativePath>../../pom.xml</relativePath>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<artifactId>spring-cloud-alibaba-sidecar-consul-example</artifactId>
|
||||||
|
<description>Example demonstrating how to use Spring Cloud Alibaba Sidecar with consul</description>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-starter-alibaba-sidecar</artifactId>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>com.alibaba.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-deploy-plugin</artifactId>
|
||||||
|
<version>${maven-deploy-plugin.version}</version>
|
||||||
|
<configuration>
|
||||||
|
<skip>true</skip>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</project>
|
@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* 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 com.alibaba.cloud.sidecar;
|
||||||
|
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
|
||||||
|
@SpringBootApplication
|
||||||
|
public class DemoApplication {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SpringApplication.run(DemoApplication.class, args);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,24 @@
|
|||||||
|
server:
|
||||||
|
port: 8070
|
||||||
|
spring:
|
||||||
|
cloud:
|
||||||
|
gateway:
|
||||||
|
discovery:
|
||||||
|
locator:
|
||||||
|
enabled: true
|
||||||
|
consul:
|
||||||
|
host: localhost
|
||||||
|
port: 8500
|
||||||
|
application:
|
||||||
|
name: node-service
|
||||||
|
sidecar:
|
||||||
|
# 异构微服务的IP
|
||||||
|
ip: 127.0.0.1
|
||||||
|
# 异构微服务的端口
|
||||||
|
port: 8060
|
||||||
|
# 异构微服务的健康检查URL
|
||||||
|
health-check-url: http://localhost:8060/health.json
|
||||||
|
management:
|
||||||
|
endpoint:
|
||||||
|
health:
|
||||||
|
show-details: always
|
@ -0,0 +1,44 @@
|
|||||||
|
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<parent>
|
||||||
|
<groupId>com.alibaba.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-alibaba-examples</artifactId>
|
||||||
|
<version>2.2.0.BUILD-SNAPSHOT</version>
|
||||||
|
<relativePath>../../pom.xml</relativePath>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<artifactId>spring-cloud-alibaba-sidecar-nacos-example</artifactId>
|
||||||
|
<description>Example demonstrating how to use Spring Cloud Alibaba Sidecar with nacos</description>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-starter-alibaba-sidecar</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-deploy-plugin</artifactId>
|
||||||
|
<version>${maven-deploy-plugin.version}</version>
|
||||||
|
<configuration>
|
||||||
|
<skip>true</skip>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</project>
|
@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* 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 com.alibaba.cloud.sidecar;
|
||||||
|
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
|
||||||
|
@SpringBootApplication
|
||||||
|
public class DemoApplication {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SpringApplication.run(DemoApplication.class, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,24 @@
|
|||||||
|
server:
|
||||||
|
port: 8070
|
||||||
|
spring:
|
||||||
|
cloud:
|
||||||
|
nacos:
|
||||||
|
discovery:
|
||||||
|
server-addr: localhost:8848
|
||||||
|
gateway:
|
||||||
|
discovery:
|
||||||
|
locator:
|
||||||
|
enabled: true
|
||||||
|
application:
|
||||||
|
name: node-service
|
||||||
|
sidecar:
|
||||||
|
# 异构微服务的IP
|
||||||
|
ip: 127.0.0.1
|
||||||
|
# 异构微服务的端口
|
||||||
|
port: 8060
|
||||||
|
# 异构微服务的健康检查URL
|
||||||
|
health-check-url: http://localhost:8060/health.json
|
||||||
|
management:
|
||||||
|
endpoint:
|
||||||
|
health:
|
||||||
|
show-details: always
|
49
spring-cloud-alibaba-sidecar/pom.xml
Normal file
49
spring-cloud-alibaba-sidecar/pom.xml
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<parent>
|
||||||
|
<groupId>com.alibaba.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-alibaba</artifactId>
|
||||||
|
<version>2.2.0.BUILD-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<artifactId>spring-cloud-alibaba-sidecar</artifactId>
|
||||||
|
<name>spring-cloud-alibaba-sidecar</name>
|
||||||
|
<description>An easy way to integrate polyglot apps for Spring Cloud Alibaba.</description>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-starter-gateway</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
@ -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 com.alibaba.cloud.sidecar;
|
||||||
|
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.core.env.ConfigurableEnvironment;
|
||||||
|
import org.springframework.web.client.RestTemplate;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author www.itmuch.com
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
@EnableConfigurationProperties(SidecarProperties.class)
|
||||||
|
public class SidecarAutoConfiguration {
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnMissingBean
|
||||||
|
public RestTemplate restTemplate() {
|
||||||
|
return new RestTemplate();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public SidecarHealthIndicator sidecarHealthIndicator(SidecarProperties sidecarProperties, RestTemplate restTemplate) {
|
||||||
|
return new SidecarHealthIndicator(sidecarProperties, restTemplate);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public SidecarHealthChecker sidecarHealthChecker(SidecarDiscoveryClient sidecarDiscoveryClient, SidecarHealthIndicator sidecarHealthIndicator, SidecarProperties sidecarProperties, ConfigurableEnvironment environment) {
|
||||||
|
SidecarHealthChecker cleaner = new SidecarHealthChecker(sidecarDiscoveryClient, sidecarHealthIndicator, sidecarProperties, environment);
|
||||||
|
cleaner.check();
|
||||||
|
return cleaner;
|
||||||
|
}
|
||||||
|
}
|
@ -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 com.alibaba.cloud.sidecar;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author www.itmuch.com
|
||||||
|
*/
|
||||||
|
public interface SidecarDiscoveryClient {
|
||||||
|
/**
|
||||||
|
* register instance
|
||||||
|
*
|
||||||
|
* @param applicationName applicationName
|
||||||
|
* @param ip ip
|
||||||
|
* @param port port
|
||||||
|
*/
|
||||||
|
void registerInstance(String applicationName, String ip, Integer port);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* deregister instance
|
||||||
|
*
|
||||||
|
* @param applicationName applicationName
|
||||||
|
* @param ip ip
|
||||||
|
* @param port port
|
||||||
|
*/
|
||||||
|
void deregisterInstance(String applicationName, String ip, Integer port);
|
||||||
|
}
|
@ -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 com.alibaba.cloud.sidecar;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.actuate.health.HealthIndicator;
|
||||||
|
import org.springframework.boot.actuate.health.Status;
|
||||||
|
import org.springframework.core.env.ConfigurableEnvironment;
|
||||||
|
import reactor.core.scheduler.Schedulers;
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author www.itmuch.com
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
|
||||||
|
public class SidecarHealthChecker {
|
||||||
|
private final SidecarDiscoveryClient sidecarDiscoveryClient;
|
||||||
|
private final HealthIndicator healthIndicator;
|
||||||
|
private final SidecarProperties sidecarProperties;
|
||||||
|
private final ConfigurableEnvironment environment;
|
||||||
|
|
||||||
|
public void check() {
|
||||||
|
Schedulers.single()
|
||||||
|
.schedulePeriodically(
|
||||||
|
() -> {
|
||||||
|
String ip = sidecarProperties.getIp();
|
||||||
|
Integer port = sidecarProperties.getPort();
|
||||||
|
|
||||||
|
Status status = healthIndicator.health().getStatus();
|
||||||
|
String applicationName = environment.getProperty("spring.application.name");
|
||||||
|
|
||||||
|
if (status.equals(Status.UP)) {
|
||||||
|
this.sidecarDiscoveryClient.registerInstance(applicationName, ip, port);
|
||||||
|
log.debug("Health check success. register this instance. applicationName = {}, ip = {}, port = {}, status = {}",
|
||||||
|
applicationName, ip, port, status
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
log.warn("Health check failed. unregister this instance. applicationName = {}, ip = {}, port = {}, status = {}",
|
||||||
|
applicationName, ip, port, status
|
||||||
|
);
|
||||||
|
this.sidecarDiscoveryClient.deregisterInstance(applicationName, ip, port);
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
0,
|
||||||
|
30,
|
||||||
|
TimeUnit.SECONDS
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -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 com.alibaba.cloud.sidecar;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.actuate.health.AbstractHealthIndicator;
|
||||||
|
import org.springframework.boot.actuate.health.Health;
|
||||||
|
import org.springframework.core.ParameterizedTypeReference;
|
||||||
|
import org.springframework.http.HttpMethod;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.web.client.RestTemplate;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author www.itmuch.com
|
||||||
|
*/
|
||||||
|
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
|
||||||
|
public class SidecarHealthIndicator extends AbstractHealthIndicator {
|
||||||
|
private final SidecarProperties sidecarProperties;
|
||||||
|
private final RestTemplate restTemplate;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doHealthCheck(Health.Builder builder) throws Exception {
|
||||||
|
try {
|
||||||
|
URI uri = this.sidecarProperties.getHealthCheckUrl();
|
||||||
|
if (uri == null) {
|
||||||
|
builder.up();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ResponseEntity<Map<String, Object>> exchange = this.restTemplate.exchange(
|
||||||
|
uri,
|
||||||
|
HttpMethod.GET,
|
||||||
|
null,
|
||||||
|
new ParameterizedTypeReference<Map<String, Object>>() {
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, Object> map = exchange.getBody();
|
||||||
|
|
||||||
|
if (map == null) {
|
||||||
|
this.getWarning(builder);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Object status = map.get("status");
|
||||||
|
if (status instanceof String) {
|
||||||
|
builder.status(status.toString());
|
||||||
|
} else {
|
||||||
|
this.getWarning(builder);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
builder.down().withDetail("error", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void getWarning(Health.Builder builder) {
|
||||||
|
builder.unknown().withDetail("warning", "no status field in response");
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* 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 com.alibaba.cloud.sidecar;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
|
||||||
|
import javax.validation.constraints.Max;
|
||||||
|
import javax.validation.constraints.Min;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
import java.net.URI;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author www.itmuch.com
|
||||||
|
*/
|
||||||
|
@ConfigurationProperties("sidecar")
|
||||||
|
@Data
|
||||||
|
@Validated
|
||||||
|
public class SidecarProperties {
|
||||||
|
/**
|
||||||
|
* polyglot service's ip
|
||||||
|
*/
|
||||||
|
private String ip;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* polyglot service's port
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
@Max(65535)
|
||||||
|
@Min(1)
|
||||||
|
private Integer port;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* polyglot service's health check url.
|
||||||
|
* this endpoint must return json and the format must follow spring boot actuator's health endpoint.
|
||||||
|
* eg. {"status": "UP"}
|
||||||
|
*/
|
||||||
|
private URI healthCheckUrl;
|
||||||
|
}
|
@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
* 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 com.alibaba.cloud.sidecar.consul;
|
||||||
|
|
||||||
|
import com.alibaba.cloud.sidecar.SidecarAutoConfiguration;
|
||||||
|
import com.alibaba.cloud.sidecar.SidecarDiscoveryClient;
|
||||||
|
import com.alibaba.cloud.sidecar.SidecarProperties;
|
||||||
|
import org.springframework.beans.factory.ObjectProvider;
|
||||||
|
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||||
|
import org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationProperties;
|
||||||
|
import org.springframework.cloud.consul.discovery.ConsulDiscoveryProperties;
|
||||||
|
import org.springframework.cloud.consul.discovery.HeartbeatProperties;
|
||||||
|
import org.springframework.cloud.consul.serviceregistry.*;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author www.itmuch.com
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
@ConditionalOnClass(ConsulServiceRegistryAutoConfiguration.class)
|
||||||
|
@AutoConfigureBefore({ConsulAutoServiceRegistrationAutoConfiguration.class, SidecarAutoConfiguration.class})
|
||||||
|
public class SidecarConsulAutoConfiguration {
|
||||||
|
@Bean
|
||||||
|
public ConsulAutoRegistration consulRegistration(
|
||||||
|
AutoServiceRegistrationProperties autoServiceRegistrationProperties,
|
||||||
|
ConsulDiscoveryProperties properties,
|
||||||
|
ApplicationContext applicationContext,
|
||||||
|
ObjectProvider<List<ConsulRegistrationCustomizer>> registrationCustomizers,
|
||||||
|
ObjectProvider<List<ConsulManagementRegistrationCustomizer>> managementRegistrationCustomizers,
|
||||||
|
HeartbeatProperties heartbeatProperties,
|
||||||
|
SidecarProperties sidecarProperties) {
|
||||||
|
return SidecarConsulAutoRegistration.registration(autoServiceRegistrationProperties,
|
||||||
|
properties, applicationContext, registrationCustomizers.getIfAvailable(),
|
||||||
|
managementRegistrationCustomizers.getIfAvailable(), heartbeatProperties, sidecarProperties);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public SidecarDiscoveryClient sidecarDiscoveryClient(
|
||||||
|
ConsulDiscoveryProperties properties,
|
||||||
|
ConsulServiceRegistry serviceRegistry,
|
||||||
|
ConsulAutoRegistration registration) {
|
||||||
|
return new SidecarConsulDiscoveryClient(properties, serviceRegistry, registration);
|
||||||
|
}
|
||||||
|
}
|
@ -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 com.alibaba.cloud.sidecar.consul;
|
||||||
|
|
||||||
|
import com.ecwid.consul.v1.agent.model.NewService;
|
||||||
|
import com.alibaba.cloud.sidecar.SidecarProperties;
|
||||||
|
import org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationProperties;
|
||||||
|
import org.springframework.cloud.consul.discovery.ConsulDiscoveryProperties;
|
||||||
|
import org.springframework.cloud.consul.discovery.HeartbeatProperties;
|
||||||
|
import org.springframework.cloud.consul.serviceregistry.ConsulAutoRegistration;
|
||||||
|
import org.springframework.cloud.consul.serviceregistry.ConsulManagementRegistrationCustomizer;
|
||||||
|
import org.springframework.cloud.consul.serviceregistry.ConsulRegistrationCustomizer;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.core.env.Environment;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author www.itmuch.com
|
||||||
|
*/
|
||||||
|
public class SidecarConsulAutoRegistration extends ConsulAutoRegistration {
|
||||||
|
public SidecarConsulAutoRegistration(NewService service, AutoServiceRegistrationProperties autoServiceRegistrationProperties, ConsulDiscoveryProperties properties, ApplicationContext context, HeartbeatProperties heartbeatProperties, List<ConsulManagementRegistrationCustomizer> managementRegistrationCustomizers) {
|
||||||
|
super(service, autoServiceRegistrationProperties, properties, context, heartbeatProperties, managementRegistrationCustomizers);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ConsulAutoRegistration registration(
|
||||||
|
AutoServiceRegistrationProperties autoServiceRegistrationProperties,
|
||||||
|
ConsulDiscoveryProperties properties, ApplicationContext context,
|
||||||
|
List<ConsulRegistrationCustomizer> registrationCustomizers,
|
||||||
|
List<ConsulManagementRegistrationCustomizer> managementRegistrationCustomizers,
|
||||||
|
HeartbeatProperties heartbeatProperties,
|
||||||
|
SidecarProperties sidecarProperties) {
|
||||||
|
|
||||||
|
NewService service = new NewService();
|
||||||
|
String appName = getAppName(properties, context.getEnvironment());
|
||||||
|
service.setId(getInstanceId(sidecarProperties, context.getEnvironment()));
|
||||||
|
if (!properties.isPreferAgentAddress()) {
|
||||||
|
service.setAddress(sidecarProperties.getIp());
|
||||||
|
}
|
||||||
|
service.setName(normalizeForDns(appName));
|
||||||
|
service.setTags(createTags(properties));
|
||||||
|
|
||||||
|
// set health check, use alibaba sidecar self's port rather than polyglot app's port.
|
||||||
|
service.setPort(Integer.valueOf(context.getEnvironment().getProperty("server.port")));
|
||||||
|
setCheck(service, autoServiceRegistrationProperties, properties, context,
|
||||||
|
heartbeatProperties);
|
||||||
|
|
||||||
|
service.setPort(sidecarProperties.getPort());
|
||||||
|
|
||||||
|
ConsulAutoRegistration registration = new ConsulAutoRegistration(service,
|
||||||
|
autoServiceRegistrationProperties, properties, context,
|
||||||
|
heartbeatProperties, managementRegistrationCustomizers);
|
||||||
|
customize(registrationCustomizers, registration);
|
||||||
|
return registration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getInstanceId(SidecarProperties sidecarProperties,
|
||||||
|
Environment environment) {
|
||||||
|
return String.format("%s-%s-%s",
|
||||||
|
environment.getProperty("spring.application.name"),
|
||||||
|
sidecarProperties.getIp(),
|
||||||
|
sidecarProperties.getPort());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* 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 com.alibaba.cloud.sidecar.consul;
|
||||||
|
|
||||||
|
import com.alibaba.cloud.sidecar.SidecarDiscoveryClient;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.cloud.consul.discovery.ConsulDiscoveryProperties;
|
||||||
|
import org.springframework.cloud.consul.serviceregistry.ConsulAutoRegistration;
|
||||||
|
import org.springframework.cloud.consul.serviceregistry.ConsulServiceRegistry;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author www.itmuch.com
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
|
||||||
|
public class SidecarConsulDiscoveryClient implements SidecarDiscoveryClient {
|
||||||
|
private final ConsulDiscoveryProperties properties;
|
||||||
|
private final ConsulServiceRegistry serviceRegistry;
|
||||||
|
private final ConsulAutoRegistration registration;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void registerInstance(String applicationName, String ip, Integer port) {
|
||||||
|
|
||||||
|
if (!this.properties.isRegister()) {
|
||||||
|
log.debug("Registration disabled.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
serviceRegistry.register(registration);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deregisterInstance(String applicationName, String ip, Integer port) {
|
||||||
|
if (!this.properties.isRegister() || !this.properties.isDeregister()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
serviceRegistry.deregister(registration);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
* 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 com.alibaba.cloud.sidecar.nacos;
|
||||||
|
|
||||||
|
import com.alibaba.cloud.nacos.NacosDiscoveryProperties;
|
||||||
|
import com.alibaba.cloud.nacos.discovery.NacosDiscoveryClientAutoConfiguration;
|
||||||
|
import com.alibaba.cloud.sidecar.SidecarAutoConfiguration;
|
||||||
|
import com.alibaba.cloud.sidecar.SidecarDiscoveryClient;
|
||||||
|
import com.alibaba.cloud.sidecar.SidecarProperties;
|
||||||
|
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author www.itmuch.com
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
@AutoConfigureBefore({NacosDiscoveryClientAutoConfiguration.class, SidecarAutoConfiguration.class})
|
||||||
|
@ConditionalOnClass(NacosDiscoveryProperties.class)
|
||||||
|
public class SidecarNacosAutoConfiguration {
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnMissingBean
|
||||||
|
public SidecarNacosDiscoveryProperties sidecarNacosDiscoveryProperties(SidecarProperties sidecarProperties) {
|
||||||
|
return new SidecarNacosDiscoveryProperties(sidecarProperties);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnMissingBean
|
||||||
|
public SidecarDiscoveryClient sidecarDiscoveryClient(SidecarNacosDiscoveryProperties sidecarNacosDiscoveryProperties) {
|
||||||
|
return new SidecarNacosDiscoveryClient(sidecarNacosDiscoveryProperties);
|
||||||
|
}
|
||||||
|
}
|
@ -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 com.alibaba.cloud.sidecar.nacos;
|
||||||
|
|
||||||
|
import com.alibaba.cloud.sidecar.SidecarDiscoveryClient;
|
||||||
|
import com.alibaba.nacos.api.exception.NacosException;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author www.itmuch.com
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
|
||||||
|
public class SidecarNacosDiscoveryClient implements SidecarDiscoveryClient {
|
||||||
|
private final SidecarNacosDiscoveryProperties sidecarNacosDiscoveryProperties;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void registerInstance(String applicationName, String ip, Integer port) {
|
||||||
|
try {
|
||||||
|
this.sidecarNacosDiscoveryProperties.namingServiceInstance()
|
||||||
|
.registerInstance(applicationName, ip, port);
|
||||||
|
} catch (NacosException e) {
|
||||||
|
log.warn("nacos exception happens", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deregisterInstance(String applicationName, String ip, Integer port) {
|
||||||
|
try {
|
||||||
|
this.sidecarNacosDiscoveryProperties.namingServiceInstance()
|
||||||
|
.deregisterInstance(applicationName, ip, port);
|
||||||
|
} catch (NacosException e) {
|
||||||
|
log.warn("nacos exception happens", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* 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 com.alibaba.cloud.sidecar.nacos;
|
||||||
|
|
||||||
|
import com.alibaba.cloud.nacos.NacosDiscoveryProperties;
|
||||||
|
import com.alibaba.cloud.sidecar.SidecarProperties;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
|
import java.net.SocketException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author itmuch.com
|
||||||
|
*/
|
||||||
|
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
|
||||||
|
public class SidecarNacosDiscoveryProperties extends NacosDiscoveryProperties {
|
||||||
|
private final SidecarProperties sidecarProperties;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init() throws SocketException {
|
||||||
|
super.init();
|
||||||
|
|
||||||
|
String ip = sidecarProperties.getIp();
|
||||||
|
if (StringUtils.isNotBlank(ip)) {
|
||||||
|
this.setIp(ip);
|
||||||
|
}
|
||||||
|
|
||||||
|
Integer port = sidecarProperties.getPort();
|
||||||
|
this.setPort(port);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,4 @@
|
|||||||
|
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
||||||
|
com.alibaba.cloud.sidecar.nacos.SidecarNacosAutoConfiguration,\
|
||||||
|
com.alibaba.cloud.sidecar.SidecarAutoConfiguration,\
|
||||||
|
com.alibaba.cloud.sidecar.consul.SidecarConsulAutoConfiguration
|
@ -20,5 +20,6 @@
|
|||||||
<module>spring-cloud-starter-stream-rocketmq</module>
|
<module>spring-cloud-starter-stream-rocketmq</module>
|
||||||
<module>spring-cloud-starter-bus-rocketmq</module>
|
<module>spring-cloud-starter-bus-rocketmq</module>
|
||||||
<module>spring-cloud-starter-dubbo</module>
|
<module>spring-cloud-starter-dubbo</module>
|
||||||
|
<module>spring-cloud-starter-alibaba-sidecar</module>
|
||||||
</modules>
|
</modules>
|
||||||
</project>
|
</project>
|
@ -0,0 +1,22 @@
|
|||||||
|
<?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>com.alibaba.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-starter-alibaba</artifactId>
|
||||||
|
<version>2.2.0.BUILD-SNAPSHOT</version>
|
||||||
|
<relativePath>../pom.xml</relativePath>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<artifactId>spring-cloud-starter-alibaba-sidecar</artifactId>
|
||||||
|
<name>Spring Cloud Starter Alibaba Sidecar</name>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-alibaba-sidecar</artifactId>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
Loading…
x
Reference in New Issue
Block a user