Фантазируйте с RibbonClient и обнаружением Consul без Spring Cloud

Я пытался настроить Feign для работы с RibbonClient, что-то вроде MyService api = Feign.builder().client(RibbonClient.create()).target(MyService.class, "https://myAppProd");, где myAppProd — это приложение, которое я вижу в Consul. Теперь, если я использую аннотации Spring для клиента Feign (@FeignClient("myAppProd"), @RequestMapping), все работает, так как модуль Spring Cloud позаботится обо всем.

Если я хочу использовать Feign.builder() и @RequestLine, я получаю сообщение об ошибке: com.netflix.client.ClientException: Load balancer does not have available server for client: myAppProd.

Моей первой первоначальной мыслью было то, что Feign был создан для работы с Eureka, и только Spring Cloud обеспечивает интеграцию с Consul, но я не уверен в этом.

Итак, есть ли способ заставить Feign работать с Consul без Spring Cloud?

Заранее спасибо.


person Turbut Alin    schedule 03.04.2017    source источник


Ответы (1)


На мой взгляд, это не притворная работа с консулом, это притворство -> лента -> консул.

RibbonClient необходимо найти serverList myAppProd из его LoadBalancer. Без ServerList ошибка: «нет доступного сервера для клиента».

Эту работу проделали SpringCloudConsul и проект SpringCloudRibbon, конечно, вы можете написать еще один адаптер, это просто связующий код. ИМХО, вы можете импортировать эту весеннюю зависимость в свой проект, но использовать ее не-весенним способом. Демонстрационный код:

просто напишите новый feign.ribbon.LBClientFactory, который генерирует LBClient с ConsulServerList (класс Spring).

public class ConsulLBFactory implements LBClientFactory {

    private ConsulClient client;
    private ConsulDiscoveryProperties properties;

    public ConsulLBFactory(ConsulClient client, ConsulDiscoveryProperties consulDiscoveryProperties) {
        this.client = client;
        this.properties = consulDiscoveryProperties;
    }

    @Override
    public LBClient create(String clientName) {
        IClientConfig config =
            ClientFactory.getNamedConfig(clientName, DisableAutoRetriesByDefaultClientConfig.class);

        ConsulServerList consulServerList = new ConsulServerList(this.client, properties);
        consulServerList.initWithNiwsConfig(config);

        ZoneAwareLoadBalancer<ConsulServer> lb = new ZoneAwareLoadBalancer<>(config);

        lb.setServersList(consulServerList.getInitialListOfServers());
        lb.setServerListImpl(consulServerList);
        return LBClient.create(lb, config);
    }
}

а затем используйте его в симуляции:

public class Demo {
    public static void main(String[] args) {
        ConsulLBFactory consulLBFactory = new ConsulLBFactory(
            new ConsulClient(),
            new ConsulDiscoveryProperties(new InetUtils(new InetUtilsProperties()))
        );

        RibbonClient ribbonClient = RibbonClient.builder()
            .lbClientFactory(consulLBFactory)
            .build();

        GitHub github = Feign.builder()
            .client(ribbonClient)
            .decoder(new GsonDecoder())
            .target(GitHub.class, "https://api.github.com");

        List<Contributor> contributors = github.contributors("OpenFeign", "feign");
        for (Contributor contributor : contributors) {
            System.out.println(contributor.login + " (" + contributor.contributions + ")");
        }
    }

    interface GitHub {
        @RequestLine("GET /repos/{owner}/{repo}/contributors")
        List<Contributor> contributors(@Param("owner") String owner, @Param("repo") String repo);
    }

    public static class Contributor {
        String login;
        int contributions;
    }
}

вы можете найти это демо-код здесь, добавьте api.github.com в свой локальный консул перед запуском этой демо-версии.

person tianzhipeng    schedule 12.02.2019