6.11.0(JUL 11, 2021)
贡献列表
- 感谢@pegasus的贡献
- 感谢@zifenhan的贡献
- 感谢@ayang的贡献
- 感谢@星河的贡献
- 感谢@jimodebeiju123的贡献
- 感谢@rottenmu的测试
- 感谢@春雷的测试
- 感谢@blank的测试
- 感谢@弄潮儿的测试
- 感谢@明天better的测试
- 感谢@陌路的测试
发布日志
6.11.0版,一个经过全面严格优化和严格测试的版本,架构科学性、代码规范性和高可用以及性能方面上更上一层楼,除此之外,暴露了更加丰富的端点(Endpoint)接口,供第三方云原生系统(例如,DevOps平台)做对接。不过,对于非核心的模块优化和重构,带来一些使用上的不兼容性,向广大用户致以歉意,我们相信您可以在几分钟内解决不兼容性问题。Please enjoy!
发布策略
提醒:版本号右边,
↑
表示>=该版本号, ↓
表示<=该版本号
表示维护中 |
表示不维护,但可用,强烈建议升级 |
表示不维护,不可用,已废弃
- 7.x.x版本(适用于202x.x.x)将继续维护
- 6.x.x版本(同时适用于Finchley、Greenwich和Hoxton)将继续维护
- 5.x.x版本(适用于Greenwich)已废弃
- 4.x.x版本(适用于Finchley)已废弃
- 3.x.x版本(适用于Edgware)不维护,但可用,强烈建议升级
- 2.x.x版本(适用于Dalston)已废弃
- 1.x.x版本(适用于Camden)已废弃
版本变更
- 默认集成Spring Boot版本为2.3.12.RELEASE(
可降级
) - 默认集成Spring Cloud版本为Hoxton.SR12(
可降级
),Hoxton.SR12为Spring Cloud官方发布的最后一个版本 - 默认集成Spring Cloud Alibaba版本为2.2.6.RELEASE(
可降级
) - 默认集成Nacos 1.4.x以上版本。如果使用1.4.x以下版本,那么
- 跟业务服务相关的Plugin模块不受影响
- 跟业务服务不相关的Console模块受影响,新增的Rest接口
/config/remote/update/{group}/{serviceId}/{formatType}
无法使用,必须使用不带{formatType}
参数的老接口 - Nacos 1.4.x以上版本推送参数新增配置文件类型(包括 xml | json | yaml | properties | html | text),可以让配置在Nacos界面上有效区别出不同的配置类型并高亮,从而提高易用性
- 默认集成Caffeine版本为2.9.2
- 默认集成SkyWalking APM Toolkit版本为8.6.0
- 默认集成OpenTelemetry版本为1.3.0
- 升级JEtcd版本为0.5.7,解决在Hoxton高版本抛Netty Grpc版本不兼容的错误
功能迭代
增强蓝绿灰度发布
① 蓝绿发布支持内置兜底路由
<?xml version="1.0" encoding="UTF-8"?>
<rule>
<strategy-release>
<conditions type="blue-green">
<!-- 蓝路由,条件expression驱动 -->
<condition id="blue-condition" expression="#H['a'] == '1'" version-id="blue-route"/>
<!-- 绿路由,条件expression驱动 -->
<condition id="green-condition" expression="#H['a'] == '1' and #H['b'] == '2'" version-id="green-route"/>
<!-- 兜底路由,无expression驱动 -->
<condition id="basic-condition" version-id="basic-route"/>
</conditions>
<routes>
<route id="blue-route" type="version">{"discovery-guide-service-a":"1.1", "discovery-guide-service-b":"1.1"}</route>
<route id="green-route" type="version">{"discovery-guide-service-a":"1.0", "discovery-guide-service-b":"1.0"}</route>
<route id="basic-route" type="version">{"discovery-guide-service-a":"1.0", "discovery-guide-service-b":"1.0"}</route>
</routes>
</strategy-release>
</rule>
② 灰度发布支持内置兜底路由
<?xml version="1.0" encoding="UTF-8"?>
<rule>
<strategy-release>
<conditions type="gray">
<!-- 灰度路由1,条件expression驱动 -->
<condition id="gray-condition1" expression="#H['a'] == '1'" version-id="gray-route=10;stable-route=90"/>
<!-- 灰度路由2,条件expression驱动 -->
<condition id="gray-condition2" expression="#H['a'] == '1' and #H['b'] == '2'" version-id="gray-route=85;stable-route=15"/>
<!-- 兜底路由,无expression驱动 -->
<condition id="basic-condition" version-id="gray-route=0;stable-route=100"/>
</conditions>
<routes>
<route id="gray-route" type="version">{"discovery-guide-service-a":"1.1", "discovery-guide-service-b":"1.1"}</route>
<route id="stable-route" type="version">{"discovery-guide-service-a":"1.0", "discovery-guide-service-b":"1.0"}</route>
</routes>
</strategy-release>
</rule>
③ 蓝绿灰度混合发布
基于上述增强,支持更简单更强大的蓝绿灰度混合发布功能
<?xml version="1.0" encoding="UTF-8"?>
<rule>
<strategy-release>
<conditions type="blue-green">
<condition id="condition-0" expression="#H['a'] == '0'" version-id="route-0"/>
<condition id="condition-1" expression="#H['a'] == '1'" version-id="route-1"/>
<condition id="basic-condition" version-id="basic-route"/> <!-- 可以删除掉蓝绿发布的兜底策略 -->
</conditions>
<conditions type="gray">
<condition id="condition-0" expression="#H['a'] == '2'" version-id="route-0=10;route-1=90"/>
<condition id="condition-1" expression="#H['a'] == '3'" version-id="route-0=85;route-1=15"/>
<condition id="basic-condition" version-id="route-0=0;route-1=100"/>
</conditions>
<routes>
<route id="route-0" type="version">{"discovery-guide-service-a":"1.1", "discovery-guide-service-b":"1.1"}</route>
<route id="route-1" type="version">{"discovery-guide-service-a":"1.1", "discovery-guide-service-b":"1.1"}</route>
<route id="basic-route" type="version">{"discovery-guide-service-a":"1.0", "discovery-guide-service-b":"1.0"}</route>
</routes>
</strategy-release>
</rule>
规则解读
原则:蓝绿规则优先于灰度规则
if (a == 0) {
执行蓝绿发布blue-green的route-0下的路由
} else if (a == 1) {
执行蓝绿发布blue-green的route-1下的路由
} else {
执行蓝绿发布blue-green的basic-route下的兜底路由
}
提醒:当蓝绿发布存在兜底策略(
basic-condition
),灰度发布永远不会被执行
如果删除掉蓝绿发布的兜底策略,那么执行逻辑则变为
if (a == 0) {
执行蓝绿发布route-0下的路由
} else if (a == 1) {
执行蓝绿发布route-1下的路由
} else if (a == 2) {
执行灰度发布route-0=10;route-1=90下的流量百分比分配路由
} else if (a == 3) {
执行灰度发布route-0=85;route-1=15下的流量百分比分配路由
} else {
执行灰度发布route-0=0;route-1=100下的兜底路由
由于赋予了route-0=0,那么流量会全部打到route-1上,相当于变种的蓝绿发布
}
蓝绿灰度混合发布一些应用场景和示例,可参考
https://github.com/Nepxion/Discovery/wiki
-> 如何执行高级蓝绿灰度混合发布
网关动态路由
网关动态路由功能,主要包括
- 路由动态添加
- 路由动态修改
- 路由动态删除
- 路由动态批量更新
- 路由查询
- 路由动态变更后,通过事件总线方式发出事件通知
上述操作,可以通过
- 网关暴露Rest Endpoint接口实施
- 控制台暴露Rest Endpoint接口,对同一个网关下若干个实例批量实施
- 网关订阅配置中心(包括Nacos、Apollo、Consul、Etcd、Redis、Zookeeper)批量实施
Spring-Cloud-Gateway网关动态路由
提醒:Spring Cloud Gateway网关在自动路由模式下,动态路由不能工作
支持Spring Cloud Gateway网关官方断言器和过滤器,也支持用户自定义断言器和过滤器
① Spring Cloud Gateway网关动态路由配置
- 精简配置
[
{
"id": "route0",
"uri": "lb://discovery-guide-service-a",
"predicates": [
"Path=/discovery-guide-service-a/**,/x/**,/y/**"
],
"filters": [
"StripPrefix=1"
]
}
]
- 完整配置
[
{
"id": "route0",
"uri": "lb://discovery-guide-service-a",
"predicates": [
"Path=/discovery-guide-service-a/**,/x/**,/y/**"
],
"filters": [
"StripPrefix=1"
],
"order": 0,
"metadata": {}
}
]
② Spring Cloud Gateway网关自定义动态路由配置
自定义方式描述网关内置断言器和过滤器
提醒:自定义方式描述网关内置断言器和过滤器的Key必须遵循如下规则
- 对于没有显式args定义的配置,类似Path、StripPrefix这种配置,args名称必须是
_genkey_序号
格式。例如,"_genkey_0": "/discovery-guide-service-a/**" - 对于显式args定义的配置,类似Header、Cookie、Query这种配置,args名称遵照Spring Cloud Gateway内置格式,请查看相关文档或者源码。例如,Header的KV格式为header -> regexp,Cookie的KV格式为name->regexp,Query的KV格式为param->regexp
[
{
"id": "route0",
"uri": "lb://discovery-guide-service-a",
"userPredicates": [
{
"name": "Path",
"args": {
"_genkey_0": "/discovery-guide-service-a/**",
"_genkey_1": "/x/**",
"_genkey_2": "/y/**"
}
},
{
"name": "Header",
"args": {
"header": "a",
"regexp": "1"
}
},
{
"name": "Header",
"args": {
"header": "b",
"regexp": "2"
}
},
{
"name": "Cookie",
"args": {
"name": "c",
"regexp": "3"
}
},
{
"name": "Cookie",
"args": {
"name": "d",
"regexp": "4"
}
},
{
"name": "Query",
"args": {
"param": "e",
"regexp": "5"
}
},
{
"name": "Query",
"args": {
"param": "f",
"regexp": "6"
}
}
],
"userFilters": [
{
"name": "StripPrefix",
"args": {
"_genkey_0": "1"
}
}
]
}
]
在DiscoveryPlatform界面上,格式为
Path={"_genkey_0":"/discovery-guide-service-a/**", "_genkey_1":"/x/**", "_genkey_2":"/y/**"}
StripPrefix={"_genkey_0":"1"}
Header={"header":"a","regexp":"1"}
Header={"header":"b","regexp":"2"}
Cookie={"name":"c","regexp":"3"}
Cookie={"name":"d","regexp":"4"}
Query={"param":"e","regexp":"5"}
Query={"param":"f","regexp":"6"}
自定义方式描述用户扩展的断言器和过滤器
提醒:自定义方式描述用户扩展的断言器和过滤器的Key必须遵循如下规则
- List结构,args名称必须是
list的变量名.序号
格式。例如,"whiteList.0": "* swagger-ui.html" - Map<String, String>结构,args名称必须是
map的变量名.map的key
格式。例如,"userMap.name": "jason"
[
{
"id": "route0",
"uri": "lb://discovery-guide-service-a",
"predicates": [
"Path=/discovery-guide-service-a/**,/x/**,/y/**"
],
"filters": [
"StripPrefix=1"
],
"userPredicates": [],
"userFilters": [
{
"name": "Authentication",
"args": {
"secretKey": "abc",
"whiteList.0": "* swagger-ui.html",
"whiteList.1": "* /swagger-resources/**",
"whiteList.2": "* /doc.html",
"userMap.name": "jason",
"userMap.age": "20",
"authInfoCarryStrategy": "AuthWriteToHeader"
}
}
]
}
]
在DiscoveryPlatform界面上,格式为
Authentication={"secretKey":"abc", "whiteList.0":"* swagger-ui.html", "whiteList.1":"* /swagger-resources/**", "whiteList.2":"* /doc.html", "userMap.name":"jason", "userMap.age":"20", "authInfoCarryStrategy":"AuthWriteToHeader"}
③ Spring Cloud Gateway网关的Rest Endpoint接口
操作 | 路径 | 参数 | 方式 |
---|---|---|---|
增加网关路由 | http:// [网关IP:PORT]/spring-cloud-gateway-route/add |
单个动态路由配置 | POST |
修改网关路由 | http:// [网关IP:PORT]/spring-cloud-gateway-route/modify |
单个动态路由配置 | POST |
删除网关路由 | http:// [网关IP:PORT]/spring-cloud-gateway-route/delete/{routeId} |
无 | DELETE |
更新全部网关路由 | http:// [网关IP:PORT]/spring-cloud-gateway-route/update-all |
多个动态路由配置 | POST |
根据路由Id查看网关路由 | http:// [网关IP:PORT]/spring-cloud-gateway-route/view/{routeId} |
无 | GET |
查看全部网关路由 | http:// [网关IP:PORT]/spring-cloud-gateway-route/view-all |
无 | GET |
④ 控制台的Rest Endpoint接口
操作 | 路径 | 参数 | 方式 |
---|---|---|---|
增加网关路由 | http:// [控制台IP:PORT]/route/add/spring-cloud-gateway/{serviceId} |
单个动态路由配置 | POST |
修改网关路由 | http:// [控制台IP:PORT]/route/modify/spring-cloud-gateway/{serviceId} |
单个动态路由配置 | POST |
删除网关路由 | http:// [控制台IP:PORT]/route/delete/spring-cloud-gateway/{serviceId}/{routeId} |
无 | DELETE |
更新全部网关路由 | http:// [控制台IP:PORT]/route/update-all/spring-cloud-gateway/{serviceId} |
多个动态路由配置 | GET |
查看全部网关路由 | http:// [控制台IP:PORT]/route/view-all/spring-cloud-gateway/{serviceId} |
无 | GET |
⑤ Spring Cloud Gateway网关订阅配置中心
网关订阅配置中心的使用方式,如下
- Key为
- Nacos、Redis、Zookeeper配置中心,Group为{group},DataId为{网关serviceId}-dynamic-route
- Apollo、Consul、Etcd配置中心,Key的格式为{group}-{网关serviceId}-dynamic-route
- {group}为注册中心元数据group值
- Value参考“① Spring Cloud Gateway网关动态路由配置”
支持如下开关开启该动能,默认是关闭的
# 开启和关闭网关订阅配置中心的动态路由策略。缺失则默认为false
spring.application.strategy.gateway.dynamic.route.enabled=true
配置中心配置的网关动态路由推送到网关后,网关会自动根据已经存在的路由表进行判断后实施增删改操作,而不是全部清空后再全部插入,这样有助于提高性能和安全性。网关控制台上会打印出如下日志
--- Gateway Dynamic Routes Update Information ----
Total count=3
Added count=1
Modified count=1
Deleted count=1
--------------------------------------------------
⑥ Spring Cloud Gateway网关事件总线通知的订阅
@EventBus
public class MySubscriber {
@Subscribe
public void onGatewayStrategyRouteAdded(GatewayStrategyRouteAddedEvent gatewayStrategyRouteAddedEvent) {
System.out.println("增加网关路由=" + gatewayStrategyRouteAddedEvent.getGatewayStrategyRouteEntity());
}
@Subscribe
public void onGatewayStrategyRouteModified(GatewayStrategyRouteModifiedEvent gatewayStrategyRouteModifiedEvent) {
System.out.println("修改网关路由=" + gatewayStrategyRouteModifiedEvent.getGatewayStrategyRouteEntity());
}
@Subscribe
public void onGatewayStrategyRouteDeleted(GatewayStrategyRouteDeletedEvent gatewayStrategyRouteDeletedEvent) {
System.out.println("删除网关路由=" + gatewayStrategyRouteDeletedEvent.getRouteId());
}
@Subscribe
public void onGatewayStrategyRouteUpdatedAll(GatewayStrategyRouteUpdatedAllEvent gatewayStrategyRouteUpdatedAllEvent) {
System.out.println("更新全部网关路由=" + gatewayStrategyRouteUpdatedAllEvent.getGatewayStrategyRouteEntityList());
}
}
Zuul网关动态路由
① Zuul网关动态路由配置
- 精简配置
[
{
"id": "route0",
"serviceId": "discovery-guide-service-a",
"path": "/discovery-guide-service-a/**"
},
{
"id": "route1",
"serviceId": "discovery-guide-service-a",
"path": "/x/**"
},
{
"id": "route2",
"serviceId": "discovery-guide-service-a",
"path": "/y/**"
}
]
如果希望一个服务只映射一个动态路由路径,则不需要id,可以简化为
[
{
"serviceId": "discovery-guide-service-a",
"path": "/x/**"
}
]
- 完整配置
[
{
"id": "route0",
"serviceId": "discovery-guide-service-a",
"path": "/discovery-guide-service-a/**",
"url": null,
"stripPrefix": true,
"retryable": null,
"sensitiveHeaders": [],
"customSensitiveHeaders": false
},
{
"id": "route1",
"serviceId": "discovery-guide-service-a",
"path": "/x/**",
"url": null,
"stripPrefix": true,
"retryable": null,
"sensitiveHeaders": [],
"customSensitiveHeaders": false
},
{
"id": "route2",
"serviceId": "discovery-guide-service-a",
"path": "/y/**",
"url": null,
"stripPrefix": true,
"retryable": null,
"sensitiveHeaders": [],
"customSensitiveHeaders": false
}
]
② Zuul网关的Rest Endpoint接口
操作 | 路径 | 参数 | 方式 |
---|---|---|---|
增加网关路由 | http:// [网关IP:PORT]/zuul-route/add |
单个动态路由配置 | POST |
修改网关路由 | http:// [网关IP:PORT]/zuul-route/modify |
单个动态路由配置 | POST |
删除网关路由 | http:// [网关IP:PORT]/zuul-route/delete/{routeId} |
无 | DELETE |
更新全部网关路由 | http:// [网关IP:PORT]/zuul-route/update-all |
多个动态路由配置 | POST |
根据路由Id查看网关路由 | http:// [网关IP:PORT]/zuul-route/view/{routeId} |
无 | GET |
查看全部网关路由 | http:// [网关IP:PORT]/zuul-route/view-all |
无 | GET |
③ 控制台的Rest Endpoint接口
操作 | 路径 | 参数 | 方式 |
---|---|---|---|
增加网关路由 | http:// [控制台IP:PORT]/route/add/zuul/{serviceId} |
单个动态路由配置 | POST |
修改网关路由 | http:// [控制台IP:PORT]/route/modify/zuul/{serviceId} |
单个动态路由配置 | POST |
删除网关路由 | http:// [控制台IP:PORT]/route/delete/zuul/{serviceId}/{routeId} |
无 | DELETE |
更新全部网关路由 | http:// [控制台IP:PORT]/route/zuul/update-all/{serviceId} |
多个动态路由配置 | GET |
查看全部网关路由 | http:// [控制台IP:PORT]/route/zuul/view-all/{serviceId} |
无 | GET |
④ Zuul网关订阅配置中心
网关订阅配置中心的使用方式,如下
- Key为
- Nacos、Redis、Zookeeper配置中心,Group为{group},DataId为{网关serviceId}-dynamic-route
- Apollo、Consul、Etcd配置中心,Key的格式为{group}-{网关serviceId}-dynamic-route
- {group}为注册中心元数据group值
- Value参考“① Zuul网关动态路由配置”
支持如下开关开启该动能,默认是关闭的
# 开启和关闭网关订阅配置中心的动态路由策略。缺失则默认为false
spring.application.strategy.zuul.dynamic.route.enabled=true
配置中心配置的网关动态路由推送到网关后,网关会自动根据已经存在的路由表进行判断后实施增删改操作,而不是全部清空后再全部插入,这样有助于提高性能和安全性。网关控制台上会打印出如下日志
----- Zuul Dynamic Routes Update Information -----
Total count=3
Added count=1
Modified count=1
Deleted count=1
--------------------------------------------------
⑤ Zuul网关事件总线通知的订阅
@EventBus
public class MySubscriber {
@Subscribe
public void onZuulStrategyRouteAdded(ZuulStrategyRouteAddedEvent zuulStrategyRouteAddedEvent) {
System.out.println("增加网关路由=" + zuulStrategyRouteAddedEvent.getZuulStrategyRouteEntity());
}
@Subscribe
public void onZuulStrategyRouteModified(ZuulStrategyRouteModifiedEvent zuulStrategyRouteModifiedEvent) {
System.out.println("修改网关路由=" + zuulStrategyRouteModifiedEvent.getZuulStrategyRouteEntity());
}
@Subscribe
public void onZuulStrategyRouteDeleted(ZuulStrategyRouteDeletedEvent zuulStrategyRouteDeletedEvent) {
System.out.println("删除网关路由=" + zuulStrategyRouteDeletedEvent.getRouteId());
}
@Subscribe
public void onZuulStrategyRouteUpdatedAll(ZuulStrategyRouteUpdatedAllEvent zuulStrategyRouteUpdatedAllEvent) {
System.out.println("更新全部网关路由=" + zuulStrategyRouteUpdatedAllEvent.getZuulStrategyRouteEntityList());
}
}
统一配置订阅执行器
统一配置订阅执行器,基于Nacos、Apollo、Consul、Etcd、Redis、Zookeeper六种配置中心,通过封装适配成同样的写法,通过切换继承类,可切换配置中心,无须修改其它代码
Spring Cloud配置动态刷新机制固化在一个比较单一的场景(例如,通过@value方式)里,无法满足更灵活更高级的订阅场景,例如,Spring Cloud Gateway和Zuul网关通过改变配置中心的路由信息无法动态刷新路由路径
本框架提供更简单灵活的实现方式,以Nacos为例子,使用者先确定订阅的Group和DataId,在Nacos界面填入这两个参数对应的配置内容,然后通过回调方法处理业务逻辑。具体使用方式,如下
// 把继承类(extends)换成如下任何一个,即可切换配置中心,代码无需任何变动
// 1. NacosProcessor
// 2. ApolloProcessor
// 3. ConsulProcessor
// 4. EtcdProcessor
// 5. ZookeeperProcessor
// 6. RedisProcessor
// Group和DataId自行决定,需要注意
// 1. 对于Nacos、Redis、Zookeeper配置中心,Group和DataId需要和界面相对应
// 2. 对于Apollo、Consul、Etcd配置中心,Key的格式为Group-DataId
// 可以同时支持多个配置中心的订阅,需要同时创建多个不同的Processor,同时@Bean方式进入到Spring容器
public class MyConfigProcessor extends NacosProcessor {
@Override
public void beforeInitialization() {
System.out.println("订阅器初始化之前,可以做一些工作");
}
@Override
public void afterInitialization() {
System.out.println("订阅器初始化之后,可以做一些工作");
}
@Override
public String getGroup() {
return "b";
}
@Override
public String getDataId() {
return "a";
}
@Override
public String getDescription() {
// description为日志打印显示而设置,作用是帮助使用者在日志上定位订阅器是否在执行
return "My subscription";
}
@Override
public void callbackConfig(String config) {
// config为配置中心对应键值的内容变更,使用者可以根据此变更对业务模块做回调处理
System.out.println("监听配置改变:config=" + config);
}
}
统一配置订阅执行器可以单独运行在Spring Boot应用上,它是一个通用的解决方案
- 如果使用者希望脱离Nepxion Discovery以及Spring Cloud框架,使用者只需要引入如下依赖之一即可
- 如果使用者正在使用Nepxion Discovery框架,则跟随它的内置引入即可,不需要额外引入如下依赖之一
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>discovery-common-nacos</artifactId>
<version>${discovery.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>discovery-common-apollo</artifactId>
<version>${discovery.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>discovery-common-redis</artifactId>
<version>${discovery.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>discovery-common-zookeeper</artifactId>
<version>${discovery.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>discovery-common-consul</artifactId>
<version>${discovery.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>discovery-common-etcd</artifactId>
<version>${discovery.version}</version>
</dependency>
具体用法和配置,请参考6.x.x指南示例配置版,分支为6.x.x-config
StrategyAlarmEvent新增告警类型
AlarmEvent更名为StrategyAlarmEvent,移动到strategy模块下
StrategyAlarmEvent新增告警类型,并把contextMap改为alarmMap,如下
public class StrategyAlarmEvent implements Serializable {
private static final long serialVersionUID = 5966845230262521754L;
private String alarmType;
private Map<String, String> alarmMap;
public StrategyAlarmEvent(String alarmType, Map<String, String> alarmMap) {
this.alarmType = alarmType;
this.alarmMap = alarmMap;
}
public String getAlarmType() {
return alarmType;
}
public Map<String, String> getAlarmMap() {
return alarmMap;
}
}
使用端的用法变更,如下
@EventBus
public class MySubscriber {
@Subscribe
public void onAlarm(StrategyAlarmEvent strategyAlarmEvent) {
// 在本告警中告警类型为StrategyConstant.STRATEGY_CONTEXT_ALARM的静态变量值,表示蓝绿灰度上下文告警
String alarmType = strategyAlarmEvent.getAlarmType();
// 通过事件总线把告警数据alarmMap存储到ElasticSearch、MessageQueue、数据库等
Map<String, String> alarmMap = strategyAlarmEvent.getAlarmMap();
}
}
Nacos配置自动鉴别配置类型
支持Nacos Client推送规则配置的时候,把配置类型(包括 xml | json | yaml | properties | html | text)推送到Nacos配置中心
元数据新增Http协议类型
Http协议类型包括http和https,通过注册元数据到注册中心,支持http和https两种方式的全链路侦测,路由,通过控制台对服务批量轮询操作
默认为http协议,当服务开启https暴露框架内部接口的时候,通过如下配置开启
spring.application.protocol=https
服务侧增加路由策略过滤器执行顺序的配置
服务侧支持路由策略过滤器执行顺序
# 路由策略过滤器的执行顺序(Order)。缺失则默认为0
spring.application.strategy.service.route.filter.order=0
重构优化
重构优化蓝绿灰度配置格式
配置节点
<strategy-customization>
变更为
<strategy-release>
但依旧兼容识别<strategy-customization>
配置节点
重构优化服务下线场景下全链路蓝绿灰度发布
① 全局唯一ID格式从UUID变更为
年月日(8位)-小时分钟秒(6位)-毫秒(3位)-随机数(4位)-随机数(3位)-随机数(3位)
前半部分精确到毫秒的设计,基本能保证ID的全局唯一,后半部分三重随机数,完全能保证ID的全局唯一。全局唯一失效的前提是,两个服务实例必须是毫秒级的同时启动,同时三次随机碰撞下来,得到完全三个相同的随机数后
② 配置方式和蓝绿灰度方式一致
全局唯一ID屏蔽变更
下面规则
<?xml version="1.0" encoding="UTF-8"?>
<rule>
<strategy-blacklist>
<!-- 单个ID形式。如果多个用“;”分隔,不允许出现空格 -->
<id value="e92edde5-0153-4ec8-9cbb-b4d3f415aa33;af043384-c8a5-451e-88f4-457914e8e3bc"/>
<!-- 多个ID节点形式 -->
<!-- <id value="e92edde5-0153-4ec8-9cbb-b4d3f415aa33"/>
<id value="af043384-c8a5-451e-88f4-457914e8e3bc"/> -->
</strategy-blacklist>
</rule>
变更为
<?xml version="1.0" encoding="UTF-8"?>
<rule>
<strategy-blacklist>
<id>20210601-222214-909-1146-372-698;20210601-222214-988-3281-569-232</id>
<!-- <id>{"discovery-guide-service-a":"20210601-222214-909-1146-372-698"}</id> -->
</strategy-blacklist>
</rule>
IP地址和端口屏蔽变更
下面规则
<?xml version="1.0" encoding="UTF-8"?>
<rule>
<strategy-blacklist>
<!-- 单个Address形式。如果多个用“;”分隔,不允许出现空格 -->
<address value="192.168.43.101:1201;192.168.*.102;1301"/>
<!-- 多个Address节点形式 -->
<!-- <address value="192.168.43.101:1201"/>
<address value="192.168.*.102"/>
<address value="1301"/> -->
</strategy-blacklist>
</rule>
变更为
<?xml version="1.0" encoding="UTF-8"?>
<rule>
<strategy-blacklist>
<address>192.168.43.101:1201;192.168.*.102;1301</address>
<!-- <address>{"discovery-guide-service-a":"3001"}</address> -->
</strategy-blacklist>
</rule>
Header传递的内容增加对Json格式的支持
n-d-id-blacklist={"discovery-guide-service-a":"20210601-222214-909-1146-372-698", "discovery-guide-service-b":"20210601-222623-277-4978-633-279"}
n-d-address-blacklist={"discovery-guide-service-a":"3001", "discovery-guide-service-b":"3001"}
利用通配符方式实现对指定日期上线的服务实例做屏蔽,示例内容如下,表示2021年6月1日(也可以精确到小时或者分钟)上线的a服务实例和b服务实例都会被屏蔽。该场景的使用意义是,在服务下线之前,使用者担心流量有损,同时使用者知道上一次服务发布的日期,只要该屏蔽策略一生效,负载均衡将实时过滤掉指定日期的服务实例。那么,使用者对这些服务实例无论是优雅停机,还是暴力下线,都不会造成任何流量有损,例如
<?xml version="1.0" encoding="UTF-8"?>
<rule>
<strategy-blacklist>
<id>{"discovery-guide-service-a":"20210601*", "discovery-guide-service-b":"20210601*"}</id>
</strategy-blacklist>
</rule>
重构优化内置Header配置
为考虑到对接DiscoveryPlatform,数据结构尽量用Json来统一描述
下面配置
<headers>
<header key="a" value="1"/>
<header key="b" value="2"/>
</headers>
变更为
<header>{"a":"1", "b":"2"}</header>
重构优化Sentinel模块
① Sentinel扩展配置中心
上个版本只支持Nacos和Apollo,本版本支持Consul、Etcd、Zookeeper、Redis,除了支持配置中心外,也支持读取本地配置文件,当配置中心和本地配置文件同时存在时,以配置中心为优先
- 依赖变更
下面三个依赖
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>discovery-plugin-strategy-starter-sentinel</artifactId>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>discovery-plugin-strategy-starter-sentinel-local</artifactId>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>discovery-plugin-strategy-starter-sentinel-apollo</artifactId>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>discovery-plugin-strategy-starter-sentinel-nacos</artifactId>
</dependency>
变更合并为如下一个依赖,囊括了六个配置中心
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>discovery-plugin-strategy-starter-sentinel-datasource</artifactId>
</dependency>
- 配置变更
下面配置变更
spring.application.strategy.sentinel.enabled=true
变更为
spring.application.strategy.sentinel.datasource.enabled=true
- 增强功能
支持本地规则文件读取,包括从classpath:xxx.json或者file:xxx.json两种方式读取
当配置中心存在对应规则时候,则忽略本地规则文件的规则;当配置中心不存在对应规则时候,则启动本地规则文件的规则
② Sentinel子模块重构
discovery-plugin-strategy-starter-service-sentinel模块主要实现Sentinel Limiter高级限流熔断,且不仅仅适用于微服务端,故用service-sentinel
的后缀来命名并不准确,故依赖名变更为discovery-plugin-strategy-starter-sentinel-limiter
下面依赖
<dependency>
<groupId>com.nepxion</groupId>
<artifactId>discovery-plugin-strategy-starter-service-sentinel</artifactId>
</dependency>
变更为
<dependency>
<groupId>com.nepxion</groupId>
<artifactId>discovery-plugin-strategy-starter-sentinel-limiter</artifactId>
</dependency>
下面配置变更(去掉service字段)
spring.application.strategy.service.sentinel.limit.app.enabled=true
spring.application.strategy.service.sentinel.request.origin.key=n-d-service-id
变更为
spring.application.strategy.sentinel.limit.app.enabled=true
spring.application.strategy.sentinel.request.origin.key=n-d-service-id
下面类名变更(去掉Service字段,加上Strategy字段)
ServiceSentinelRequestOriginAdapter
DefaultServiceSentinelRequestOriginAdapter
类变更为
SentinelStrategyRequestOriginAdapter
DefaultSentinelStrategyRequestOriginAdapter
重构优化其它模块
① 重构优化Common模块
- 抽象出中间件基本枚举类型,包括ConfigType,DiscoveryType,GatewayType,LoadBalancerType,ProtectorType,SentinelRuleType,TracingType等
- 抽象出ExceptionUtil,对于Endpoint统一异常封装
- 增加DiscoveryClientDelegate,为Plugin和Console模块提供代理接口
- DiscoveryResponseErrorHandler和RestUtil,方法名getCause更名为getError,做了统一规范
- JsonUtil增加Json字符串美化输出JsonUtil.toPrettyJson
- PropertiesUtil增加方法
- FileContextUtil从discovery-plugin-framework-starter模块移动到common模块,并重命名为FileUtil
- BeanRegisterUtil从discovery-plugin-framework-starter模块移动到common模块
- Dom4J通用类从discovery-plugin-framework-starter-parser模块移动到common模块
- 抽象出DiscoveryThreadPoolFactory,对Nacos和Consul配置模块的线程池做了统一封装
- 增加future通用模块,支持对WebFlux实现阻塞式获取数据
- 修改RelationalType枚举类型,&&改为and,||改为or,规避&&的转义
- 增加若干个枚举变量
- 修改和优化内置变量名
② 重构优化Framework模块
- 去掉RibbonProccessor
- 某些HashMap的变量改成LinkedHashMap
③ 重构优化Framework Parser
- PluginConfigParser和PluginConfigDeparser Bean的创建方式归属到Framework Parser模块
④ 重构优化配置订阅模块
- 优化所有通用配置自动装配spring.factories
- 增加所有配置订阅模块通过DisposableBean关闭订阅
- 增加所有配置订阅模块additional-spring-configuration-metadata.json
- 重构优化Redis配置订阅模块
- 重构优化Zookeeper配置订阅模块,TreeCache方式改为NodeCache,Sleep Time默认值从6秒改为3秒
- 规范化配置模块类对象的命名
⑤ 重构优化Admin Endpoint模块
- 抽象出Resource层,封装Endpoint逻辑,Endpoint调用Resource,第三方可以通过调用Resource层,进行Endpoint扩展和自定义
- 统一返回值为ResponseEntity,统一异常处理
- Endpoint初始化次序做了优化
- Endpoint如果返回值是Boolean类型,则返回值用true/false代替原来的ok/no,做了统一规范
- 优化Swagger描述和返回值,部分接口为提升友好性加入默认值
- 增加ServiceEndpoint
- 增加获取注册中心类型,配置中心类型的接口
- 增加根据网关类型列表获取网关服务名列表的接口
- 增加根据服务类型列表获取服务名列表的接口
- 增加根据服务名获取服务组名的接口
- DiscoveryClientDecorator暴露出getDelegate方法,为ServiceEndpoint提供注册中心类型的获取逻辑
- 其它更多接口
- 返回值进行排序
- 增加GatewayStrategyRouteEndpoint和ZuulStrategyRouteEndpoint接口
- 增加增加网关路由的接口
- 增加修改网关路由的接口
- 增加删除网关路由的接口
- 增加更新全部网关路由的接口
- 增加根据路由Id查看网关路由的接口
- 增加查看全部网关路由的接口
⑥ 重构优化Console Endpoint
- 分解ConsoleEndpoint为AuthenticationEndpoint,ConfigEndpoint,RouteEndpoint,SentinelEndpoint,ServiceEndpoint,StrategyEndpoint,VersionEndpoint
- 抽象出Resource层,封装Endpoint逻辑,Endpoint调用Resource,第三方可以通过调用Resource层,进行Endpoint扩展和自定义
- 统一返回值为ResponseEntity,统一异常处理
- 批量轮询调用返回对象ResultEntity加了serviceId、host和port三个字段
- Endpoint初始化次序做了优化
- Endpoint如果返回值是Boolean类型,则返回值用true/false代替原来的ok/no,做了统一规范
- 优化Swagger描述和返回值,部分接口为提升友好性加入默认值
- 增加AuthenticationEndpoint
- 修改登录校验接口,对接DiscoveryPlatform,引入Access Web Token机制
- 增加ConfigEndpoint
- 增加更新规则配置到远程配置中心的接口,把配置类型(包括 xml | json | yaml | properties | html | text)推送到配置中心(只支持Nacos配置中心,其它配置中心不适用)
- 增加批量查看规则配置的接口
- 增加规则配置字符串转对象(parse)和对象转字符串(deparse)的接口
- 增加RouteEndpoint
- 增加批量增加网关路由的接口
- 增加批量修改网关路由的接口
- 增加批量删除网关路由的接口
- 增加批量更新全部网关路由的接口
- 增加批量查看全部网关路由的接口
- 增加SentinelEndpoint
- 增加批量查看哨兵规则列表的接口
- 增加ServiceEndpoint
- 增加获取注册中心类型,配置中心类型的接口
- 增加根据网关类型获取网关服务名列表的接口
- 增加根据服务名获取服务组名的接口
- 其它更多接口
- 增加StrategyEndpoint
- 增加VersionEndpoint
- 增加批量查看版本的接口
⑦ 重构优化Strategy Service
- 优化ServiceStrategyRequestDecorator,去除不必要的getRequestURL和getRequestURI的代理,采用父类代理
⑧ 重构优化Strategy Gateway
- 增加Spring Cloud Gateway中SkyWalking的相关开关
# 开启和关闭从SkyWalking apm-agent-core里反射获取TraceId并复制。由于SkyWalking对WebFlux上下文Threadlocal处理机制不恰当,导致产生的TraceId在全链路中并不一致,打开这个开关可以保证全链路TraceId都是一致的。缺失则默认为true
spring.application.strategy.gateway.skywalking.traceid.enabled=true
⑨ 重构优化Swagger模块
- 自定义Swagger接口利用内置的SwaggerConfiguration来初始化,这样使用者可以不需要定义自己的SwaggerConfiguration。通过如下配置实现
swagger.service.scan.group=your-scan-group
swagger.service.scan.packages=your-scan-packages
- 自定义内置的基准Docket组名。通过如下配置实现
swagger.service.base.group=your-base-group
- Swagger界面显示的组名变更为Nepxion Discovery
- Swagger界面显示的版本号表达为Nepxion Discovery版本号
- 新增DiscoverySwaggerConstant用来定义静态变量
- 自定义覆盖内置的Swagger配置。通过如下配置实现
# 启动和关闭Swagger。缺失则默认为true
swagger.service.enabled=true
# Swagger基准Docket组名
swagger.service.base.group=Nepxion Discovery
# Swagger自定义Docket组名
swagger.service.scan.group=Admin Center Restful APIs
# Swagger自定义扫描目录
swagger.service.scan.packages=your-scan-packages
# Swagger描述
swagger.service.description=your-description
# Swagger版本
swagger.service.version=6.11.0
# Swagger License名称
swagger.service.license.name=Apache License 2.0
# Swagger License链接
swagger.service.license.url=http://www.apache.org/licenses/LICENSE-2.0
# Swagger联系人名称
swagger.service.contact.name=Nepxion
# Swagger联系人网址
swagger.service.contact.url=https://github.com/Nepxion/Discovery
# Swagger联系人邮件
[email protected]
# Swagger服务条件网址
swagger.service.termsOfService.url=http://www.nepxion.com
- 自定义基于Access Token Header的Swagger授权,包括全局授权和接口级授权。使用者通过如下方式进行扩展支持,可以选择其中一种,也可以两种并存。当两种并存的时候,全局授权优先于接口级授权
@Configuration
@ConditionalOnProperty(value = DiscoverySwaggerConstant.SWAGGER_SERVICE_ENABLED, matchIfMissing = true)
public class SwaggerAutoConfiguration {
// Access Token Header全局授权
@Bean
public List<SecurityScheme> swaggerSecuritySchemes() {
return Collections.singletonList(new ApiKey(DiscoveryConstant.N_D_ACCESS_TOKEN, DiscoveryConstant.N_D_ACCESS_TOKEN, "header"));
}
@Bean
public List<SecurityContext> swaggerSecurityContexts() {
return Collections.singletonList(
SecurityContext
.builder()
.securityReferences(Collections.singletonList(new SecurityReference(DiscoveryConstant.N_D_ACCESS_TOKEN, scopes())))
.forPaths(PathSelectors.any())
.build());
}
private AuthorizationScope[] scopes() {
return new AuthorizationScope[] { new AuthorizationScope("global", "accessAnything") };
}
// Access Token Header接口级授权
@Bean
public List<Parameter> swaggerHeaderParameters() {
return Collections.singletonList(
new ParameterBuilder()
.name(DiscoveryConstant.N_D_ACCESS_TOKEN)
.description("Access Token。格式:" + DiscoveryConstant.BEARER + "空格${access-token}。当全局授权(Authorize)后,此处不必填写")
.modelRef(new ModelRef("string"))
.parameterType("header")
.defaultValue(DiscoveryConstant.BEARER + " ${access-token}")
.required(false)
.build());
}
}
把SwaggerAutoConfiguration加入到src/main/resources/META-INF/spring.factories进行自动装配
⑩ 其它优化
-
优化日志打印
-
优化去除了一些无效依赖的引入
-
优化去除了一些过时方法的引用
-
优化指南示例的配置,增加Apollo Demo环境的配置
-
优化指南示例的测试用例
缺陷修复
① 修复在只引入注册中心依赖后(不引入其它三个依赖)无法启动的缺陷
② 修复Zookeeper重复订阅的缺陷
③ 修复Zookeeper服务发现时候,无法获取元数据的缺陷
④ 修复配置中心上,在删除配置后,响应事件回调值不是null的缺陷
⑤ 修复批量轮询调用,处理异常通过DiscoveryResponseErrorHandler返回异常信息的多线程缺陷,通过DiscoveryResponseContext中ThreadLocal予以修复
⑥ 修复Spring Boot 1.5版本重复触发反订阅事件的缺陷
⑦ 修复Spring Cloud Gateway和WebClient重复设置Header的缺陷
⑧ 修复外置Parameter、Cookie传递和内置Header并存时候,前两者失效的缺陷,取值顺序调整为外置Parameter > 外置Cookie > 外置Header > 内置Header
⑨ 修复全局灰度条件和局部灰度条件并存时候,取值顺序调整为局部灰度条件 > 全局灰度条件
⑩ 修复服务侧在无法获取到内置Header的缺陷
⑪ 更改内置Header的Map类型为LinkedCaseInsensitiveMap,大小写不敏感
⑫ 修复修复极端情况下SkyWalkingGatewayStrategyFilter引起的服务调用失败。感谢@jimodebeiju123贡献的PR
相关发布
DiscoveryAgent发布
DiscoveryAgent发布1.1.0版
重构优化
- 优化Agent和Example的Pom结构
- 优化Agent异常抛出
缺陷修复
- 修复在线程没有切换的情况下,也会进入插件执行的缺陷
- 修复agent.config文件重复打包的缺陷
感谢@zifenhan贡献的PR
DiscoveryDesktop发布
DiscoveryDesktop发布发布1.1.0版
功能迭代
- 对接DiscoveryPlatform,支持Shiro和JWT的登录以及鉴权
相关下载
DiscoveryAgent下载
访问https://github.com/Nepxion/DiscoveryAgent/releases
获取最新版本
DiscoveryDesktop下载
访问https://github.com/Nepxion/DiscoveryUI/releases
获取最新版本