4

我试图将 Feign 设置为与 RibbonClient 一起使用,例如MyService api = Feign.builder().client(RibbonClient.create()).target(MyService.class, "https://myAppProd");,其中 myAppProd 是我可以在 Consul 中看到的应用程序。现在,如果我为 Feign 客户端 ( @FeignClient("myAppProd"), @RequestMapping) 使用 Spring 注释,那么一切都可以正常工作,因为 Spring Cloud 模块会处理一切。

如果我想使用Feign.builder()and @RequestLine,我会得到错误: com.netflix.client.ClientException: Load balancer does not have available server for client: myAppProd.

我最初的想法是 Feign 是为与 Eureka 一起工作而构建的,只有 Spring Cloud 与 Consul 集成,但我不确定这一点。

那么,有没有办法让 Feign 在没有 Spring Cloud 的情况下与 Consul 一起工作呢?

提前致谢。

4

1 回答 1

1

在我看来,这不是与领事的假装工作,它的假装->功能区->领事。

RibbonClient 需要serverList从它的LoadBalancer. 如果没有 ServerList,则会出现错误:“没有可供客户端使用的服务器”。

这个工作已经由 SpringCloudConsul 和 SpringCloudRibbon 项目完成,当然你也可以再写一个适配器,只是一些胶水代码。恕我直言,您可以将此弹簧依赖项导入您的项目,但以非弹簧方式使用它。演示代码:

只需编写一个新feign.ribbon.LBClientFactory的,使用 ConsulServerList(Spring 的类)生成 LBClient。

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);
    }
}

然后在feign中使用它:

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到你当地的领事。

于 2019-02-12T06:41:23.407 回答