热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

SpringCloudRibbon(六)之服务实例过滤器ServerListFilter

一、服务实例过滤器ServerListFilter服务实例过滤器(ServerListFilter)为负载均衡器(Loadbalance

一、服务实例过滤器ServerListFilter

服务实例过滤器(ServerListFilter)为负载均衡器(Loadbalancer)提供从服务实例列表(ServerList)获取的服务实例过滤出符合要求的服务实例。

负载均衡器(Loadbalancer)通过服务实例列表(ServerList)从注册中心(register)或者配置文件(yaml或properties)上读取全部服务实例(server),然后以服务实例过滤器(ServerListFilter)的过滤方式进行筛选留下满足条件的服务实例,进而借助负载均衡策略(IRule)选择出一个合适的服务实例。

 


二、ServerListFilter实现类

ZoneAffinityServerListFilter     区区域相关性筛选服务实例列表过滤器

ZonePreferenceServerListFilter  首选本地区域服务实例列表过滤器

ServerListSubsetFilter   服务实例数限制为所有服务实例的子集 筛选过滤器

 


三、具体代码实现

(1)ZoneAffinityServerListFilter 

public class ZoneAffinityServerListFilter extendsAbstractServerListFilter implements IClientConfigAware {private volatile boolean zoneAffinity = DefaultClientConfigImpl.DEFAULT_ENABLE_ZONE_AFFINITY;private volatile boolean zoneExclusive = DefaultClientConfigImpl.DEFAULT_ENABLE_ZONE_EXCLUSIVITY;private DynamicDoubleProperty activeReqeustsPerServerThreshold;private DynamicDoubleProperty blackOutServerPercentageThreshold;private DynamicIntProperty availableServersThreshold;private Counter overrideCounter;private ZoneAffinityPredicate zoneAffinityPredicate = new ZoneAffinityPredicate();private static Logger logger = LoggerFactory.getLogger(ZoneAffinityServerListFilter.class);String zone;public ZoneAffinityServerListFilter() { }public ZoneAffinityServerListFilter(IClientConfig niwsClientConfig) {initWithNiwsConfig(niwsClientConfig);}@Overridepublic void initWithNiwsConfig(IClientConfig niwsClientConfig) {String sZoneAffinity = "" + niwsClientConfig.getProperty(CommonClientConfigKey.EnableZoneAffinity, false);if (sZoneAffinity != null){zoneAffinity = Boolean.parseBoolean(sZoneAffinity);logger.debug("ZoneAffinity is set to {}", zoneAffinity);}String sZoneExclusive = "" + niwsClientConfig.getProperty(CommonClientConfigKey.EnableZoneExclusivity, false);if (sZoneExclusive != null){zoneExclusive = Boolean.parseBoolean(sZoneExclusive);}if (ConfigurationManager.getDeploymentContext() != null) {zone = ConfigurationManager.getDeploymentContext().getValue(ContextKey.zone);}activeReqeustsPerServerThreshold = DynamicPropertyFactory.getInstance().getDoubleProperty(niwsClientConfig.getClientName() + "." + niwsClientConfig.getNameSpace() + ".zoneAffinity.maxLoadPerServer", 0.6d);logger.debug("activeReqeustsPerServerThreshold: {}", activeReqeustsPerServerThreshold.get());blackOutServerPercentageThreshold = DynamicPropertyFactory.getInstance().getDoubleProperty(niwsClientConfig.getClientName() + "." + niwsClientConfig.getNameSpace() + ".zoneAffinity.maxBlackOutServesrPercentage", 0.8d);logger.debug("blackOutServerPercentageThreshold: {}", blackOutServerPercentageThreshold.get());availableServersThreshold = DynamicPropertyFactory.getInstance().getIntProperty(niwsClientConfig.getClientName() + "." + niwsClientConfig.getNameSpace() + ".zoneAffinity.minAvailableServers", 2);logger.debug("availableServersThreshold: {}", availableServersThreshold.get());overrideCounter = Monitors.newCounter("ZoneAffinity_OverrideCounter");Monitors.registerObject("NIWSServerListFilter_" + niwsClientConfig.getClientName());}private boolean shouldEnableZoneAffinity(List filtered) { if (!zoneAffinity && !zoneExclusive) {return false;}if (zoneExclusive) {return true;}LoadBalancerStats stats = getLoadBalancerStats();if (stats == null) {return zoneAffinity;} else {logger.debug("Determining if zone affinity should be enabled with given server list: {}", filtered);ZoneSnapshot snapshot = stats.getZoneSnapshot(filtered);double loadPerServer = snapshot.getLoadPerServer();int instanceCount = snapshot.getInstanceCount(); int circuitBreakerTrippedCount = snapshot.getCircuitTrippedCount();if (((double) circuitBreakerTrippedCount) / instanceCount >= blackOutServerPercentageThreshold.get() || loadPerServer >= activeReqeustsPerServerThreshold.get()|| (instanceCount - circuitBreakerTrippedCount) getFilteredListOfServers(List servers) {if (zone != null && (zoneAffinity || zoneExclusive) && servers !=null && servers.size() > 0){List filteredServers = Lists.newArrayList(Iterables.filter(servers, this.zoneAffinityPredicate.getServerOnlyPredicate()));if (shouldEnableZoneAffinity(filteredServers)) {return filteredServers;} else if (zoneAffinity) {overrideCounter.increment();}}return servers;}@Overridepublic String toString(){StringBuilder sb = new StringBuilder("ZoneAffinityServerListFilter:");sb.append(", zone: ").append(zone).append(", zoneAffinity:").append(zoneAffinity);sb.append(", zoneExclusivity:").append(zoneExclusive);return sb.toString(); }
}

(2)ZonePreferenceServerListFilter

public class ZonePreferenceServerListFilter extends ZoneAffinityServerListFilter {private String zone;&#64;Overridepublic void initWithNiwsConfig(IClientConfig niwsClientConfig) {super.initWithNiwsConfig(niwsClientConfig);if (ConfigurationManager.getDeploymentContext() !&#61; null) {this.zone &#61; ConfigurationManager.getDeploymentContext().getValue(ContextKey.zone);}}&#64;Overridepublic List getFilteredListOfServers(List servers) {List output &#61; super.getFilteredListOfServers(servers);if (this.zone !&#61; null && output.size() &#61;&#61; servers.size()) {List local &#61; new ArrayList<>();for (Server server : output) {if (this.zone.equalsIgnoreCase(server.getZone())) {local.add(server);}}if (!local.isEmpty()) {return local;}}return output;}public String getZone() {return zone;}public void setZone(String zone) {this.zone &#61; zone;}&#64;Overridepublic boolean equals(Object o) {if (this &#61;&#61; o) {return true;}if (o &#61;&#61; null || getClass() !&#61; o.getClass()) {return false;}ZonePreferenceServerListFilter that &#61; (ZonePreferenceServerListFilter) o;return Objects.equals(zone, that.zone);}&#64;Overridepublic int hashCode() {return Objects.hash(zone);}&#64;Overridepublic String toString() {return new StringBuilder("ZonePreferenceServerListFilter{").append("zone&#61;&#39;").append(zone).append("&#39;").append("}").toString();}}

&#xff08;3&#xff09;ServerListSubsetFilter 

public class ServerListSubsetFilter extends ZoneAffinityServerListFilter implements IClientConfigAware, Comparator{private Random random &#61; new Random();private volatile Set currentSubset &#61; Sets.newHashSet(); private DynamicIntProperty sizeProp &#61; new DynamicIntProperty(DefaultClientConfigImpl.DEFAULT_PROPERTY_NAME_SPACE &#43; ".ServerListSubsetFilter.size", 20);private DynamicFloatProperty eliminationPercent &#61; new DynamicFloatProperty(DefaultClientConfigImpl.DEFAULT_PROPERTY_NAME_SPACE &#43; ".ServerListSubsetFilter.forceEliminatePercent", 0.1f);private DynamicIntProperty eliminationFailureCountThreshold &#61; new DynamicIntProperty(DefaultClientConfigImpl.DEFAULT_PROPERTY_NAME_SPACE &#43; ".ServerListSubsetFilter.eliminationFailureThresold", 0);private DynamicIntProperty eliminationConnectionCountThreshold &#61; new DynamicIntProperty(DefaultClientConfigImpl.DEFAULT_PROPERTY_NAME_SPACE &#43; ".ServerListSubsetFilter.eliminationConnectionThresold", 0);&#64;Overridepublic void initWithNiwsConfig(IClientConfig clientConfig) {super.initWithNiwsConfig(clientConfig);sizeProp &#61; new DynamicIntProperty(clientConfig.getClientName() &#43; "." &#43; clientConfig.getNameSpace() &#43; ".ServerListSubsetFilter.size", 20);eliminationPercent &#61; new DynamicFloatProperty(clientConfig.getClientName() &#43; "." &#43; clientConfig.getNameSpace() &#43; ".ServerListSubsetFilter.forceEliminatePercent", 0.1f);eliminationFailureCountThreshold &#61; new DynamicIntProperty( clientConfig.getClientName() &#43; "." &#43; clientConfig.getNameSpace()&#43; ".ServerListSubsetFilter.eliminationFailureThresold", 0);eliminationConnectionCountThreshold &#61; new DynamicIntProperty(clientConfig.getClientName() &#43; "." &#43; clientConfig.getNameSpace()&#43; ".ServerListSubsetFilter.eliminationConnectionThresold", 0);}/*** Given all the servers, keep only a stable subset of servers to use. This method* keeps the current list of subset in use and keep returning the same list, with exceptions* to relatively unhealthy servers, which are defined as the following:*

*

    *
  • Servers with their concurrent connection count exceeding the client configuration for * {&#64;code ..ServerListSubsetFilter.eliminationConnectionThresold} (default is 0)*
  • Servers with their failure count exceeding the client configuration for * {&#64;code ..ServerListSubsetFilter.eliminationFailureThresold} (default is 0)*
  • If the servers evicted above is less than the forced eviction percentage as defined by client configuration* {&#64;code ..ServerListSubsetFilter.forceEliminatePercent} (default is 10%, or 0.1), the* remaining servers will be sorted by their health status and servers will worst health status will be* forced evicted.*
*

* After the elimination, new servers will be randomly chosen from all servers pool to keep the* number of the subset unchanged. * */&#64;Overridepublic List getFilteredListOfServers(List servers) {List zoneAffinityFiltered &#61; super.getFilteredListOfServers(servers);Set candidates &#61; Sets.newHashSet(zoneAffinityFiltered);Set newSubSet &#61; Sets.newHashSet(currentSubset);LoadBalancerStats lbStats &#61; getLoadBalancerStats();for (T server: currentSubset) {// this server is either down or out of serviceif (!candidates.contains(server)) {newSubSet.remove(server);} else {ServerStats stats &#61; lbStats.getSingleServerStat(server);// remove the servers that do not meet health criteriaif (stats.getActiveRequestsCount() > eliminationConnectionCountThreshold.get()|| stats.getFailureCount() > eliminationFailureCountThreshold.get()) {newSubSet.remove(server);// also remove from the general pool to avoid selecting them againcandidates.remove(server);}}}int targetedListSize &#61; sizeProp.get();int numEliminated &#61; currentSubset.size() - newSubSet.size();int minElimination &#61; (int) (targetedListSize * eliminationPercent.get());int numToForceEliminate &#61; 0;if (targetedListSize numEliminated) {numToForceEliminate &#61; minElimination - numEliminated; }if (numToForceEliminate > newSubSet.size()) {numToForceEliminate &#61; newSubSet.size();}if (numToForceEliminate > 0) {List sortedSubSet &#61; Lists.newArrayList(newSubSet); Collections.sort(sortedSubSet, this);List forceEliminated &#61; sortedSubSet.subList(0, numToForceEliminate);newSubSet.removeAll(forceEliminated);candidates.removeAll(forceEliminated);}// after forced elimination or elimination of unhealthy instances,// the size of the set may be less than the targeted size,// then we just randomly add servers from the big poolif (newSubSet.size() candidates.size()) {// Not enough healthy instances to choose, fallback to use the// total server poolcandidates &#61; Sets.newHashSet(zoneAffinityFiltered);candidates.removeAll(newSubSet);}List chosen &#61; randomChoose(Lists.newArrayList(candidates), numToChoose);for (T server: chosen) {newSubSet.add(server);}}currentSubset &#61; newSubSet; return Lists.newArrayList(newSubSet); }/*** Randomly shuffle the beginning portion of server list (according to the number passed into the method) * and return them.* * &#64;param servers* &#64;param toChoose* &#64;return*/private List randomChoose(List servers, int toChoose) {int size &#61; servers.size();if (toChoose >&#61; size || toChoose <0) {return servers;} for (int i &#61; 0; i }

 


推荐阅读
  • 个人学习使用:谨慎参考1Client类importcom.thoughtworks.gauge.Step;importcom.thoughtworks.gauge.T ... [详细]
  • 本文介绍了Oracle数据库中tnsnames.ora文件的作用和配置方法。tnsnames.ora文件在数据库启动过程中会被读取,用于解析LOCAL_LISTENER,并且与侦听无关。文章还提供了配置LOCAL_LISTENER和1522端口的示例,并展示了listener.ora文件的内容。 ... [详细]
  • 本文介绍了一个适用于PHP应用快速接入TRX和TRC20数字资产的开发包,该开发包支持使用自有Tron区块链节点的应用场景,也支持基于Tron官方公共API服务的轻量级部署场景。提供的功能包括生成地址、验证地址、查询余额、交易转账、查询最新区块和查询交易信息等。详细信息可参考tron-php的Github地址:https://github.com/Fenguoz/tron-php。 ... [详细]
  • 篇首语:本文由编程笔记#小编为大家整理,主要介绍了SpringCloudRibbon部分源码相关的知识,希望对你有一定的参考价值。1:ribbon是提供通过servi ... [详细]
  • zuul 路由不生效_Zuul网关到底有何牛逼之处?竟然这么多人在用~
    作者:kosamino来源:cnblogs.comjing99p11696192.html哈喽,各位新来的小伙伴们,大家好& ... [详细]
  • flutter图片缓存Flutter的图片缓存机制有问题(可能是我使用的版本1.12.13有问题)网络图片会默认缓存到本地,但是不管图片是不是完整的或者损坏的,导致页面在下次进入的 ... [详细]
  • SpringBoot uri统一权限管理的实现方法及步骤详解
    本文详细介绍了SpringBoot中实现uri统一权限管理的方法,包括表结构定义、自动统计URI并自动删除脏数据、程序启动加载等步骤。通过该方法可以提高系统的安全性,实现对系统任意接口的权限拦截验证。 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • 阿,里,云,物,联网,net,core,客户端,czgl,aliiotclient, ... [详细]
  • JavaSE笔试题-接口、抽象类、多态等问题解答
    本文解答了JavaSE笔试题中关于接口、抽象类、多态等问题。包括Math类的取整数方法、接口是否可继承、抽象类是否可实现接口、抽象类是否可继承具体类、抽象类中是否可以有静态main方法等问题。同时介绍了面向对象的特征,以及Java中实现多态的机制。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • 关键词:Golang, Cookie, 跟踪位置, net/http/cookiejar, package main, golang.org/x/net/publicsuffix, io/ioutil, log, net/http, net/http/cookiejar ... [详细]
  • r2dbc配置多数据源
    R2dbc配置多数据源问题根据官网配置r2dbc连接mysql多数据源所遇到的问题pom配置可以参考官网,不过我这样配置会报错我并没有这样配置将以下内容添加到pom.xml文件d ... [详细]
  • centos安装Mysql的方法及步骤详解
    本文介绍了centos安装Mysql的两种方式:rpm方式和绿色方式安装,详细介绍了安装所需的软件包以及安装过程中的注意事项,包括检查是否安装成功的方法。通过本文,读者可以了解到在centos系统上如何正确安装Mysql。 ... [详细]
author-avatar
幼俐佩其392
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有