5、Spring Cloud-声明式调用 Feign(下)
5.5、在Feign中使用HttpClient和OkhHttp
FeignRibbonClientAutoConfiguration.java
@ConditionalOnClass({ILoadBalancer.class, Feign.class})
@Configuration
@AutoConfigureBefore({FeignAutoConfiguration.class})
@EnableConfigurationProperties({FeignHttpClientProperties.class})
@Import({HttpClientFeignLoadBalancedConfiguration.class, OkHttpFeignLoadBalancedConfiguration.class, DefaultFeignLoadBalancedConfiguration.class})
public class FeignRibbonClientAutoConfiguration {
public FeignRibbonClientAutoConfiguration() {
} @Bean
@Primary
@ConditionalOnMissingBean
@ConditionalOnMissingClass({"org.springframework.retry.support.RetryTemplate"})
public CachingSpringLoadBalancerFactory cachingLBClientFactory(SpringClientFactory factory) {
return new CachingSpringLoadBalancerFactory(factory);
} @Bean
@Primary
@ConditionalOnMissingBean
@ConditionalOnClass(
name = {"org.springframework.retry.support.RetryTemplate"}
)
public CachingSpringLoadBalancerFactory retryabeCachingLBClientFactory(SpringClientFactory factory, LoadBalancedRetryFactory retryFactory) {
return new CachingSpringLoadBalancerFactory(factory, retryFactory);
} @Bean
@ConditionalOnMissingBean
public Options feignRequestOptions() {
return LoadBalancerFeignClient.DEFAULT_OPTIONS;
}
}
<dependency>
<groupId>com.netflix.feign</groupId>
<artifactId>feign-httpclient</artifactId>
</dependency>
配置文件中:
feign.httpclient.enabled=true
从新启动即可(具体看源码进行分析)
5.6、Feign如何实现负载均衡
LoadBalancerFeignClient.java
public Response execute(Request request, Options options) throws IOException {
try {
URI asUri = URI.create(request.url());
String clientName = asUri.getHost();
URI uriWithoutHost = cleanUrl(request.url(), clientName);
RibbonRequest ribbonRequest = new RibbonRequest(this.delegate, request, uriWithoutHost);
IClientConfig requestConfig = this.getClientConfig(options, clientName);
return ((RibbonResponse)this.lbClient(clientName).executeWithLoadBalancer(ribbonRequest, requestConfig)).toResponse();
} catch (ClientException var8) {
IOException io = this.findIOException(var8);
if (io != null) {
throw io;
} else {
throw new RuntimeException(var8);
}
}
}
execute执行请求的方法
public T executeWithLoadBalancer(final S request, final IClientConfig requestConfig) throws ClientException {
LoadBalancerCommand command = this.buildLoadBalancerCommand(request, requestConfig); try {
return (IResponse)command.submit(new ServerOperation<T>() {
public Observable<T> call(Server server) {
URI finalUri = AbstractLoadBalancerAwareClient.this.reconstructURIWithServer(server, request.getUri());
ClientRequest requestForServer = request.replaceUri(finalUri); try {
return Observable.just(AbstractLoadBalancerAwareClient.this.execute(requestForServer, requestConfig));
} catch (Exception var5) {
return Observable.error(var5);
}
}
}).toBlocking().single();
} catch (Exception var6) {
Throwable t = var6.getCause();
if (t instanceof ClientException) {
throw (ClientException)t;
} else {
throw new ClientException(var6);
}
}
}
public Observable<T> submit(final ServerOperation<T> operation) {
final LoadBalancerCommand<T>.ExecutionInfoContext context = new LoadBalancerCommand.ExecutionInfoContext();
if (this.listenerInvoker != null) {
try {
this.listenerInvoker.onExecutionStart();
} catch (AbortExecutionException var6) {
return Observable.error(var6);
}
} final int maxRetrysSame = this.retryHandler.getMaxRetriesOnSameServer();
final int maxRetrysNext = this.retryHandler.getMaxRetriesOnNextServer();
Observable<T> o = (this.server == null ? this.selectServer() : Observable.just(this.server)).concatMap(new Func1<Server, Observable<T>>() {
public Observable<T> call(Server server) {
context.setServer(server);
......
上述代码中有一个selectServe()方法:该方法就是选择服务进行负载均衡的方法
private Observable<Server> selectServer() {
return Observable.create(new OnSubscribe<Server>() {
public void call(Subscriber<? super Server> next) {
try {
Server server = LoadBalancerCommand.this.loadBalancerContext.getServerFromLoadBalancer(LoadBalancerCommand.this.loadBalancerURI, LoadBalancerCommand.this.loadBalancerKey);
next.onNext(server);
next.onCompleted();
} catch (Exception var3) {
next.onError(var3);
} }
});
}
由上述可知,最终负载均衡交给loadbalancerContext来处理
5.7、总结
5、Spring Cloud-声明式调用 Feign(下)的更多相关文章
- spring cloud服务间调用feign
参考文章:Spring Cloud Feign设计原理 1.feign是spring cloud服务间相互调用的组件,声明式.模板化的HTTP客户端.类似的HttpURLConnection.Apac ...
- Spring Cloud声明式调用Feign负载均衡FeignClient详解
为了深入理解Feign,下面将从源码的角度来讲解Feign.首先来看看FeignClient注解@FeignClient的源码,代码如下: FeignClient注解被@Target(ElementT ...
- spring cloud 2.x版本 Feign服务发现教程(内含集成Hystrix熔断机制)
前言 本文采用Spring cloud本文为2.1.8RELEASE,version=Greenwich.SR3 本文基于前两篇文章eureka-server和eureka-client的实现. 参考 ...
- Spring-Cloud之Feign声明式调用-4
一.Feign受Retrofit.JAXRS-2.0和WebSocket影响,采用了声明式API 接口的风格,将Java Http 客户端绑定到它的内部. Feign 首要目的是将 Java Http ...
- Spring Cloud项目中通过Feign进行内部服务调用发生401\407错误无返回信息的问题
问题描述 最近在使用Spring Cloud改造现有服务的工作中,在内部服务的调用方式上选择了Feign组件,由于服务与服务之间有权限控制,发现通过Feign来进行调用时如果发生了401.407错误时 ...
- 【spring cloud】spring cloud2.X spring boot2.0.4调用feign配置Hystrix Dashboard 和 集成Turbine 【解决:Hystrix仪表盘Unable to connect to Command Metric Stream】【解决:Hystrix仪表盘Loading...】
环境: <java.version>1.8</java.version><spring-boot.version>2.0.4.RELEASE</spring- ...
- Spring Cloud系列之使用Feign进行服务调用
在上一章的学习中,我们知道了微服务的基本概念,知道怎么基于Ribbon+restTemplate的方式实现服务调用,接着上篇博客,我们学习怎么基于Feign实现服务调用,请先学习上篇博客,然后再学习本 ...
- Spring Cloud Alibaba Sentinel 整合 Feign 的设计实现
作者 | Spring Cloud Alibaba 高级开发工程师洛夜 来自公众号阿里巴巴中间件投稿 前段时间 Hystrix 宣布不再维护之后(Hystrix 停止开发...Spring Cloud ...
- Spring Cloud系列文,Feign整合Ribbon和Hysrix
在本博客之前的Spring Cloud系列里,我们讲述了Feign的基本用法,这里我们将讲述下Feign整合Ribbon实现负载均衡以及整合Hystrix实现断路保护效果的方式. 1 准备Eureka ...
- Spring Cloud Alibaba Sentinel对Feign的支持
Spring Cloud Alibaba Sentinel 除了对 RestTemplate 做了支持,同样对于 Feign 也做了支持,如果我们要从 Hystrix 切换到 Sentinel 是非常 ...
随机推荐
- Java学习--jsp基础语法
<%! %>和<% %>的区别: <%! //1.可定义方法 //2.可定义static方法 //3.可定义static属性 //4.不可以使用out对象 %> ...
- mysql数据导入mongoDB
目前许多平台都会同时使用MySQL , mongoDB 两款数据库软件,他们之间的数据同步交换也是经常面临的问题,如何定时的进行数据交换同步是一个要面对的问题. 通过Treesoft数据库管理系统可以 ...
- unity3d之使用技巧
知乎 project.hierarchy折叠打开全部文件夹——alt +方向键
- Class.forName("com.mysql.jdbc.Driver")找不到类
解决方法: 如果是java项目,只需要引入mysql-connector-java-8.0.13.jar就可以运行java项目. 建的如果是web工程,需要把mysql-connector-java- ...
- [翻译]Review——Learn these core JavaScript concepts in just a few minutes
Learn these core JavaScript concepts in just a few minutes(只需几分钟即可学习这些核心JavaScript概念) 原文地址:https://m ...
- drupal7 自定义登录&找回密码页面,注意事项
1.登录页面的 $form['form_id'] 和 $form['form_build_id'],是这样输出的: <?php print drupal_render($form['form_i ...
- eclipse 断点调试快捷键
(1)Ctrl+M --切换窗口的大小(2)Ctrl+Q --跳到最后一次的编辑处(3)F2 --当鼠标放在一个标记处出现Tooltip时候按F2则把鼠标移开时Tooltip还会显示即Show Too ...
- 浅谈count(*)、count(1)、count(列名)
count(*) 和 count(1)和count(列名)区别 执行效果上: count(*)包括了所有的列,相当于行数,在统计结果的时候,不会忽略列值为NULL count(1)包括了所有列, ...
- C++中接口与实现分离的技术 ZZ
最简单清晰的例子:http://www.cnblogs.com/maoye/archive/2010/03/19/1690183.html 接口与实现分离 为什么这样设计? 主要原因是保持接口的稳定, ...
- Django路由系统---Django重点之url别名
django重点之url别名[参数名必须是name,格式是name="XXX] 不论后台路径如何进行修改路径,前台访问的路径不变,永远是alias, 这样方便开发 前台根据 {{ url & ...