Skip to content

Commit 721720a

Browse files
authored
Merge pull request #53 from SpringCloud/A
A
2 parents 17cdbd1 + e2d79b7 commit 721720a

File tree

59 files changed

+486
-131
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+486
-131
lines changed

README.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22

33

44
[![License](https://img.shields.io/badge/license-Apache%202-blue.svg)](https://www.apache.org/licenses/LICENSE-2.0.html)
5-
[![A Release](https://img.shields.io/badge/release-A.1.1.3-blue)](https://github.com/SpringCloud/spring-cloud-gray/releases/tag/A.1.1.2)
6-
[![B Release](https://img.shields.io/badge/release-B.0.0.4-blue)](https://github.com/SpringCloud/spring-cloud-gray/releases/tag/B.0.0.2)
7-
[![B Release](https://img.shields.io/badge/release-C.0.0.3-blue)](https://github.com/SpringCloud/spring-cloud-gray/releases/tag/C.0.0.1)
5+
[![A Release](https://img.shields.io/badge/release-A.1.1.6-blue)](https://github.com/SpringCloud/spring-cloud-gray/releases/tag/A.1.1.6)
6+
[![B Release](https://img.shields.io/badge/release-B.0.0.6-blue)](https://github.com/SpringCloud/spring-cloud-gray/releases/tag/B.0.0.6)
7+
[![B Release](https://img.shields.io/badge/release-C.0.0.5-blue)](https://github.com/SpringCloud/spring-cloud-gray/releases/tag/C.0.0.5)
88

99
## 介绍
1010
Spring Cloud Gray 是一套开源的微服务灰度路由解决方案,它由spring-cloud-gray-client,spring-cloud-gray-client-netflix 和 spring-cloud-tray-server,spring-cloud-gray-webui组成。<br/>
@@ -34,11 +34,11 @@ insert into `user` ( `user_id`, `account`, `name`, `password`, `roles`, `status`
3434
[管控端界面使用手册](doc/guide/gray-admin-guide.md)<br/>
3535

3636
## 版本信息
37-
项目分支 | srpingcloud版本 | springboot版本
38-
--- | --- | ---
39-
A | Edgware | 1.5.*
40-
B | Finchley | 2.0.*
41-
C | Greenwich | 2.1.*
37+
项目分支 | 项目版本 | srpingcloud版本 | springboot版本
38+
--- | --- | --- | ---
39+
A | A.1.1.6 | Edgware | 1.5.*
40+
B | B.0.0.6 | Finchley | 2.0.*
41+
C | C.0.0.5 | Greenwich | 2.1.*
4242

4343

4444
## Spring Cloud Gray 能做什么

pom.xml

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
<groupId>cn.springcloud.gray</groupId>
1313
<artifactId>spring-cloud-gray</artifactId>
1414
<packaging>pom</packaging>
15-
<version>A.1.1.3</version>
15+
<version>A.1.1.6</version>
1616
<url>https://github.com/SpringCloud/spring-cloud-gray</url>
1717
<organization>
1818
<name>Spring Cloud中国社区</name>
@@ -56,7 +56,6 @@
5656
<developerConnection>scm:git:[email protected]:SpringCloud/spring-cloud-gray.git</developerConnection>
5757
</scm>
5858

59-
6059
<properties>
6160
<maven.compiler.source>1.8</maven.compiler.source>
6261
<maven.compiler.target>1.8</maven.compiler.target>
@@ -165,8 +164,6 @@
165164
</dependency>
166165

167166

168-
169-
170167
<!-- gray client plugins start -->
171168

172169
<dependency>

spring-cloud-gray-client-netflix/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<parent>
66
<artifactId>spring-cloud-gray</artifactId>
77
<groupId>cn.springcloud.gray</groupId>
8-
<version>A.1.1.3</version>
8+
<version>A.1.1.6</version>
99
</parent>
1010
<modelVersion>4.0.0</modelVersion>
1111

spring-cloud-gray-client-netflix/src/main/java/cn/springcloud/gray/client/netflix/RibbonServerChooser.java

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import cn.springcloud.gray.servernode.ServerListProcessor;
1313
import cn.springcloud.gray.servernode.ServerSpec;
1414
import com.netflix.loadbalancer.Server;
15+
import lombok.extern.slf4j.Slf4j;
1516
import org.apache.commons.collections.CollectionUtils;
1617
import org.apache.commons.collections.ListUtils;
1718
import org.apache.commons.lang3.StringUtils;
@@ -21,6 +22,7 @@
2122
import java.util.Objects;
2223
import java.util.stream.Collectors;
2324

25+
@Slf4j
2426
public class RibbonServerChooser implements ServerChooser<Server> {
2527

2628
private GrayManager grayManager;
@@ -60,7 +62,8 @@ public boolean matchGrayDecisions(Server server) {
6062
@Override
6163
public ServerListResult<Server> distinguishServerList(List<Server> servers) {
6264
String serviceId = getServiceId(servers);
63-
if(StringUtils.isEmpty(serviceId)){
65+
if (StringUtils.isEmpty(serviceId)) {
66+
log.warn("没有获取到当前remote request的service id, 返回null");
6467
return null;
6568
}
6669
return distinguishServerList(serviceId, servers);
@@ -75,23 +78,27 @@ public ServerListResult<Server> distinguishAndMatchGrayServerList(List<Server> s
7578
}
7679

7780
if (GrayClientHolder.getGraySwitcher().isEanbleGrayRouting()) {
78-
serverListResult.setGrayServers(
79-
serverListResult.getGrayServers().stream()
80-
.filter(this::matchGrayDecisions)
81-
.collect(Collectors.toList()));
82-
}else{
81+
log.debug("开始匹配{}服务的灰度实例", serverListResult.getServiceId());
82+
List<Server> matchedGrayServers = serverListResult.getGrayServers().stream()
83+
.filter(this::matchGrayDecisions)
84+
.collect(Collectors.toList());
85+
log.debug("{} 服务共有{}个灰度实例,本次匹配到{}个",
86+
serverListResult.getServiceId(), serverListResult.getGrayServers().size(), matchedGrayServers.size());
87+
serverListResult.setGrayServers(matchedGrayServers);
88+
} else {
89+
log.debug("grayRouting未打开,将{}服务的灰度实例清空,使之路由到正常实例", serverListResult.getServiceId());
8390
serverListResult.setGrayServers(ListUtils.EMPTY_LIST);
8491
}
8592

8693
return serverListResult;
8794
}
8895

89-
private String getServiceId(List<Server> servers){
96+
private String getServiceId(List<Server> servers) {
9097
GrayRequest grayRequest = requestLocalStorage.getGrayRequest();
9198
if (grayRequest != null && StringUtils.isNotEmpty(grayRequest.getServiceId())) {
9299
return grayRequest.getServiceId();
93100
}
94-
if(CollectionUtils.isNotEmpty(servers)) {
101+
if (CollectionUtils.isNotEmpty(servers)) {
95102
Server server = servers.get(0);
96103
if (!Objects.isNull(server)) {
97104
return server.getMetaInfo().getServiceIdForDiscovery();
@@ -103,6 +110,7 @@ private String getServiceId(List<Server> servers){
103110

104111
private ServerListResult<Server> distinguishServerList(String serviceId, List<Server> servers) {
105112
if (!grayManager.hasGray(serviceId)) {
113+
log.debug("当前灰度开关未打开,或服务 '{}'没有相关灰度策略", serviceId);
106114
return null;
107115
}
108116

@@ -119,6 +127,7 @@ private ServerListResult<Server> distinguishServerList(String serviceId, List<Se
119127
}
120128
}
121129

130+
log.debug("区分服务实例灰度状态: 服务 {} 实例数:{total: {}, gray:{}, normal:{}}", serviceId, servers.size(), grayServers.size(), normalServers.size());
122131
return new ServerListResult<>(serviceId, grayServers, normalServers);
123132
}
124133
}

spring-cloud-gray-client-netflix/src/main/java/cn/springcloud/gray/client/netflix/ribbon/GrayChooserRule.java

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55
import com.google.common.base.Optional;
66
import com.netflix.loadbalancer.Server;
77
import com.netflix.loadbalancer.ZoneAvoidanceRule;
8+
import lombok.extern.slf4j.Slf4j;
89

10+
@Slf4j
911
public class GrayChooserRule extends ZoneAvoidanceRule {
1012

1113
private ServerChooser<Server> serverChooser;
@@ -16,13 +18,18 @@ public GrayChooserRule() {
1618

1719
@Override
1820
public Server choose(Object key) {
19-
return serverChooser.chooseServer(getLoadBalancer().getAllServers(), servers -> {
20-
Optional<Server> server = getPredicate().chooseRoundRobinAfterFiltering(servers, key);
21-
if (server.isPresent()) {
22-
return server.get();
23-
} else {
24-
return null;
25-
}
26-
});
21+
try {
22+
return serverChooser.chooseServer(getLoadBalancer().getAllServers(), servers -> {
23+
Optional<Server> server = getPredicate().chooseRoundRobinAfterFiltering(servers, key);
24+
if (server.isPresent()) {
25+
return server.get();
26+
} else {
27+
return null;
28+
}
29+
});
30+
} catch (Exception e) {
31+
log.warn("gray choose server occur exception:{}, execute super method.", e.getMessage(), e);
32+
return super.choose(key);
33+
}
2734
}
2835
}

spring-cloud-gray-client-netflix/src/main/java/cn/springcloud/gray/client/netflix/ribbon/configuration/GrayRibbonClientsConfiguration.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,15 @@
77
import com.netflix.loadbalancer.IRule;
88
import com.netflix.loadbalancer.ZoneAvoidanceRule;
99
import org.springframework.beans.factory.annotation.Autowired;
10+
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
1011
import org.springframework.context.annotation.Bean;
1112
import org.springframework.context.annotation.Configuration;
1213

1314
@Configuration
1415
public class GrayRibbonClientsConfiguration {
1516

1617
@Bean
18+
@ConditionalOnProperty(value = "gray.route.ribbon.rule.default-definition", matchIfMissing = true)
1719
public IRule ribbonRule(
1820
@Autowired(required = false) IClientConfig config) {
1921
ZoneAvoidanceRule rule = null;

spring-cloud-gray-client/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<parent>
66
<artifactId>spring-cloud-gray</artifactId>
77
<groupId>cn.springcloud.gray</groupId>
8-
<version>A.1.1.3</version>
8+
<version>A.1.1.6</version>
99
</parent>
1010
<modelVersion>4.0.0</modelVersion>
1111

spring-cloud-gray-client/src/main/java/cn/springcloud/gray/GrayClientHolder.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,14 @@
22

33
import cn.springcloud.gray.client.switcher.GraySwitcher;
44
import cn.springcloud.gray.local.InstanceLocalInfo;
5+
import cn.springcloud.gray.request.GrayRequest;
56
import cn.springcloud.gray.request.LocalStorageLifeCycle;
67
import cn.springcloud.gray.request.RequestLocalStorage;
78
import cn.springcloud.gray.servernode.ServerExplainer;
89
import cn.springcloud.gray.servernode.ServerListProcessor;
910

11+
import java.util.Objects;
12+
1013
public class GrayClientHolder {
1114

1215
private static GrayManager grayManager;
@@ -82,4 +85,15 @@ public static <SERVER> ServerChooser<SERVER> getServerChooser() {
8285
public static void setServerChooser(ServerChooser<?> serverChooser) {
8386
GrayClientHolder.serverChooser = serverChooser;
8487
}
88+
89+
90+
/**
91+
* 获取当前remote request的service id
92+
*
93+
* @return
94+
*/
95+
public static String getCurrentRequestServiceId() {
96+
GrayRequest grayRequest = getRequestLocalStorage().getGrayRequest();
97+
return Objects.isNull(grayRequest) ? null : grayRequest.getServiceId();
98+
}
8599
}

spring-cloud-gray-client/src/main/java/cn/springcloud/gray/ServerChooser.java

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22

33
import cn.springcloud.gray.choose.ListChooser;
44
import cn.springcloud.gray.servernode.ServerSpec;
5+
import cn.springcloud.gray.utils.LogUtils;
56
import org.apache.commons.collections.CollectionUtils;
7+
import org.slf4j.Logger;
68

79
import java.util.List;
810

@@ -36,15 +38,26 @@ default Server chooseServer(List<Server> servers, ListChooser<Server> chooser) {
3638
return chooser.choose(servers);
3739
}
3840

39-
if (GrayClientHolder.getGraySwitcher().isEanbleGrayRouting()) {
40-
if (CollectionUtils.isNotEmpty(serverListResult.getGrayServers())) {
41-
Server server = chooser.choose(serverListResult.getGrayServers());
42-
if (server != null) {
43-
return server;
44-
}
45-
}
41+
Logger log = LogUtils.logger(ServerChooser.class);
42+
43+
if (!GrayClientHolder.getGraySwitcher().isEanbleGrayRouting()) {
44+
log.warn("grayRouting未打开,从正常实例列表中挑选");
45+
return chooser.choose(serverListResult.getNormalServers());
46+
}
47+
48+
if (CollectionUtils.isEmpty(serverListResult.getGrayServers())) {
49+
log.debug("没有匹配的灰度实例,从正常实例列表中挑选");
50+
return chooser.choose(serverListResult.getNormalServers());
51+
}
52+
53+
log.debug("开始从灰度实例列表中负载挑选...");
54+
Server server = chooser.choose(serverListResult.getGrayServers());
55+
if (server != null) {
56+
log.debug("从灰度实例列表成功负载挑选到 {}", server);
57+
return server;
4658
}
4759

60+
log.warn("从灰度实例列表负载挑选失败,从正常实例列表中挑选");
4861
return chooser.choose(serverListResult.getNormalServers());
4962
}
5063

Lines changed: 53 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,20 @@
11
package cn.springcloud.gray.choose;
22

33
import cn.springcloud.gray.GrayManager;
4+
import cn.springcloud.gray.decision.BringPolicyDefinitionGrayDecision;
45
import cn.springcloud.gray.decision.GrayDecision;
56
import cn.springcloud.gray.decision.GrayDecisionInputArgs;
7+
import cn.springcloud.gray.model.PolicyDefinition;
68
import cn.springcloud.gray.request.GrayRequest;
79
import cn.springcloud.gray.request.RequestLocalStorage;
810
import cn.springcloud.gray.servernode.ServerSpec;
11+
import cn.springcloud.gray.utils.JsonUtils;
12+
import lombok.extern.slf4j.Slf4j;
913

14+
import java.io.IOException;
1015
import java.util.List;
1116

17+
@Slf4j
1218
public class DefaultGrayPredicate implements GrayPredicate {
1319

1420
private RequestLocalStorage requestLocalStorage;
@@ -22,30 +28,71 @@ public DefaultGrayPredicate(RequestLocalStorage requestLocalStorage, GrayManager
2228

2329
@Override
2430
public boolean apply(ServerSpec serverSpec) {
25-
GrayDecisionInputArgs decisionInputArgs = GrayDecisionInputArgs
26-
.builder().grayRequest(requestLocalStorage.getGrayRequest()).server(serverSpec).build();
31+
GrayDecisionInputArgs decisionInputArgs = GrayDecisionInputArgs.builder()
32+
.grayRequest(requestLocalStorage.getGrayRequest())
33+
.server(serverSpec)
34+
.build();
2735
return apply(decisionInputArgs);
2836
}
2937

3038
@Override
3139
public boolean apply(GrayDecisionInputArgs decisionInputArgs) {
3240
GrayRequest grayRequest = decisionInputArgs.getGrayRequest();
33-
if(grayRequest==null){
41+
if (grayRequest == null) {
3442
return false;
3543
}
3644
ServerSpec serverSpec = decisionInputArgs.getServer();
37-
if(serverSpec==null){
45+
if (serverSpec == null) {
3846
return false;
3947
}
4048

4149
List<GrayDecision> grayDecisions =
4250
grayManager.getGrayDecision(serverSpec.getServiceId(), serverSpec.getInstanceId());
4351

44-
for (GrayDecision grayDecision : grayDecisions) {
45-
if (grayDecision.test(decisionInputArgs)) {
52+
for (int i = 0; i < grayDecisions.size(); i++) {
53+
GrayDecision grayDecision = grayDecisions.get(i);
54+
boolean testValue = grayDecision.test(decisionInputArgs);
55+
printGrayPolicyDecisionInfo(decisionInputArgs, grayDecision, testValue, grayDecisions.size(), i);
56+
if (testValue) {
4657
return true;
4758
}
4859
}
4960
return false;
5061
}
62+
63+
64+
private void printGrayPolicyDecisionInfo(
65+
GrayDecisionInputArgs decisionInputArgs,
66+
GrayDecision grayDecision,
67+
boolean testValue,
68+
int decisionLength,
69+
int currentDecisionIndex) {
70+
if (!log.isDebugEnabled()) {
71+
return;
72+
}
73+
try {
74+
if (grayDecision instanceof BringPolicyDefinitionGrayDecision) {
75+
BringPolicyDefinitionGrayDecision policyDefinitionGrayDecision = (BringPolicyDefinitionGrayDecision) grayDecision;
76+
PolicyDefinition policyDefinition = policyDefinitionGrayDecision.getPolicyDefinition();
77+
log.debug("【灰度决策】服务'{}'的实例'{}' ,'{}-{}'决策结果为'{}'; \ndecisionInputArgs: {}, \npolicyDefinition: {}",
78+
decisionInputArgs.getGrayRequest().getServiceId(),
79+
decisionInputArgs.getServer().getInstanceId(),
80+
decisionLength,
81+
currentDecisionIndex + 1,
82+
testValue,
83+
JsonUtils.toJson(decisionInputArgs),
84+
JsonUtils.toJson(policyDefinition));
85+
}
86+
log.debug("【灰度决策】服务'{}'的实例'{}' ,'{}-{}'决策结果为'{}'; \ndecisionInputArgs: {}",
87+
decisionInputArgs.getGrayRequest().getServiceId(),
88+
decisionInputArgs.getServer().getInstanceId(),
89+
decisionLength,
90+
currentDecisionIndex + 1,
91+
testValue,
92+
JsonUtils.toJson(decisionInputArgs));
93+
} catch (IOException e) {
94+
log.error("", e);
95+
}
96+
97+
}
5198
}

0 commit comments

Comments
 (0)