不带Eureka的色带:Ribbon不记得服务器通过PingURL关闭了

问题描述 投票:0回答:1

我使用的是不带Eureka的Ribbon。我使用的是ConfigurationBasedServerList来提供服务器实例的列表,如下所示。

customerinfo.ribbon.listOfServers=localhost:9003,localhost:9008

我已使用/ health端点配置PingURL。我还配置了AvailabilityFilteringRule,它需要过滤不可用的服务器实例。像这样..

public class RibbonConfig {

@Autowired
IClientConfig ribbonClientConfig;

@Bean
public IPing ribbonPing(IClientConfig config) {
    return new PingUrl(true, "/health");
}

@Bean
public IRule ribbonRule(IClientConfig config) {
    return new AvailabilityFilteringRule();
}

}

这通常效果很好。在一种情况下,它不能很好地工作。在端口9008上运行的服务器实例关闭时,情况就是这样。

让我解释一些调试消息。

DEBUG com.netflix.loadbalancer.DynamicServerListLoadBalancer - List of Servers for customerinfo obtained from Discovery client: [localhost:9003, localhost:9008]
DEBUG com.netflix.loadbalancer.DynamicServerListLoadBalancer - Filtered List of Servers for customerinfo obtained from Discovery client: [localhost:9003, localhost:9008]
DEBUG com.netflix.loadbalancer.BaseLoadBalancer - LoadBalancer:  clearing server list (SET op)
DEBUG com.netflix.loadbalancer.BaseLoadBalancer - LoadBalancer:  addServer [localhost:9003]
DEBUG com.netflix.loadbalancer.BaseLoadBalancer - LoadBalancer:  addServer [localhost:9008]
com.netflix.loadbalancer.DynamicServerListLoadBalancer - Setting server list for zones: {unknown=[localhost:9003, localhost:9008]}
DEBUG com.netflix.loadbalancer.BaseLoadBalancer - LoadBalancer:  clearing server list (SET op)
DEBUG com.netflix.loadbalancer.BaseLoadBalancer - LoadBalancer:  addServer [localhost:9003]
DEBUG com.netflix.loadbalancer.BaseLoadBalancer - LoadBalancer:  addServer [localhost:9008]
DEBUG com.netflix.loadbalancer.BaseLoadBalancer - LoadBalancer:  forceQuickPing invoked
DEBUG com.netflix.loadbalancer.BaseLoadBalancer - LoadBalancer:  PingTask executing [2] servers configured
DEBUG com.netflix.loadbalancer.BaseLoadBalancer - LoadBalancer:  Server [localhost:9008] status changed to DEAD

查看DEBUG消息。遵循的过程如下所示:1)清除服务器列表,然后再次从配置中添加服务器。2)对他们的状态进行Ping。3)根据ping结果更新可用的服务器列表。

似乎每隔30秒就会发生上述过程,以维护DynamicServerList。

现在,问题是-从第一个log语句到倒数第二个log语句,ribbon认为两个服务器实例均可用。因此,如果在此时间内出现负载平衡请求,则可能会将其发送到服务器localhost:9008,该服务器处于DOWN状态。

据我了解,Ribbon库未保留PingStatistics。我认为该库依靠Eureka之类的服务发现工具来提供DynamicServerlist,该服务取决于某些运行状况检查是否正常。

现在,要解决此问题,我可以开始使用Eureka,并且此问题可能会消失。我不想使用Eureka,因为我的环境不会经常增长/缩小...它几乎是静态的。

我在这里缺少配置吗?我们如何解决这个问题?

我正在使用“ spring-cloud-starter-ribbon”版本1.2.6.RELEASE。

spring-cloud-netflix netflix-ribbon
1个回答
0
投票
所有可用的IRule实现均未正确使用reachableServers,我们必须实现一个新的IRule。

@Slf4j public class LoadBalanceConfig { @Bean public IClientConfig ribbonClientConfig() { DefaultClientConfigImpl config = new DefaultClientConfigImpl(); config.set(IClientConfigKey.Keys.IsSecure, false); config.set(IClientConfigKey.Keys.ListOfServers, XXXXXXX); config.set(IClientConfigKey.Keys.ServerListRefreshInterval, 3000); return config; } @Bean public ServerList<Server> ribbonServerList(IClientConfig clientConfig) { AbstractServerList<Server> lst = new ConfigurationBasedServerList(); lst.initWithNiwsConfig(clientConfig); return lst; } @Bean public ServerListFilter<Server> ribbonServerListFilter() { return new AbstractServerListFilter<Server>() { @Override public List<Server> getFilteredListOfServers(List<Server> servers) { return servers; } }; } // modified from com.netflix.loadbalancer.RoundRobinRule public static class RoundRobinRule implements IRule { private ILoadBalancer lb; private AtomicInteger nextServerCyclicCounter = new AtomicInteger(0); @Override public void setLoadBalancer(ILoadBalancer lb) { this.lb = lb; } @Override public ILoadBalancer getLoadBalancer() { return lb; } @Override public Server choose(Object key) { ILoadBalancer lb = getLoadBalancer(); if (lb == null) { log.warn("no load balancer"); return null; } List<Server> reachableServers = lb.getReachableServers(); int upCount = reachableServers.size(); if (upCount == 0) { log.warn("No up servers available from load balancer: " + lb); return null; } int nextServerIndex = incrementAndGetModulo(upCount); return reachableServers.get(nextServerIndex); } private int incrementAndGetModulo(int modulo) { for (;;) { int current = nextServerCyclicCounter.get(); int next = (current + 1) % modulo; if (nextServerCyclicCounter.compareAndSet(current, next)) { return next; } } } } @Bean public IRule ribbonRule() { return new RoundRobinRule(); } @Bean public IPing ribbonPing() { PingUrl ping = new PingUrl(false, "/XXXactive_detect"); ping.setExpectedContent("{\"status\":\"OK\"}"); return ping; } @Bean public ILoadBalancer ribbonLoadBalancer(IClientConfig clientConfig, IRule rule, IPing ping, ServerList<Server> serverList, ServerListFilter<Server> filter, ServerListUpdater serverListUpdater) { DynamicServerListLoadBalancer<Server> loadBalancer = new DynamicServerListLoadBalancer<>(clientConfig, rule, ping, serverList, filter, serverListUpdater); return loadBalancer; } @Bean public ServerListUpdater ribbonServerListUpdater(IClientConfig clientConfig) { return new PollingServerListUpdater(clientConfig); } }

© www.soinside.com 2019 - 2024. All rights reserved.