Лента без Eureka: лента не помнит, что сервер не работает через PingURL

Я использую Ribbon без Eureka. Я использую ConfigurationBasedServerList, чтобы предоставить список таких экземпляров сервера.

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

Я настроил PingURL с конечной точкой /health. Я также настроил 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) Пропингуйте их, чтобы узнать их статус. 3) Обновите список доступных серверов в зависимости от результатов пинга.

Кажется, что каждые 30 секунд происходит описанный выше процесс, который должен поддерживать DynamicServerList.

Теперь проблема в том, что от первого оператора журнала до предпоследнего оператора журнала лента считает, что оба экземпляра сервера доступны. Таким образом, если в течение этого времени поступает запрос на балансировку нагрузки, есть вероятность, что он будет отправлен на сервер localhost:9008, который отключен.

Насколько я понимаю, библиотека Ribbon не хранит PingStatistics. Я думаю, что библиотека зависит от инструментов обнаружения служб, таких как Eureka, для предоставления динамического списка серверов, которые исправны в зависимости от некоторых проверок работоспособности.

Теперь, чтобы решить эту проблему, я могу начать использовать Eureka, и эта проблема может исчезнуть. Я не хочу использовать Eureka, так как моя среда не часто увеличивается/уменьшается... она довольно статична.

Есть ли конфигурация, которую мне здесь не хватает? Как решить эту проблему?

Я использую «весеннюю облачную стартовую ленту» версии 1.2.6.RELEASE.


person Amith M    schedule 06.10.2017    source источник
comment
Эта проблема возникает только до завершения первой команды ping?   -  person Azarea    schedule 18.10.2017
comment
@Sakura Kyouko ... нет, это не ограничивается - до завершения первой команды ping.   -  person Amith M    schedule 23.10.2017
comment
проблема, я думаю, в том, что автоматический выключатель включается только после нескольких сбоев соединения. Функция прерывателя цепи не предусмотрена для компонента PingUrl. Я думаю, что eureka и другие инструменты удалят сервер из списка, когда проверки работоспособности начнут давать сбой. Этот бит недоступен в библиотеке ленты, если не используются инструменты обнаружения служб.   -  person Amith M    schedule 23.10.2017


Ответы (1)


Все доступные реализации 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);
    }
}

person Roc King    schedule 17.12.2019