目录

Feign简介

message-center改造

引入Feign依赖

修改启动类

创建Feign客户端

调用Feign客户端

关于传参

重写Feign的默认配置

关于超时

参考文章


Feign简介

Feign是一个声明式的Web Service客户端,它能够让Web Service客户端的编写变得更加容易(你只需创建一个接口,并在接口上添加相应注解即可)。除了Feign自带的注解外它还支持JAX-RS注解,SpringCloud又为Feign增加了对SpringMVC注解的支持,同时为了能够使用和Spring Web中默认使用的相同的httpMessageConverter,SpringCloud集成了Ribbon和Eureka,用来在使用Feign时能够为其提供一个负载均衡的HTTP客户端。

总起来说,Feign具有如下特性:

1.可插拔的注解支持,包括Feign注解和JAX-RS注解;
2.支持可插拔的HTTP编码器和解码器;
3.支持Hystrix和它的Fallback;
4.支持Ribbon的负载均衡;
5.支持HTTP请求和响应的压缩。

接下来我们将通过对上一章《客户端负载均衡(Ribbon)》中的 message-center 项目进行改造,演示如何使用Feign。

message-center改造

引入Feign依赖

由于Feign依赖中默认包含了Ribbon,所以只需要在 pom.xml 文件中引入Feign依赖即可,Ribbon依赖无需重复引入:

 <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.0.6.RELEASE</version></parent><properties><spring-cloud.version>Finchley.SR2</spring-cloud.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- Eureka-Client 依赖 --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency><!-- Feign 依赖 --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></dependency></dependencies><dependencyManagement><dependencies><!-- SpringCloud 版本控制依赖 --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>${spring-cloud.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement>

修改启动类

在MessageCenterApplication启动类上增加@EnableFeignClients注解:

import org.springframework.boot.WebApplicationType;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.cloud.openfeign.EnableFeignClients;@SpringBootApplication
@EnableFeignClients
public class MessageCenterApplication {public static void main(String[] args) {new SpringApplicationBuilder(MessageCenterApplication.class).web(WebApplicationType.SERVLET).run(args);}}

这里我们在启动类中增加了@EnableFeignClients注解,用来开启Feign客户端发现功能。

如果你的Feign客户端类文件不在Spring的包扫描路径之中,可以在@EnableFeignClients注解中对Feign客户端的包路径进行指定。

@SpringBootApplication
@EnableFeignClients(basePackages = "com.pengjunlee.client.**")
public class MessageCenterApplication {public static void main(String[] args) {new SpringApplicationBuilder(MessageCenterApplication.class).web(WebApplicationType.SERVLET).run(args);}}

创建Feign客户端

在上一章《客户端负载均衡(Ribbon)》中,对外提供服务的HTTP接口定义在MessageController中。

@RestController
@RequestMapping("/api/v1/msg")
public class MessageController {@Value("${server.port}")private String port;/*** 返回一条消息*/@GetMapping("/get")public String getMsg() {return "This message is sent from port: " + port;}
}

接下来,我们在消费端message-center中为它创建一个Feign客户端。新建一个接口取名MessageServiceClient,并在上面添加@FeignClient注解,完整代码如下:

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;@FeignClient(name = "message-service")
public interface MessageServiceClient {@GetMapping("/api/v1/msg/get")public String getMsg();
}

说明:此处@FeignClient注解的name属性应与message-service应用的spring.application.name属性相同,表示为message-service服务创建一个Feign客户端。接口的映射地址路径以及接口入参都必须与MessageController中的方法完全相同。

调用Feign客户端

接下来,我们来看一看如何在消费端使用创建好的Feign客户端对message-service服务进行调用,示例代码如下:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import com.pengjunlee.service.MessageServiceClient;@RestController
@RequestMapping("/api/v1/center")
public class MessageCenterController {@Autowiredprivate MessageServiceClient messageService;@GetMapping("/msg/get")public Object getMsg() {String msg = messageService.getMsg();return msg;}
}

启动应用,再次请求 http://localhost:8781/api/v1/center/msg/get ,返回如下结果表明服务调用成功:

关于传参

Feign除了支持自带的注解和JAX-RS注解外,还支持 SpringMVC注解,常用的有:@RequestParam 、@PathVariable、@RequestBody 等。

例如,服务端提供如下两个服务接口:

 /*** 获取消息详情*/@GetMapping("/api/v1/msg/detail/{id}")public MessageEntity getDetail(@PathVariable(name = "id") Long id) {return messageService.getById(id);}/*** 新建一条消息*/@PostMapping("/api/v1/msg/save")public MessageEntity save(@RequestBody MessageEntity message) {return messageService.save(message);}

相应的,在Feign客户端中可以进行如下定义:

 /*** 获取消息详情*/@GetMapping("/api/v1/msg/detail/{id}")public MessageEntity getDetail(@PathVariable(name = "id") Long id) ;/*** 新建一条消息*/@PostMapping("/api/v1/msg/save")public MessageEntity save(@RequestBody MessageEntity message) ;

重写Feign的默认配置

在Spring Cloud对Feign的支持实现中,一个核心的概念就是客户端命名,每一个Feign客户端都是整个组件系统的一部分,它们相互协同一起工作来按照需求与远程服务器取得联系。并且它们每一个都有自己的名字,应用程序开发人员可以使用@feignclient来给它取名。Spring Cloud按照自己的需要又使用FeignClientsConfiguration为每一个已命名的客户端创建了一个ApplicationContext,额外包含了一个feign.Decoder、一个 feign.Encoder 和一个 feign.Contract。你可以通过指定@FeignClient注解的contextId 属性来设置ApplicationContext的名字。

SpringCloud还允许你在FeignClientsConfiguration的基础之上使用@FeignClient声明一些额外的配置,从而实现对Feign客户端的完全控制,如下例所示:

@FeignClient(name = "message-service", configuration = MessageConfiguration.class)
public interface MessageServiceClient {//..
}

在这个例子中,这个Feign客户端将由FeignClientsConfiguration 和MessageConfiguration中的组件一起组成(后者会覆盖前者的配置)。

注意:本例中,MessageConfiguration不必用@Configuration注解进行标注,如果确实要加上@Configuration注解,你需要注意把MessageConfiguration排除在@ComponentScan和@SpringBootApplication扫描的包路径之外,否则它将成为feign.Decoder、feign.Encoder 和 feign.Contract 等的默认值。

下表列出了 Spring Cloud Netflix 缺省为Feign提供的所有 Bean(Bean类型 Bean名称:Bean实现):

Decoder feignDecoder: ResponseEntityDecoder (包装了一个 SpringDecoder)
Encoder feignEncoder: SpringEncoder
Logger feignLogger: Slf4jLogger
Contract feignContract: SpringMvcContract
Feign.Builder feignBuilder: HystrixFeign.Builder
Client feignClient: 启用 Ribbon 时是 LoadBalancerFeignClient,否则使用 feign.Client.Default。

你可以使用 OkHttpClient 或者 ApacheHttpClient 的Feign客户端,只需要将 feign.okhttp.enabled 或者 feign.httpclient.enabled 设置为 true ,并将相应类添加到项目的CLASSPATH即可。你也可以使用自定义的HTTP 客户端,使用 Apache 时提供一个ClosableHttpClient 类型Bean或者使用OK HTTP时提供一个OkHttpClient 类型Bean。

默认情况下,Spring Cloud Netflix 并没有为Feign提供下列的Bean,但依然会从Spring容器中查找这些类型的Bean用来创建Feign客户端。

Logger.Level
Retryer
ErrorDecoder
Request.Options
Collection<RequestInterceptor>
SetterFactory

创建这些类型的一个Bean 并将它写到 @FeignClient 声明的配置中,这样你就能够对这些Bean中的每一个进行重写。例如下面的 MessageConfiguration 利用feign.Contract.Default替代了SpringMvcContract 并向RequestInterceptor 集合中添加了一个RequestInterceptor 。

@Configuration
public class MessageConfiguration {@Beanpublic Contract feignContract() {return new feign.Contract.Default();}@Beanpublic BasicAuthRequestInterceptor basicAuthRequestInterceptor() {return new BasicAuthRequestInterceptor("user", "password");}
}

当然,@FeignClient 也支持通过配置文件进行配置。

feign:client:config:message-service:connectTimeout: 5000readTimeout: 5000loggerLevel: fullerrorDecoder: com.pengjunlee.SimpleErrorDecoderretryer: com.pengjunlee.SimpleRetryerrequestInterceptors:- com.pengjunlee.FooRequestInterceptor- com.pengjunlee.BarRequestInterceptordecode404: falseencoder: com.pengjunlee.SimpleEncoderdecoder: com.pengjunlee.SimpleDecodercontract: com.pengjunlee.SimpleContract

默认配置可以通过@EnableFeignClients的defaultConfiguration属性进行指定,然后会被应用到所有的Feign客户端。如果你希望使用配置文件对所有的@FeignClient进行配置,可以使用 default 作为Feign客户端的名称。

feign:client:config:default:connectTimeout: 5000readTimeout: 5000loggerLevel: basic

如果我们同时使用了@Configuration Bean和文件配置,文件配置会优先生效。如果你希望优先使用 @Configuration Bean中的配置,可以将 feign.client.default-to-properties 设置为 false 。

如果你需要在RequestInterceptor中使用ThreadLocal 变量,你需要将Hystrix 的线程隔离策略设置为 SEMAPHORE 或者直接禁用Hystrix 。

# To disable Hystrix in Feign
feign:hystrix:enabled: false# To set thread isolation to SEMAPHORE
hystrix:command:default:execution:isolation:strategy: SEMAPHORE

关于超时

在启用Ribbon的情况下,Feign客户端是一个LoadBalancerFeignClient Bean,其内部有一个 execute() 方法用来发送一个HTTP请求并获取响应, 本质上其实还是使用的Ribbon做负载均衡,并使用RestTemplate发送的请求。execute() 接口声明如下:

public Response execute(Request request, Request.Options options) throws IOException;

其中,Request 用来封装HTTP请求的详细信息。

/*** * An immutable request to an http server.* */public final class Request {private final String method;private final String url;private final Map<String, Collection<String>> headers;private final byte[] body;private final Charset charset;// ...}

Options 则封装了一些请求控制参数:

public static class Options {private final int connectTimeoutMillis;private final int readTimeoutMillis;private final boolean followRedirects;public Options(int connectTimeoutMillis, int readTimeoutMillis) {this(connectTimeoutMillis, readTimeoutMillis, true);}public Options() {this(10 * 1000, 60 * 1000);}// ...}

从Options 源码来看,Feign客户端默认的读取超时时间为60秒。若同时使用了Hystrix,由于Hystrix 默认的读取超时时间为1秒,会导致Feign客户端默认的读取超时时间设置无效,即超过1秒即为读取超时。可使用如下配置同时对Feign客户端和Hystrix 的超时配置进行重写。

feign:client:config:default:connectTimeout: 5000readTimeout: 5000

参考文章

https://cloud.spring.io/spring-cloud-openfeign/single/spring-cloud-openfeign.html

https://www.jianshu.com/p/a0d50385e598

https://blog.csdn.net/chengqiuming/article/details/80713471

模拟RPC调用(Feign)相关推荐

  1. java socket 远程调用_使用Socket反射Java流操作进行方法的远程调用(模拟RPC远程调用)...

    写在前面 阅读本文首先得具备基本的Socket.反射.Java流操作的基本API使用知识:否则本文你可能看不懂... 服务端的端口监听 进行远程调用,那就必须得有客户端和服务端.服务端负责提供服务,客 ...

  2. Feign实现RPC调用

    前言 Feign的中文名称翻译过来是伪装 那么Feign伪装的是什么呢?答案很明确,Feign伪装的是服务提供者. Feign可以用来做什么?既然能伪装,当然能提供服务提供者的功能,即RPC调用服务提 ...

  3. RabbitMQ (五)实现类似Dubbo的RPC调用

    springboot对rabbitMQ的接口做了封装,要实现 request/reponse 模式的调用,只需要调用 rabbitTemplate.convertSendAndReceive 方法即可 ...

  4. 深入剖析通信层和RPC调用的异步化(上)

    <Netty 进阶之路>.<分布式服务框架原理与实践>作者李林锋深入剖析通信层和 RPC 调用的异步化.李林锋此后还将在 InfoQ 上开设 Netty 专题持续出稿,感兴趣的 ...

  5. 开发中的坑:MQ 也能做 RPC 调用?

    hi, 大家好,我是 haohongfan. 最近浏览 帖子[1] 的时候看到一个有意思的吐槽. 大概意思是架构师没有选用 RPC 框架来做服务间调用,而选择用 MQ 来代替.是不是很意外? 当然不出 ...

  6. 趣说技术 | 用MQ 能完全替代 RPC 调用?

    最近浏览 帖子[1] 的时候看到一个有意思的吐槽. 图片 大概意思是架构师没有选用 RPC 框架来做服务间调用,而选择用 MQ 来代替.是不是很意外? 当然不出意外的,评论区炸了! 图片 现在提出一些 ...

  7. SpringCloud集成Dubbo实现RPC调用

    SpringCloud轻松集成Dubbo实现RPC调用 很久之前在做微服务架构选型的时候就听说阿里的微服务RPC框架dubbo,当时与Spring Cloud以http协议调用的架构做对比.发现dub ...

  8. 使用Dubbo实现简单的RPC调用(Spring配置文件版)

    更多文章和资源欢迎访问:SuperCoder Blog 文章目录 更多文章和资源欢迎访问:[SuperCoder Blog](https://supercoder.com.cn) 前言 一.Dubbo ...

  9. Spring Cloud之(十一)服务调用Feign

    十一.服务调用Feign 11.1 Feign简介 Feign是Netflix开发的声明式,模板化的HTTP客户端,其灵感来自Retrofit,JAXRS-2.0以及WebSocket. Feign可 ...

最新文章

  1. 易点租加速电脑租赁市场布局
  2. HTML的标签描述7
  3. matlab心电图诊断系统,ECG-diag MATLAB心电图自动诊断程序 联合开发网 - pudn.com
  4. 数位 DP 入门 (不要 62+windy 数)
  5. 使用Docker-镜像命令
  6. 2019.3.18 区块链论文翻译
  7. sql server安装记
  8. [蓝桥杯]算法提高 vertex cover(dfs)
  9. FreeSql (四)实体特性 Fluent Api
  10. Unity中Camera的Clear flags,Culling Mask,Depth参数
  11. 概率与计算机论文,数学概率统计论文范文
  12. 在centos平台下用modelsim对altera的ip核进行仿真
  13. FGUI手势案例代码
  14. Crackme 23
  15. 曲苑杂坛--收缩数据库日志
  16. 面试:设计一个电商平台积分兑换系统
  17. tbf格式用什么打开_TBF的完整形式是什么?
  18. java开发之异常处理_SimpleMappingExceptionResolver
  19. C++: 判断两个数互质(最大公约数为1)
  20. 互联网公司招聘--京东--产品岗-2017年笔试题

热门文章

  1. 背后的故事和故事的背后(1)
  2. 如何设计数据库(数据库设计原则)
  3. 嵌入式方案设计文档该怎么写?
  4. keras数据增广并保存到本地文件夹
  5. linux 设置rides(5.0.3)开机自启
  6. 大型项目中 MSAA 的方案参考
  7. python倒计时60_Python微项目分享之事件倒计时
  8. 教你如何写简历找工作
  9. vue3 ts main添加vform3,无法找到模块“vform3-builds”的声明文件
  10. 深证上证上市公司最新公告监控提醒