我在没有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消息。
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。
现在,问题是 - 从第一个日志语句到倒数第二个日志语句,功能区认为两个服务器实例都可用。因此,如果在该时间内存在负载均衡请求,则有可能将其发送到服务器localhost:9008,即DOWN。
据我所知,功能区库不保留PingStatistics。我认为库依赖于像Eureka这样的服务发现工具来提供DynamicServerlist,它们是健康的,具体取决于一些健康检查。
现在,为了解决这个问题,我可以开始使用Eureka,这个问题可能会消失。我不想使用Eureka,因为我的环境经常不会增长/缩小......它几乎是静态的。
我在这里缺少配置吗?我们如何解决这个问题?
我正在使用“spring-cloud-starter-ribbon”版本1.2.6.RELEASE。
答案 0 :(得分: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);
}
}