Commit 5afc0d9e by Nepxion

增加服务注册的数目限制过滤

parent 1bbda364
......@@ -28,6 +28,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import com.nepxion.discovery.plugin.configcenter.constant.ConfigConstant;
import com.nepxion.discovery.plugin.configcenter.xml.Dom4JParser;
import com.nepxion.discovery.plugin.framework.constant.PluginConstant;
import com.nepxion.discovery.plugin.framework.entity.CountEntity;
import com.nepxion.discovery.plugin.framework.entity.DiscoveryEntity;
import com.nepxion.discovery.plugin.framework.entity.DiscoveryServiceEntity;
import com.nepxion.discovery.plugin.framework.entity.FilterEntity;
......@@ -71,12 +72,12 @@ public class ConfigParser extends Dom4JParser {
int registerElementCount = element.elements(ConfigConstant.REGISTER_ELEMENT_NAME).size();
if (registerElementCount > 1) {
throw new PluginException("The count of element[" + ConfigConstant.REGISTER_ELEMENT_NAME + "] can't be more than 1");
throw new PluginException("Allow only one element[" + ConfigConstant.REGISTER_ELEMENT_NAME + "] to be configed");
}
int discoveryElementCount = element.elements(ConfigConstant.DISCOVERY_ELEMENT_NAME).size();
if (discoveryElementCount > 1) {
throw new PluginException("The count of element[" + ConfigConstant.DISCOVERY_ELEMENT_NAME + "] can't be more than 1");
throw new PluginException("Allow only one element[" + ConfigConstant.DISCOVERY_ELEMENT_NAME + "] to be configed");
}
RegisterEntity registerEntity = null;
......@@ -107,7 +108,7 @@ public class ConfigParser extends Dom4JParser {
reentrantReadWriteLock.writeLock().unlock();
}
LOG.info("Rule xml=\n{}", text);
LOG.info("Rule entity=\n{}", ruleEntity);
}
@SuppressWarnings("rawtypes")
......@@ -121,6 +122,8 @@ public class ConfigParser extends Dom4JParser {
parseFilter(childElement, ConfigConstant.BLACKLIST_ELEMENT_NAME, registerEntity);
} else if (StringUtils.equals(childElement.getName(), ConfigConstant.WHITELIST_ELEMENT_NAME)) {
parseFilter(childElement, ConfigConstant.WHITELIST_ELEMENT_NAME, registerEntity);
} else if (StringUtils.equals(childElement.getName(), ConfigConstant.COUNT_ELEMENT_NAME)) {
parseCount(childElement, registerEntity);
}
}
}
......@@ -148,7 +151,7 @@ public class ConfigParser extends Dom4JParser {
private void parseFilter(Element element, String filterTypeValue, FilterHolderEntity filterHolderEntity) {
FilterEntity filterEntity = filterHolderEntity.getFilterEntity();
if (filterEntity != null) {
throw new PluginException("Filter[" + filterEntity.getFilterType() + "] has been configed, only one filter element exists");
throw new PluginException("Allow only one filter element to be configed, [" + ConfigConstant.BLACKLIST_ELEMENT_NAME + "] or [" + ConfigConstant.WHITELIST_ELEMENT_NAME + "]");
}
filterEntity = new FilterEntity();
......@@ -187,10 +190,65 @@ public class ConfigParser extends Dom4JParser {
}
@SuppressWarnings("rawtypes")
private void parseCount(Element element, RegisterEntity registerEntity) {
CountEntity countEntity = registerEntity.getCountEntity();
if (countEntity != null) {
throw new PluginException("Allow only one element[" + ConfigConstant.COUNT_ELEMENT_NAME + "] to be configed");
}
countEntity = new CountEntity();
Attribute globalFilterAttribute = element.attribute(ConfigConstant.FILTER_VALUE_ATTRIBUTE_NAME);
if (globalFilterAttribute != null) {
String globalFilterValue = globalFilterAttribute.getData().toString().trim();
if (StringUtils.isNotEmpty(globalFilterValue)) {
Integer globalValue = null;
try {
globalValue = Integer.valueOf(globalFilterValue);
} catch (NumberFormatException e) {
throw new PluginException("Attribute[" + ConfigConstant.FILTER_VALUE_ATTRIBUTE_NAME + "] value in element[" + element.getName() + "] is invalid, must be int type", e);
}
countEntity.setFilterValue(globalValue);
}
}
Map<String, Integer> filterMap = countEntity.getFilterMap();
for (Iterator elementIterator = element.elementIterator(); elementIterator.hasNext();) {
Object childElementObject = elementIterator.next();
if (childElementObject instanceof Element) {
Element childElement = (Element) childElementObject;
Attribute serviceNameAttribute = childElement.attribute(ConfigConstant.SERVICE_NAME_ATTRIBUTE_NAME);
if (serviceNameAttribute == null) {
throw new PluginException("Attribute[" + ConfigConstant.SERVICE_NAME_ATTRIBUTE_NAME + "] in element[" + childElement.getName() + "] is missing");
}
String serviceName = serviceNameAttribute.getData().toString().trim();
Integer value = null;
Attribute filterValueAttribute = childElement.attribute(ConfigConstant.FILTER_VALUE_ATTRIBUTE_NAME);
if (filterValueAttribute != null) {
String filterValue = filterValueAttribute.getData().toString().trim();
if (StringUtils.isNotEmpty(filterValue)) {
try {
value = Integer.valueOf(filterValue);
} catch (NumberFormatException e) {
throw new PluginException("Attribute[" + ConfigConstant.FILTER_VALUE_ATTRIBUTE_NAME + "] value in element[" + childElement.getName() + "] is invalid, must be int type", e);
}
}
}
filterMap.put(serviceName, value);
}
}
registerEntity.setCountEntity(countEntity);
}
@SuppressWarnings("rawtypes")
private void parseVersion(Element element, DiscoveryEntity discoveryEntity) {
VersionEntity versionEntity = discoveryEntity.getVersionEntity();
if (versionEntity != null) {
throw new PluginException("Version has been configed, only one version element exists");
throw new PluginException("Allow only one element[" + ConfigConstant.VERSION_ELEMENT_NAME + "] to be configed");
}
versionEntity = new VersionEntity();
......
......@@ -16,6 +16,7 @@ public class ConfigConstant {
public static final String SERVICE_ELEMENT_NAME = "service";
public static final String BLACKLIST_ELEMENT_NAME = "blacklist";
public static final String WHITELIST_ELEMENT_NAME = "whitelist";
public static final String COUNT_ELEMENT_NAME = "count";
public static final String VERSION_ELEMENT_NAME = "version";
public static final String FILTER_VALUE_ATTRIBUTE_NAME = "filter-value";
public static final String SERVICE_NAME_ATTRIBUTE_NAME = "service-name";
......
......@@ -20,6 +20,7 @@ import com.nepxion.discovery.plugin.framework.entity.RuleEntity;
import com.nepxion.discovery.plugin.framework.event.PluginPublisher;
import com.nepxion.discovery.plugin.framework.listener.DiscoveryListenerExecutor;
import com.nepxion.discovery.plugin.framework.listener.RegisterListenerExecutor;
import com.nepxion.discovery.plugin.framework.listener.impl.CountFilterRegisterListener;
import com.nepxion.discovery.plugin.framework.listener.impl.IpAddressFilterDiscoveryListener;
import com.nepxion.discovery.plugin.framework.listener.impl.IpAddressFilterRegisterListener;
import com.nepxion.discovery.plugin.framework.listener.impl.VersionFilterDiscoveryListener;
......@@ -81,6 +82,11 @@ public class PluginAutoConfiguration {
}
@Bean
public CountFilterRegisterListener countFilterRegisterListener() {
return new CountFilterRegisterListener();
}
@Bean
public IpAddressFilterDiscoveryListener ipAddressFilterDiscoveryListener() {
return new IpAddressFilterDiscoveryListener();
}
......
......@@ -22,6 +22,7 @@ public class PluginConstant {
public static final String HOST = "host";
public static final String PORT = "port";
public static final String INSTANCES = "instances";
public static final String COUNT_LIMIT = "countLimit";
public static final String ENCODING_UTF_8 = "UTF-8";
public static final String SEPARATE = ";";
......
package com.nepxion.discovery.plugin.framework.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 CountEntity implements Serializable {
private static final long serialVersionUID = 3830016495318834467L;
private Integer filterValue;
private Map<String, Integer> filterMap = new LinkedHashMap<String, Integer>();
public CountEntity() {
}
public Integer getFilterValue() {
return filterValue;
}
public void setFilterValue(Integer filterValue) {
this.filterValue = filterValue;
}
public Map<String, Integer> getFilterMap() {
return filterMap;
}
public void setFilterMap(Map<String, Integer> filterMap) {
this.filterMap = filterMap;
}
@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
......@@ -12,7 +12,17 @@ package com.nepxion.discovery.plugin.framework.entity;
public class RegisterEntity extends FilterHolderEntity {
private static final long serialVersionUID = -2097322826969006191L;
private CountEntity countEntity;
public RegisterEntity() {
}
public CountEntity getCountEntity() {
return countEntity;
}
public void setCountEntity(CountEntity countEntity) {
this.countEntity = countEntity;
}
}
\ No newline at end of file
......@@ -15,12 +15,15 @@ public class RegisterFailureEvent implements Serializable {
private static final long serialVersionUID = -1343084923958294246L;
private String eventType;
private String eventDescription;
private String serviceId;
private String ipAddress;
private int port;
public RegisterFailureEvent(String eventType, String serviceId, String ipAddress, int port) {
public RegisterFailureEvent(String eventType, String eventDescription, String serviceId, String ipAddress, int port) {
this.eventType = eventType;
this.eventDescription = eventDescription;
this.serviceId = serviceId;
this.ipAddress = ipAddress;
this.port = port;
......@@ -30,6 +33,10 @@ public class RegisterFailureEvent implements Serializable {
return eventType;
}
public String getEventDescription() {
return eventDescription;
}
public String getServiceId() {
return serviceId;
}
......
......@@ -15,11 +15,15 @@ import java.util.concurrent.locks.ReentrantReadWriteLock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.serviceregistry.Registration;
import com.nepxion.discovery.plugin.framework.listener.impl.CountFilterRegisterListener;
import com.nepxion.discovery.plugin.framework.listener.impl.IpAddressFilterRegisterListener;
// 因为内置监听触发的时候,会抛异常处理,所以逆序执行
public class RegisterListenerExecutor {
@Autowired
private CountFilterRegisterListener countFilterRegisterListener;
@Autowired
private IpAddressFilterRegisterListener ipAddressFilterRegisterListener;
@Autowired
......@@ -33,11 +37,12 @@ public class RegisterListenerExecutor {
reentrantReadWriteLock.readLock().lock();
for (RegisterListener registerListener : registerListenerList) {
if (registerListener != ipAddressFilterRegisterListener) {
if (registerListener != countFilterRegisterListener && registerListener != ipAddressFilterRegisterListener) {
registerListener.onRegister(registration);
}
}
countFilterRegisterListener.onRegister(registration);
ipAddressFilterRegisterListener.onRegister(registration);
} finally {
reentrantReadWriteLock.readLock().unlock();
......@@ -46,31 +51,34 @@ public class RegisterListenerExecutor {
public void onDeregister(Registration registration) {
for (RegisterListener registerListener : registerListenerList) {
if (registerListener != ipAddressFilterRegisterListener) {
if (registerListener != countFilterRegisterListener && registerListener != ipAddressFilterRegisterListener) {
registerListener.onDeregister(registration);
}
}
countFilterRegisterListener.onDeregister(registration);
ipAddressFilterRegisterListener.onDeregister(registration);
}
public void onSetStatus(Registration registration, String status) {
for (RegisterListener registerListener : registerListenerList) {
if (registerListener != ipAddressFilterRegisterListener) {
if (registerListener != countFilterRegisterListener && registerListener != ipAddressFilterRegisterListener) {
registerListener.onSetStatus(registration, status);
}
}
countFilterRegisterListener.onSetStatus(registration, status);
ipAddressFilterRegisterListener.onSetStatus(registration, status);
}
public void onClose() {
for (RegisterListener registerListener : registerListenerList) {
if (registerListener != ipAddressFilterRegisterListener) {
if (registerListener != countFilterRegisterListener && registerListener != ipAddressFilterRegisterListener) {
registerListener.onClose();
}
}
countFilterRegisterListener.onClose();
ipAddressFilterRegisterListener.onClose();
}
}
\ No newline at end of file
package com.nepxion.discovery.plugin.framework.listener.impl;
/**
* <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.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.serviceregistry.Registration;
import com.nepxion.discovery.plugin.framework.adapter.PluginAdapter;
import com.nepxion.discovery.plugin.framework.constant.PluginConstant;
import com.nepxion.discovery.plugin.framework.decorator.DiscoveryClientDecorator;
import com.nepxion.discovery.plugin.framework.entity.CountEntity;
import com.nepxion.discovery.plugin.framework.entity.RegisterEntity;
import com.nepxion.discovery.plugin.framework.entity.RuleEntity;
import com.nepxion.discovery.plugin.framework.event.PluginPublisher;
import com.nepxion.discovery.plugin.framework.event.RegisterFailureEvent;
import com.nepxion.discovery.plugin.framework.exception.PluginException;
import com.nepxion.discovery.plugin.framework.listener.AbstractRegisterListener;
public class CountFilterRegisterListener extends AbstractRegisterListener {
@Autowired
private RuleEntity ruleEntity;
@Autowired
private PluginAdapter pluginAdapter;
@Autowired
private PluginPublisher pluginPublisher;
@Autowired
private DiscoveryClientDecorator discoveryClient;
@Override
public void onRegister(Registration registration) {
String serviceId = registration.getServiceId();
String ipAddress = pluginAdapter.getIpAddress(registration);
int port = pluginAdapter.getPort(registration);
applyCountFilter(serviceId, ipAddress, port);
}
private void applyCountFilter(String serviceId, String ipAddress, int port) {
RegisterEntity registerEntity = ruleEntity.getRegisterEntity();
if (registerEntity == null) {
return;
}
CountEntity countEntity = registerEntity.getCountEntity();
if (countEntity == null) {
return;
}
Integer globalFilterValue = countEntity.getFilterValue();
Map<String, Integer> filterMap = countEntity.getFilterMap();
Integer filterValue = filterMap.get(serviceId);
// 如果局部值存在,就取局部值,否则取全局值
Integer maxCount = null;
if (filterValue != null) {
maxCount = filterValue;
} else {
maxCount = globalFilterValue;
}
if (maxCount == null) {
return;
}
int count = discoveryClient.getRealInstances(serviceId).size();
if (count >= maxCount) {
onRegisterFailure(maxCount, serviceId, ipAddress, port);
}
}
private void onRegisterFailure(int maxCount, String serviceId, String ipAddress, int port) {
String description = ipAddress + " isn't allowed to register to Register server, reach max limited count=" + maxCount;
Boolean registerFailureEventEnabled = environment.getProperty(PluginConstant.SPRING_APPLICATION_REGISTER_FAILURE_EVENT_ENABLED, Boolean.class, Boolean.FALSE);
if (registerFailureEventEnabled) {
pluginPublisher.asyncPublish(new RegisterFailureEvent(PluginConstant.COUNT_LIMIT, description, serviceId, ipAddress, port));
}
throw new PluginException(description);
}
@Override
public void onDeregister(Registration registration) {
}
@Override
public void onSetStatus(Registration registration, String status) {
}
@Override
public void onClose() {
}
}
\ No newline at end of file
......@@ -106,12 +106,14 @@ public class IpAddressFilterRegisterListener extends AbstractRegisterListener {
}
private void onRegisterFailure(FilterType filterType, List<String> allFilterValueList, String serviceId, String ipAddress, int port) {
String description = ipAddress + " isn't allowed to register to Register server, not match IP address " + filterType + "=" + allFilterValueList;
Boolean registerFailureEventEnabled = environment.getProperty(PluginConstant.SPRING_APPLICATION_REGISTER_FAILURE_EVENT_ENABLED, Boolean.class, Boolean.FALSE);
if (registerFailureEventEnabled) {
pluginPublisher.asyncPublish(new RegisterFailureEvent(filterType.toString(), serviceId, ipAddress, port));
pluginPublisher.asyncPublish(new RegisterFailureEvent(filterType.toString(), description, serviceId, ipAddress, port));
}
throw new PluginException(ipAddress + " isn't allowed to register to Register server, not match IP address " + filterType + "=" + allFilterValueList);
throw new PluginException(description);
}
@Override
......
......@@ -17,6 +17,6 @@ import com.nepxion.eventbus.annotation.EventBus;
public class MySubscriber {
@Subscribe
public void subscribeRegisterFailure(RegisterFailureEvent registerFailureEvent) {
System.out.println("========== 注册失败:eventType=" + registerFailureEvent.getEventType() + ", serviceId=" + registerFailureEvent.getServiceId() + ", ipAddress=" + registerFailureEvent.getIpAddress() + ", port=" + registerFailureEvent.getPort());
System.out.println("========== 注册失败:eventType=" + registerFailureEvent.getEventType() + ", eventDescription=" + registerFailureEvent.getEventDescription() + ", serviceId=" + registerFailureEvent.getServiceId() + ", ipAddress=" + registerFailureEvent.getIpAddress() + ", port=" + registerFailureEvent.getPort());
}
}
\ 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