当前位置: 首页 > 知识库问答 >
问题:

没有Eureka的Ribbon:Ribbon不记得服务器通过PingURL停机

平俊茂
2023-03-14

我正在使用Ribbon而不使用Eureka。我正在使用ConfigurationBasedServerList提供这样的服务器实例列表。。

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

我已经用/healthendpoint配置了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

查看调试消息。下面的过程看起来是这样的:1)清除服务器列表并再次从配置中添加服务器。2) Ping他们的状态。3)根据ping结果更新可用服务器列表。

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

现在,问题是,从第一条日志语句到倒数第二条日志语句,ribbon认为这两个服务器实例都可用。因此,如果在该时间内出现负载平衡请求,则有可能将其发送到服务器localhost:9008,即DOWN。

据我了解,Ribbon库并没有保留PingStatistics。我认为该库依赖于诸如Eureka之类的服务发现工具来提供DynamicServerlist,它是健康的,取决于一些健康检查。

现在,为了解决这个问题,我可以开始使用Eureka,这个问题可能会消失。我不想使用Eureka,因为我的环境不会经常增长/收缩…它几乎是静态的。

这里有我丢失的配置吗?我们如何解决这个问题?

我使用的是"sping-cloud-starter-ribbon"版本1.2.6.RELEASE.

共有1个答案

弘焕
2023-03-14

所有可用的 IRule 实现都不能正确使用可访问的服务器,我们必须实现一个新的 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);
    }
}

 类似资料:
  • 我使用SpringBoot、SpringCloudNetfix和docker来运行微服务。 在非停靠环境中一切正常,但一旦我停靠了eureka服务器和microservice(例如用户服务),我发现用户服务无法注册到eureka服务器。 我可以通过http://{Ubuntu server}:8761/eureka/访问停靠的eureka服务器,或者通过http://{Ubuntu server}

  • 如何包含Eureka服务器 要在项目中包含Eureka服务器,请使用组org.springframework.cloud和工件id spring-cloud-starter-eureka-server的启动器。有关 使用当前的Spring Cloud发布列表设置构建系统的详细信息,请参阅Spring Cloud项目页面。 如何运行Eureka服务器 示例eureka服务器; @SpringBoot

  • pom.xml 主应用程序类 Application.Properties eureka客户端设置 pom.xml Application.Properties 我在eureka-server仪表板(http://localhost:8761)中没有看到向Eureka server注册的micro-service-currency-exchange-service 为什么eureka客户端没有注册

  • iam使用spring boot gateway与eureka服务器,但当我试图从gateway访问某个api时,它不使用gateway路由的路径,而是使用服务名 但如果我将“book”替换为“books”(服务名),它就会起作用

  • 问题描述: 我们有100多个springboot服务运行在不同的环境中:dev、uat、prod等,对于每一个,我们都有eureka服务器正在运行以注册这些微服务,这没有问题,在部署一个服务之后,它会注册并且工作良好,但是当我们在本地运行一个服务时,它会在prod的eureka服务器中注册,