Commit 91518365 by Nepxion

客户定制化控制,由远程推送客户化参数的改变,实现一些特色化的灰度发布

parent 1101aa31
package com.nepxion.discovery.common.entity;
/**
* <p>Title: Nepxion Discovery</p>
* <p>Description: Nepxion Discovery</p>
* <p>Copyright: Copyright (c) 2017-2050</p>
* <p>Company: Nepxion</p>
* @author Haojun Ren
* @version 1.0
*/
import java.io.Serializable;
import java.util.LinkedHashMap;
import java.util.Map;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
public class CustomizationEntity implements Serializable {
private static final long serialVersionUID = -5135099669922746855L;
private Map<String, Map<String, String>> customizationMap = new LinkedHashMap<String, Map<String, String>>();
public CustomizationEntity() {
}
public Map<String, Map<String, String>> getCustomizationMap() {
return customizationMap;
}
public void setCustomizationMap(Map<String, Map<String, String>> customizationMap) {
this.customizationMap = customizationMap;
}
@Override
public int hashCode() {
return HashCodeBuilder.reflectionHashCode(this);
}
@Override
public boolean equals(Object object) {
return EqualsBuilder.reflectionEquals(this, object);
}
@Override
public String toString() {
return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE);
}
}
\ No newline at end of file
......@@ -21,6 +21,7 @@ public class RuleEntity implements Serializable {
private RegisterEntity registerEntity;
private DiscoveryEntity discoveryEntity;
private CustomizationEntity customizationEntity;
private String content;
public RegisterEntity getRegisterEntity() {
......@@ -39,6 +40,14 @@ public class RuleEntity implements Serializable {
this.discoveryEntity = discoveryEntity;
}
public CustomizationEntity getCustomizationEntity() {
return customizationEntity;
}
public void setCustomizationEntity(CustomizationEntity customizationEntity) {
this.customizationEntity = customizationEntity;
}
public String getContent() {
return content;
}
......
......@@ -22,6 +22,7 @@ import com.nepxion.discovery.plugin.configcenter.loader.RemoteConfigLoader;
import com.nepxion.discovery.plugin.framework.adapter.PluginAdapter;
import com.nepxion.discovery.plugin.framework.config.PluginConfigParser;
import com.nepxion.discovery.plugin.framework.context.PluginContextAware;
import com.nepxion.discovery.plugin.framework.event.PluginEventWapper;
public class ConfigInitializer {
private static final Logger LOG = LoggerFactory.getLogger(ConfigInitializer.class);
......@@ -36,6 +37,9 @@ public class ConfigInitializer {
private PluginConfigParser pluginConfigParser;
@Autowired
private PluginEventWapper pluginEventWapper;
@Autowired
private LocalConfigLoader localConfigLoader;
@Autowired(required = false)
......@@ -77,6 +81,8 @@ public class ConfigInitializer {
if (StringUtils.isEmpty(remoteConfig) && StringUtils.isEmpty(localConfig)) {
LOG.info("No config is retrieved");
}
pluginEventWapper.fireCustomization();
}
private String getRemoteConfig() {
......
......@@ -13,6 +13,7 @@ public class ConfigConstant {
public static final String RULE_ELEMENT_NAME = "rule";
public static final String REGISTER_ELEMENT_NAME = "register";
public static final String DISCOVERY_ELEMENT_NAME = "discovery";
public static final String CUSTOMIZATION_ELEMENT_NAME = "customization";
public static final String SERVICE_ELEMENT_NAME = "service";
public static final String BLACKLIST_ELEMENT_NAME = "blacklist";
public static final String WHITELIST_ELEMENT_NAME = "whitelist";
......@@ -26,5 +27,7 @@ public class ConfigConstant {
public static final String CONSUMER_VERSION_VALUE_ATTRIBUTE_NAME = "consumer-version-value";
public static final String PROVIDER_VERSION_VALUE_ATTRIBUTE_NAME = "provider-version-value";
public static final String PROVIDER_WEIGHT_VALUE_ATTRIBUTE_NAME = "provider-weight-value";
public static final String KEY_ATTRIBUTE_NAME = "key";
public static final String VALUE_ATTRIBUTE_NAME = "value";
public static final String SEPARATE = "=";
}
\ No newline at end of file
......@@ -25,6 +25,7 @@ import org.slf4j.LoggerFactory;
import com.nepxion.discovery.common.constant.DiscoveryConstant;
import com.nepxion.discovery.common.entity.CountFilterEntity;
import com.nepxion.discovery.common.entity.CustomizationEntity;
import com.nepxion.discovery.common.entity.DiscoveryEntity;
import com.nepxion.discovery.common.entity.FilterHolderEntity;
import com.nepxion.discovery.common.entity.FilterType;
......@@ -74,8 +75,14 @@ public class XmlConfigParser implements PluginConfigParser {
throw new DiscoveryException("Allow only one element[" + ConfigConstant.DISCOVERY_ELEMENT_NAME + "] to be configed");
}
int customizationElementCount = element.elements(ConfigConstant.CUSTOMIZATION_ELEMENT_NAME).size();
if (customizationElementCount > 1) {
throw new DiscoveryException("Allow only one element[" + ConfigConstant.CUSTOMIZATION_ELEMENT_NAME + "] to be configed");
}
RegisterEntity registerEntity = null;
DiscoveryEntity discoveryEntity = null;
CustomizationEntity customizationEntity = null;
for (Iterator elementIterator = element.elementIterator(); elementIterator.hasNext();) {
Object childElementObject = elementIterator.next();
if (childElementObject instanceof Element) {
......@@ -87,6 +94,9 @@ public class XmlConfigParser implements PluginConfigParser {
} else if (StringUtils.equals(childElement.getName(), ConfigConstant.DISCOVERY_ELEMENT_NAME)) {
discoveryEntity = new DiscoveryEntity();
parseDiscovery(childElement, discoveryEntity);
} else if (StringUtils.equals(childElement.getName(), ConfigConstant.CUSTOMIZATION_ELEMENT_NAME)) {
customizationEntity = new CustomizationEntity();
parseCustomization(childElement, customizationEntity);
}
}
}
......@@ -94,6 +104,7 @@ public class XmlConfigParser implements PluginConfigParser {
RuleEntity ruleEntity = new RuleEntity();
ruleEntity.setRegisterEntity(registerEntity);
ruleEntity.setDiscoveryEntity(discoveryEntity);
ruleEntity.setCustomizationEntity(customizationEntity);
ruleEntity.setContent(config);
LOG.info("Rule entity=\n{}", ruleEntity);
......@@ -140,6 +151,44 @@ public class XmlConfigParser implements PluginConfigParser {
}
@SuppressWarnings("rawtypes")
private void parseCustomization(Element element, CustomizationEntity customizationEntity) {
Map<String, Map<String, String>> customizationMap = customizationEntity.getCustomizationMap();
for (Iterator elementIterator = element.elementIterator(); elementIterator.hasNext();) {
Object childElementObject = elementIterator.next();
if (childElementObject instanceof Element) {
Element childElement = (Element) childElementObject;
if (StringUtils.equals(childElement.getName(), ConfigConstant.SERVICE_ELEMENT_NAME)) {
Attribute serviceNameAttribute = childElement.attribute(ConfigConstant.SERVICE_NAME_ATTRIBUTE_NAME);
if (serviceNameAttribute == null) {
throw new DiscoveryException("Attribute[" + ConfigConstant.SERVICE_NAME_ATTRIBUTE_NAME + "] in element[" + childElement.getName() + "] is missing");
}
String serviceName = serviceNameAttribute.getData().toString().trim();
Attribute keyAttribute = childElement.attribute(ConfigConstant.KEY_ATTRIBUTE_NAME);
if (keyAttribute == null) {
throw new DiscoveryException("Attribute[" + ConfigConstant.KEY_ATTRIBUTE_NAME + "] in element[" + childElement.getName() + "] is missing");
}
String key = keyAttribute.getData().toString().trim();
Attribute valueAttribute = childElement.attribute(ConfigConstant.VALUE_ATTRIBUTE_NAME);
if (valueAttribute == null) {
throw new DiscoveryException("Attribute[" + ConfigConstant.VALUE_ATTRIBUTE_NAME + "] in element[" + childElement.getName() + "] is missing");
}
String value = valueAttribute.getData().toString().trim();
Map<String, String> customizationParameter = customizationMap.get(serviceName);
if (customizationParameter == null) {
customizationParameter = new LinkedHashMap<String, String>();
customizationMap.put(serviceName, customizationParameter);
}
customizationParameter.put(key, value);
}
}
}
}
@SuppressWarnings("rawtypes")
private void parseHostFilter(Element element, String filterTypeValue, FilterHolderEntity filterHolderEntity) {
HostFilterEntity hostFilterEntity = filterHolderEntity.getHostFilterEntity();
if (hostFilterEntity != null) {
......
package com.nepxion.discovery.plugin.framework.event;
/**
* <p>Title: Nepxion Discovery</p>
* <p>Description: Nepxion Discovery</p>
* <p>Copyright: Copyright (c) 2017-2050</p>
* <p>Company: Nepxion</p>
* @author Haojun Ren
* @version 1.0
*/
import java.io.Serializable;
import com.nepxion.discovery.common.entity.CustomizationEntity;
public class CustomizationEvent implements Serializable {
private static final long serialVersionUID = 7843872188960155327L;
private CustomizationEntity customizationEntity;
public CustomizationEvent(CustomizationEntity customizationEntity) {
this.customizationEntity = customizationEntity;
}
public CustomizationEntity getCustomizationEntity() {
return customizationEntity;
}
}
\ No newline at end of file
......@@ -11,8 +11,14 @@ package com.nepxion.discovery.plugin.framework.event;
import org.springframework.beans.factory.annotation.Autowired;
import com.nepxion.discovery.common.entity.RuleEntity;
import com.nepxion.discovery.plugin.framework.adapter.PluginAdapter;
public class PluginEventWapper {
@Autowired
private PluginAdapter pluginAdapter;
@Autowired
private PluginPublisher pluginPublisher;
@Autowired
......@@ -53,4 +59,13 @@ public class PluginEventWapper {
public void fireRegisterFailure(RegisterFailureEvent registerFailureEvent) {
pluginPublisher.asyncPublish(registerFailureEvent);
}
public void fireCustomization(CustomizationEvent customizationEvent) {
pluginPublisher.asyncPublish(customizationEvent);
}
public void fireCustomization() {
RuleEntity ruleEntity = pluginAdapter.getRule();
fireCustomization(new CustomizationEvent(ruleEntity != null ? ruleEntity.getCustomizationEntity() : null));
}
}
\ No newline at end of file
......@@ -38,6 +38,9 @@ public class PluginSubscriber {
private PluginConfigParser pluninConfigParser;
@Autowired
private PluginEventWapper pluginEventWapper;
@Autowired
private LoadBalanceListenerExecutor loadBalanceListenerExecutor;
@Subscribe
......@@ -59,6 +62,8 @@ public class PluginSubscriber {
try {
RuleEntity ruleEntity = pluninConfigParser.parse(rule);
pluginAdapter.setDynamicRule(ruleEntity);
pluginEventWapper.fireCustomization();
} catch (Exception e) {
LOG.error("Parse rule xml failed", e);
......@@ -85,6 +90,8 @@ public class PluginSubscriber {
pluginAdapter.clearDynamicRule();
pluginEventWapper.fireCustomization();
refreshLoadBalancer();
}
......
......@@ -9,12 +9,35 @@ package com.nepxion.discovery.plugin.example.service.extension;
* @version 1.0
*/
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import com.google.common.eventbus.Subscribe;
import com.nepxion.discovery.common.entity.CustomizationEntity;
import com.nepxion.discovery.plugin.framework.adapter.PluginAdapter;
import com.nepxion.discovery.plugin.framework.event.CustomizationEvent;
import com.nepxion.discovery.plugin.framework.event.RegisterFailureEvent;
import com.nepxion.eventbus.annotation.EventBus;
@EventBus
public class MySubscriber {
@Autowired
private PluginAdapter pluginAdapter;
@Subscribe
public void onCustomization(CustomizationEvent customizationEvent) {
CustomizationEntity customizationEntity = customizationEvent.getCustomizationEntity();
String serviceId = pluginAdapter.getServiceId();
if (customizationEntity != null) {
Map<String, Map<String, String>> customizationMap = customizationEntity.getCustomizationMap();
Map<String, String> customizationParameter = customizationMap.get(serviceId);
System.out.println("========== 获取客户化对象, serviceId=" + serviceId + ", customizationParameter=" + customizationParameter);
} else {
System.out.println("========== 获取客户化对象, serviceId=" + serviceId + ", customizationEntity=" + customizationEntity);
}
}
@Subscribe
public void onRegisterFailure(RegisterFailureEvent registerFailureEvent) {
System.out.println("========== 注册失败, eventType=" + registerFailureEvent.getEventType() + ", eventDescription=" + registerFailureEvent.getEventDescription() + ", serviceId=" + registerFailureEvent.getServiceId() + ", host=" + registerFailureEvent.getHost() + ", port=" + registerFailureEvent.getPort());
......
......@@ -95,5 +95,12 @@
]
}
}
},
"customizationEntity": {
"customizationMap": {
"discovery-springcloud-example-b": {
"database": "prod"
}
}
}
}
\ No newline at end of file
......@@ -75,4 +75,11 @@
<service consumer-service-name="discovery-springcloud-example-b" provider-service-name="discovery-springcloud-example-c" provider-weight-value="1.0=90;1.1=10"/>
</weight>
</discovery>
<!-- 客户定制化控制,由远程推送客户化参数的改变,实现一些特色化的灰度发布,例如,基于数据库的灰度发布 -->
<customization>
<!-- 服务b有两个库的配置,分别是临时数据库(database的value为temp)和生产数据库(database的value为prod) -->
<!-- 上线后,一开始数据库指向临时数据库,对应value为temp,然后灰度发布的时候,改对应value为prod,即实现数据库的灰度发布 -->
<service service-name="discovery-springcloud-example-b" key="database" value="prod"/>
</customization>
</rule>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment