Skip to content

Commit ee29a03

Browse files
committed
灰度发布添加对zookeeper的支持
1 parent 40ad2fd commit ee29a03

File tree

18 files changed

+190
-155
lines changed

18 files changed

+190
-155
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
* spring-cloud-start-gray
2222
* spring-cloud-start-gray-server
2323
* [spring-cloud-gray-samples](spring-cloud-gray-samples/README.md)
24+
* [spring-cloud-gray-zookeeper-samples](spring-cloud-gray-zookeeper-samples/README.md)
2425

2526
#### maven 依赖
2627
jar包已经上传到maven中央库,可以通过maven直接从中央库下载

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

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
import cn.springcloud.bamboo.autoconfig.BambooAutoConfiguration;
55
import cn.springcloud.gray.DefaultGrayManager;
66
import cn.springcloud.gray.HttpInformationClient;
7-
import cn.springcloud.gray.InstanceLocalInfo;
87
import cn.springcloud.gray.RetryableInformationClient;
98
import cn.springcloud.gray.client.GrayClientInitializingBean;
109
import cn.springcloud.gray.client.GrayOptionalArgs;
@@ -13,15 +12,12 @@
1312
import cn.springcloud.gray.core.GrayManager;
1413
import cn.springcloud.gray.core.InformationClient;
1514
import cn.springcloud.gray.decision.DefaultGrayDecisionFactory;
16-
import cn.springcloud.gray.utils.ServiceUtil;
1715
import org.springframework.beans.factory.annotation.Autowired;
1816
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
1917
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
2018
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
2119
import org.springframework.boot.context.properties.EnableConfigurationProperties;
22-
import org.springframework.cloud.client.serviceregistry.Registration;
2320
import org.springframework.cloud.netflix.ribbon.RibbonClients;
24-
import org.springframework.context.ApplicationContext;
2521
import org.springframework.context.annotation.Bean;
2622
import org.springframework.context.annotation.Configuration;
2723
import org.springframework.core.annotation.Order;
@@ -53,23 +49,6 @@ public GrayClientInitializingBean grayClientInitializingBean() {
5349
return new GrayClientInitializingBean();
5450
}
5551

