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 { ...@@ -21,6 +21,7 @@ public class RuleEntity implements Serializable {
private RegisterEntity registerEntity; private RegisterEntity registerEntity;
private DiscoveryEntity discoveryEntity; private DiscoveryEntity discoveryEntity;
private CustomizationEntity customizationEntity;
private String content; private String content;
public RegisterEntity getRegisterEntity() { public RegisterEntity getRegisterEntity() {
...@@ -39,6 +40,14 @@ public class RuleEntity implements Serializable { ...@@ -39,6 +40,14 @@ public class RuleEntity implements Serializable {
this.discoveryEntity = discoveryEntity; this.discoveryEntity = discoveryEntity;
} }
public CustomizationEntity getCustomizationEntity() {
return customizationEntity;
}
public void setCustomizationEntity(CustomizationEntity customizationEntity) {
this.customizationEntity = customizationEntity;
}
public String getContent() { public String getContent() {
return content; return content;
} }
......
...@@ -22,6 +22,7 @@ import com.nepxion.discovery.plugin.configcenter.loader.RemoteConfigLoader; ...@@ -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.adapter.PluginAdapter;
import com.nepxion.discovery.plugin.framework.config.PluginConfigParser; import com.nepxion.discovery.plugin.framework.config.PluginConfigParser;
import com.nepxion.discovery.plugin.framework.context.PluginContextAware; import com.nepxion.discovery.plugin.framework.context.PluginContextAware;
import com.nepxion.discovery.plugin.framework.event.PluginEventWapper;
public class ConfigInitializer { public class ConfigInitializer {
private static final Logger LOG = LoggerFactory.getLogger(ConfigInitializer.class); private static final Logger LOG = LoggerFactory.getLogger(ConfigInitializer.class);
...@@ -36,6 +37,9 @@ public class ConfigInitializer { ...@@ -36,6 +37,9 @@ public class ConfigInitializer {
private PluginConfigParser pluginConfigParser; private PluginConfigParser pluginConfigParser;
@Autowired @Autowired
private PluginEventWapper pluginEventWapper;
@Autowired
private LocalConfigLoader localConfigLoader; private LocalConfigLoader localConfigLoader;
@Autowired(required = false) @Autowired(required = false)
...@@ -77,6 +81,8 @@ public class ConfigInitializer { ...@@ -77,6 +81,8 @@ public class ConfigInitializer {
if (StringUtils.isEmpty(remoteConfig) && StringUtils.isEmpty(localConfig)) { if (StringUtils.isEmpty(remoteConfig) && StringUtils.isEmpty(localConfig)) {
LOG.info("No config is retrieved"); LOG.info("No config is retrieved");
} }
pluginEventWapper.fireCustomization();
} }
private String getRemoteConfig() { private String getRemoteConfig() {
......
...@@ -13,6 +13,7 @@ public class ConfigConstant { ...@@ -13,6 +13,7 @@ public class ConfigConstant {
public static final String RULE_ELEMENT_NAME = "rule"; public static final String RULE_ELEMENT_NAME = "rule";
public static final String REGISTER_ELEMENT_NAME = "register"; public static final String REGISTER_ELEMENT_NAME = "register";
public static final String DISCOVERY_ELEMENT_NAME = "discovery"; 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 SERVICE_ELEMENT_NAME = "service";
public static final String BLACKLIST_ELEMENT_NAME = "blacklist"; public static final String BLACKLIST_ELEMENT_NAME = "blacklist";
public static final String WHITELIST_ELEMENT_NAME = "whitelist"; public static final String WHITELIST_ELEMENT_NAME = "whitelist";
...@@ -26,5 +27,7 @@ public class ConfigConstant { ...@@ -26,5 +27,7 @@ public class ConfigConstant {
public static final String CONSUMER_VERSION_VALUE_ATTRIBUTE_NAME = "consumer-version-value"; 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_VERSION_VALUE_ATTRIBUTE_NAME = "provider-version-value";
public static final String PROVIDER_WEIGHT_VALUE_ATTRIBUTE_NAME = "provider-weight-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 = "="; public static final String SEPARATE = "=";
} }
\ No newline at end of file
...@@ -25,6 +25,7 @@ import org.slf4j.LoggerFactory; ...@@ -25,6 +25,7 @@ import org.slf4j.LoggerFactory;
import com.nepxion.discovery.common.constant.DiscoveryConstant; import com.nepxion.discovery.common.constant.DiscoveryConstant;
import com.nepxion.discovery.common.entity.CountFilterEntity; 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.DiscoveryEntity;
import com.nepxion.discovery.common.entity.FilterHolderEntity; import com.nepxion.discovery.common.entity.FilterHolderEntity;
import com.nepxion.discovery.common.entity.FilterType; import com.nepxion.discovery.common.entity.FilterType;
...@@ -74,8 +75,14 @@ public class XmlConfigParser implements PluginConfigParser { ...@@ -74,8 +75,14 @@ public class XmlConfigParser implements PluginConfigParser {
throw new DiscoveryException("Allow only one element[" + ConfigConstant.DISCOVERY_ELEMENT_NAME + "] to be configed"); 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; RegisterEntity registerEntity = null;
DiscoveryEntity discoveryEntity = null; DiscoveryEntity discoveryEntity = null;
CustomizationEntity customizationEntity = null;
for (Iterator elementIterator = element.elementIterator(); elementIterator.hasNext();) { for (Iterator elementIterator = element.elementIterator(); elementIterator.hasNext();) {
Object childElementObject = elementIterator.next(); Object childElementObject = elementIterator.next();
if (childElementObject instanceof Element) { if (childElementObject instanceof Element) {
...@@ -87,6 +94,9 @@ public class XmlConfigParser implements PluginConfigParser { ...@@ -87,6 +94,9 @@ public class XmlConfigParser implements PluginConfigParser {
} else if (StringUtils.equals(childElement.getName(), ConfigConstant.DISCOVERY_ELEMENT_NAME)) { } else if (StringUtils.equals(childElement.getName(), ConfigConstant.DISCOVERY_ELEMENT_NAME)) {
discoveryEntity = new DiscoveryEntity(); discoveryEntity = new DiscoveryEntity();
parseDiscovery(childElement, 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 { ...@@ -94,6 +104,7 @@ public class XmlConfigParser implements PluginConfigParser {
RuleEntity ruleEntity = new RuleEntity(); RuleEntity ruleEntity = new RuleEntity();
ruleEntity.setRegisterEntity(registerEntity); ruleEntity.setRegisterEntity(registerEntity);
ruleEntity.setDiscoveryEntity(discoveryEntity); ruleEntity.setDiscoveryEntity(discoveryEntity);
ruleEntity.setCustomizationEntity(customizationEntity);
ruleEntity.setContent(config); ruleEntity.setContent(config);
LOG.info("Rule entity=\n{}", ruleEntity); LOG.info("Rule entity=\n{}", ruleEntity);
...@@ -140,6 +151,44 @@ public class XmlConfigParser implements PluginConfigParser { ...@@ -140,6 +151,44 @@ public class XmlConfigParser implements PluginConfigParser {
} }
@SuppressWarnings("rawtypes") @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) { private void parseHostFilter(Element element, String filterTypeValue, FilterHolderEntity filterHolderEntity) {
HostFilterEntity hostFilterEntity = filterHolderEntity.getHostFilterEntity(); HostFilterEntity hostFilterEntity = filterHolderEntity.getHostFilterEntity();
if (hostFilterEntity != null) { 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; ...@@ -11,8 +11,14 @@ package com.nepxion.discovery.plugin.framework.event;
import org.springframework.beans.factory.annotation.Autowired; 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 { public class PluginEventWapper {
@Autowired @Autowired
private PluginAdapter pluginAdapter;
@Autowired
private PluginPublisher pluginPublisher; private PluginPublisher pluginPublisher;
@Autowired @Autowired
...@@ -53,4 +59,13 @@ public class PluginEventWapper { ...@@ -53,4 +59,13 @@ public class PluginEventWapper {
public void fireRegisterFailure(RegisterFailureEvent registerFailureEvent) { public void fireRegisterFailure(RegisterFailureEvent registerFailureEvent) {
pluginPublisher.asyncPublish(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 { ...@@ -38,6 +38,9 @@ public class PluginSubscriber {
private PluginConfigParser pluninConfigParser; private PluginConfigParser pluninConfigParser;
@Autowired @Autowired
private PluginEventWapper pluginEventWapper;
@Autowired
private LoadBalanceListenerExecutor loadBalanceListenerExecutor; private LoadBalanceListenerExecutor loadBalanceListenerExecutor;
@Subscribe @Subscribe
...@@ -59,6 +62,8 @@ public class PluginSubscriber { ...@@ -59,6 +62,8 @@ public class PluginSubscriber {
try { try {
RuleEntity ruleEntity = pluninConfigParser.parse(rule); RuleEntity ruleEntity = pluninConfigParser.parse(rule);
pluginAdapter.setDynamicRule(ruleEntity); pluginAdapter.setDynamicRule(ruleEntity);
pluginEventWapper.fireCustomization();
} catch (Exception e) { } catch (Exception e) {
LOG.error("Parse rule xml failed", e); LOG.error("Parse rule xml failed", e);
...@@ -85,6 +90,8 @@ public class PluginSubscriber { ...@@ -85,6 +90,8 @@ public class PluginSubscriber {
pluginAdapter.clearDynamicRule(); pluginAdapter.clearDynamicRule();
pluginEventWapper.fireCustomization();
refreshLoadBalancer(); refreshLoadBalancer();
} }
......
...@@ -9,12 +9,35 @@ package com.nepxion.discovery.plugin.example.service.extension; ...@@ -9,12 +9,35 @@ package com.nepxion.discovery.plugin.example.service.extension;
* @version 1.0 * @version 1.0
*/ */
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import com.google.common.eventbus.Subscribe; 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.discovery.plugin.framework.event.RegisterFailureEvent;
import com.nepxion.eventbus.annotation.EventBus; import com.nepxion.eventbus.annotation.EventBus;
@EventBus @EventBus
public class MySubscriber { 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 @Subscribe
public void onRegisterFailure(RegisterFailureEvent registerFailureEvent) { public void onRegisterFailure(RegisterFailureEvent registerFailureEvent) {
System.out.println("========== 注册失败, eventType=" + registerFailureEvent.getEventType() + ", eventDescription=" + registerFailureEvent.getEventDescription() + ", serviceId=" + registerFailureEvent.getServiceId() + ", host=" + registerFailureEvent.getHost() + ", port=" + registerFailureEvent.getPort()); System.out.println("========== 注册失败, eventType=" + registerFailureEvent.getEventType() + ", eventDescription=" + registerFailureEvent.getEventDescription() + ", serviceId=" + registerFailureEvent.getServiceId() + ", host=" + registerFailureEvent.getHost() + ", port=" + registerFailureEvent.getPort());
......
...@@ -95,5 +95,12 @@ ...@@ -95,5 +95,12 @@
] ]
} }
} }
},
"customizationEntity": {
"customizationMap": {
"discovery-springcloud-example-b": {
"database": "prod"
}
}
} }
} }
\ No newline at end of file
...@@ -75,4 +75,11 @@ ...@@ -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"/> <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> </weight>
</discovery> </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> </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