我试图将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()
和@RequestLine
,我会收到错误消息:
com.netflix.client.ClientException: Load balancer does not have available server for client: myAppProd
。
我的第一个初步想法是,Feign是为与Eureka合作而建立的,只有Spring Cloud与Consul集成,但我对此不确定。
那么,有没有办法让Feign在没有Spring Cloud的情况下与Consul合作?
提前致谢。
答案 0 :(得分:0)
我认为与领事不是伪装,而是伪装->丝带->领事。
RibbonClient需要从其serverList
中找到myAppProd的LoadBalancer
。
如果没有ServerList,则错误:“客户端没有可用的服务器”。
这项工作是由SpringCloudConsul和SpringCloudRibbon项目完成的,当然您可以编写另一个适配器,这只是一些粘合代码。恕我直言,您可以将此Spring依赖项导入到您的项目中,但以非Spring方式使用它。演示代码:
只需编写一个新的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);
}
}
然后假装使用它:
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;
}
}
您可以找到此demo code here,并在运行此演示之前将api.github.com
添加到本地领事。