56-
57-
@Bean
58-
@ConditionalOnMissingBean
59-
public InstanceLocalInfo instanceLocalInfo(@Autowired ApplicationContext context,
60-
@Autowired Registration registration) {
61-
String instanceId = ServiceUtil.getInstanceId(registration);
62-
if(null == instanceId){
63-
context.getId();
64-
}
65-
66-
InstanceLocalInfo localInfo = new InstanceLocalInfo();
67-
localInfo.setInstanceId(instanceId);
68-
localInfo.setServiceId(registration.getServiceId());
69-
localInfo.setGray(false);
70-
return localInfo;
71-
}
72-
7352
@Bean
7453
@ConditionalOnMissingBean
7554
public GrayDecisionFactory grayDecisionFactory() {
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package cn.springcloud.gray.client.config;
2+
3+
import cn.springcloud.gray.InstanceLocalInfo;
4+
import com.netflix.discovery.EurekaClient;
5+
import org.springframework.beans.factory.annotation.Autowired;
6+
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
7+
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
8+
import org.springframework.cloud.netflix.eureka.serviceregistry.EurekaRegistration;
9+
import org.springframework.context.annotation.Bean;
10+
import org.springframework.context.annotation.Configuration;
11+
12+
/**
13+
* @Author: duozl
14+
* @Date: 2018/6/5 18:18
15+
*/
16+
@Configuration
17+
@ConditionalOnBean(EurekaClient.class)
18+
public class GrayClientEurekaAutoConfiguration {
19+
20+
@Bean
21+
@ConditionalOnMissingBean
22+
public InstanceLocalInfo instanceLocalInfo(@Autowired EurekaRegistration registration) {
23+
String instanceId = registration.getInstanceConfig().getInstanceId();
24+
25+
InstanceLocalInfo localInfo = new InstanceLocalInfo();
26+
localInfo.setInstanceId(instanceId);
27+
localInfo.setServiceId(registration.getServiceId());
28+
localInfo.setGray(false);
29+
return localInfo;
30+
}
31+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package cn.springcloud.gray.client.config;
2+
3+
import cn.springcloud.gray.InstanceLocalInfo;
4+
import org.springframework.beans.factory.annotation.Autowired;
5+
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
6+
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
7+
import org.springframework.cloud.client.serviceregistry.Registration;
8+
import org.springframework.cloud.zookeeper.discovery.ZookeeperDiscoveryProperties;
9+
import org.springframework.cloud.zookeeper.serviceregistry.ZookeeperRegistration;
10+
import org.springframework.context.annotation.Bean;
11+
import org.springframework.context.annotation.Configuration;
12+
13+
import javax.naming.ConfigurationException;
14+
15+
/**
16+
* @Author: duozl
17+
* @Date: 2018/6/5 18:18
18+
*/
19+
@Configuration
20+
@ConditionalOnBean(ZookeeperRegistration.class)
21+
public class GrayClientZookeeperAutoConfiguration {
22+
private static final String METADATA_KEY_INSTANCE_ID = "instanceId";
23+
24+
@Bean
25+
@ConditionalOnMissingBean
26+
public InstanceLocalInfo instanceLocalInfo(@Autowired Registration registration,
27+
@Autowired ZookeeperDiscoveryProperties properties)
28+
throws ConfigurationException {
29+
String instanceId;
30+
if (properties.getMetadata().containsKey(METADATA_KEY_INSTANCE_ID)) {
31+
instanceId = properties.getMetadata().get(METADATA_KEY_INSTANCE_ID);
32+
} else {
33+
throw new ConfigurationException("Unable to find config spring.cloud.zookeeper.discovery.metadata" +
34+
".instanceId!");
35+
}
36+
37+
InstanceLocalInfo localInfo = new InstanceLocalInfo();
38+
localInfo.setInstanceId(instanceId);
39+
localInfo.setServiceId(registration.getServiceId());
40+
localInfo.setGray(false);
41+
return localInfo;
42+
}
43+
}

spring-cloud-gray-client/src/main/java/cn/springcloud/gray/client/config/properties/GrayClientProperties.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,10 @@ public void setRetryNumberOfRetries(int retryNumberOfRetries) {
8686
*/
8787
public class InstanceConfig {
8888

89-
private boolean grayEnroll;
89+
private boolean grayEnroll = false;
9090
private int grayEnrollDealyTimeInMs = 40000;
9191
private boolean useMultiVersion = false;
92+
private String instanceId;
9293

9394
public boolean isGrayEnroll() {
9495
return grayEnroll;
@@ -118,5 +119,13 @@ public boolean isUseMultiVersion() {
118119
public void setUseMultiVersion(boolean useMultiVersion) {
119120
this.useMultiVersion = useMultiVersion;
120121
}
122+
123+
public String getInstanceId() {
124+
return instanceId;
125+
}
126+
127+
public void setInstanceId(String instanceId) {
128+
this.instanceId = instanceId;
129+
}
121130
}
122131
}

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

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package cn.springcloud.gray.ribbon;
22

3+
import cn.springcloud.bamboo.BambooAppContext;
34
import cn.springcloud.bamboo.BambooRequest;
45
import cn.springcloud.bamboo.BambooRequestContext;
56
import cn.springcloud.gray.core.GrayDecision;
@@ -9,6 +10,7 @@
910
import com.netflix.loadbalancer.Server;
1011

1112
import java.util.List;
13+
import java.util.Map;
1214

1315
public class GrayDecisionPredicate extends AbstractServerPredicate {
1416

@@ -22,12 +24,14 @@ public boolean apply(PredicateKey input) {
2224
if (bambooRequestContext == null || bambooRequestContext.getBambooRequest() == null) {
2325
return false;
2426
}
27+
BambooRequest bambooRequest = bambooRequestContext.getBambooRequest();
2528
Server server = input.getServer();
26-
String instanceId = ServiceUtil.getInstanceId(server);
29+
String serviceId = bambooRequest.getServiceId();
30+
Map<String, String> serverMetadata = getServerMetadata(serviceId, server);
31+
String instanceId = ServiceUtil.getInstanceId(server, serverMetadata);
2732

28-
BambooRequest bambooRequest = bambooRequestContext.getBambooRequest();
2933
List<GrayDecision> grayDecisions =
30-
getIRule().getGrayManager().grayDecision(bambooRequest.getServiceId(), instanceId);
34+
getIRule().getGrayManager().grayDecision(serviceId, instanceId);
3135
for (GrayDecision grayDecision : grayDecisions) {
3236
if (grayDecision.test(bambooRequest)) {
3337
return true;
@@ -41,5 +45,7 @@ protected GrayLoadBalanceRule getIRule() {
4145
return (GrayLoadBalanceRule) this.rule;
4246
}
4347

44-
48+
public Map<String, String> getServerMetadata(String serviceId, Server server) {
49+
return BambooAppContext.getEurekaServerExtractor().getServerMetadata(serviceId, server);
50+
}
4551
}

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

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package cn.springcloud.gray.ribbon;
22

3+
import cn.springcloud.bamboo.BambooAppContext;
34
import cn.springcloud.bamboo.BambooRequestContext;
45
import cn.springcloud.bamboo.ribbon.loadbalancer.BambooZoneAvoidanceRule;
56
import cn.springcloud.gray.client.GrayClientAppContext;
@@ -13,6 +14,7 @@
1314

1415
import java.util.ArrayList;
1516
import java.util.List;
17+
import java.util.Map;
1618

1719
/**
1820
* 灰度发布的负载规则
@@ -46,13 +48,15 @@ protected void init(){
4648
public Server choose(Object key) {
4749
ILoadBalancer lb = getLoadBalancer();
4850
BambooRequestContext requestContext = BambooRequestContext.currentRequestCentxt();
49-
if (requestContext != null && getGrayManager().isOpen(requestContext.getServiceId())) {
50-
GrayService grayService = getGrayManager().grayService(requestContext.getServiceId());
51+
String serviceId = requestContext.getServiceId();
52+
if (requestContext != null && getGrayManager().isOpen(serviceId)) {
53+
GrayService grayService = getGrayManager().grayService(serviceId);
5154
List<Server> servers = lb.getAllServers();
5255
List<Server> grayServers = new ArrayList<>(grayService.getGrayInstances().size());
5356
List<Server> normalServers = new ArrayList<>(servers.size() - grayService.getGrayInstances().size());
5457
for (Server server : servers) {
55-
String instanceId = ServiceUtil.getInstanceId(server);
58+
Map<String, String> serverMetadata = getServerMetadata(serviceId, server);
59+
String instanceId = ServiceUtil.getInstanceId(server, serverMetadata);
5660
if (grayService.getGrayInstance(instanceId) != null) {
5761
grayServers.add(server);
5862
} else {
@@ -98,8 +102,11 @@ private Server choose(AbstractServerPredicate serverPredicate, List<Server> serv
98102
}
99103
}
100104

101-
102105
public GrayManager getGrayManager() {
103106
return GrayClientAppContext.getGrayManager();
104107
}
108+
109+
public static Map<String, String> getServerMetadata(String serviceId, Server server) {
110+
return BambooAppContext.getEurekaServerExtractor().getServerMetadata(serviceId, server);
111+
}
105112
}
Lines changed: 11 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,30 @@
11
package cn.springcloud.gray.utils;
22

33
import com.netflix.loadbalancer.Server;
4-
import org.apache.curator.x.discovery.ServiceInstance;
5-
import org.springframework.cloud.client.serviceregistry.Registration;
6-
import org.springframework.cloud.netflix.eureka.serviceregistry.EurekaRegistration;
7-
import org.springframework.cloud.zookeeper.discovery.ZookeeperInstance;
84
import org.springframework.cloud.zookeeper.discovery.ZookeeperServer;
9-
import org.springframework.cloud.zookeeper.serviceregistry.ZookeeperRegistration;
5+
6+
import java.util.Map;
107

118
/**
129
* @Author: duozl
1310
* @Date: 2018/6/5 15:56
1411
*/
1512
public class ServiceUtil {
13+
private static final String METADATA_KEY_INSTANCE_ID = "instanceId";
1614

17-
public static String getInstanceId(Server server) {
18-
String instanceId;
15+
public static String getInstanceId(Server server, Map<String, String> serverMetadata) {
1916
try {
2017
if (server instanceof ZookeeperServer) {
21-
return server.getHostPort();
22-
}
23-
} catch (Exception e) {
24-
// do nothing,可能是类找不到等原因,如果引入了zookeeper的依赖,这个不会找不到
25-
}
26-
instanceId = server.getMetaInfo().getInstanceId();
27-
return instanceId;
28-
}
29-
30-
public static String getInstanceId(Registration registration) {
31-
String instanceId = null;
32-
try {
33-
if (registration instanceof ZookeeperRegistration) {
34-
ServiceInstance<ZookeeperInstance> instance = ((ZookeeperRegistration) registration)
35-
.getServiceInstance();
36-
instanceId = instance.getAddress() + ":" + instance.getPort();
18+
if (serverMetadata.containsKey(METADATA_KEY_INSTANCE_ID)) {
19+
return serverMetadata.get(METADATA_KEY_INSTANCE_ID);
20+
} else {
21+
throw new IllegalStateException("Unable to find config spring.cloud.zookeeper.discovery.metadata" +
22+
".instanceId!");
23+
}
3724
}
3825
} catch (Throwable e) {
3926
// do nothing,可能是类找不到等原因,如果引入了zookeeper的依赖,这个不会找不到
4027
}
41-
42-
try {
43-
if (registration instanceof EurekaRegistration) {
44-
instanceId = ((EurekaRegistration) registration).getInstanceConfig().getInstanceId();
45-
}
46-
} catch (Throwable e) {
47-
// do nothing,可能是类找不到等原因,如果引入了eureka的依赖,这个不会找不到
48-
}
49-
50-
return instanceId;
28+
return server.getMetaInfo().getInstanceId();
5129
}
5230
}

spring-cloud-gray-samples/spring-cloud-gray-service-a-sample/src/main/resources/config/application.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ spring:
22
application:
33
name: service-a
44
server:
5-
port: 20101
5+
port: 20103
66
eureka:
77
client:
88
register-with-eureka: true
@@ -14,5 +14,5 @@ eureka:
1414
gray:
1515
client:
1616
instance:
17-
grayEnroll: false #是否在启动后自动注册成灰度实例
17+
grayEnroll: true #是否在启动后自动注册成灰度实例
1818
serverUrl: http://localhost:20202 #灰度服务端的url

0 commit comments

Comments
 (0)