使用Spring Cloud Feign作为HTTP客户端调用远程HTTP服务
2017-05-06 20:40
1376 查看
在spring Cloud Netflix栈中,各个微服务都是以HTTP接口的形式暴露自身服务的,因此在调用远程服务时就必须使用HTTP客户端。我们可以使用JDK原生的
Feign是一种声明式、模板化的HTTP客户端。在Spring Cloud中使用Feign, 我们可以做到使用HTTP请求远程服务时能与调用本地方法一样的编码体验,开发者完全感知不到这是远程方法,更感知不到这是个HTTP请求。比如:
2
3
4
5
6
1
2
3
4
5
6
开发者通过
为了让Feign知道在调用方法时应该向哪个地址发请求以及请求需要带哪些参数,我们需要定义一个接口:
2
3
4
5
6
7
8
1
2
3
4
5
6
7
8
A:
B:
C:
Spring Cloud应用在启动时,Feign会扫描标有
在本例中,我们将Feign与Eureka和Ribbon组合使用,
Feign将方法签名中方法参数对象序列化为请求参数放到HTTP请求中的过程,是由编码器(Encoder)完成的。同理,将HTTP响应数据反序列化为Java对象是由解码器(Decoder)完成的。
默认情况下,Feign会将标有
2
1
2
此时因为声明的是GET请求没有请求体,所以
在Spring Cloud环境下,Feign的Encoder*只会用来编码没有添加注解的参数*。如果你自定义了Encoder, 那么只有在编码
~ 300之间时ErrorDecoder才会被调用。ErrorDecoder的作用是可以根据HTTP响应信息返回一个异常,该异常可以在调用Feign接口的地方被捕获到。我们目前就通过ErrorDecoder来使Feign接口抛出业务异常以供调用者处理。
Feign在默认情况下使用的是JDK原生的
HTTP Client和
2
3
4
5
6
7
8
9
10
1
2
3
4
5
6
7
8
9
10
然后在
1
通过Feign, 我们能把HTTP远程调用对开发者完全透明,得到与调用本地方法一致的编码体验。这一点与阿里Dubbo中暴露远程服务的方式类似,区别在于Dubbo是基于私有二进制协议,而Feign本质上还是个HTTP客户端。如果是在用Spring Cloud Netflix搭建微服务,那么Feign无疑是最佳选择。
URLConnection、Apache的
Http Client、Netty的异步HTTP Client, Spring的
RestTemplate。但是,用起来最方便、最优雅的还是要属Feign了。
Feign简介
Feign是一种声明式、模板化的HTTP客户端。在Spring Cloud中使用Feign, 我们可以做到使用HTTP请求远程服务时能与调用本地方法一样的编码体验,开发者完全感知不到这是远程方法,更感知不到这是个HTTP请求。比如:@Autowired private AdvertGropRemoteService service; // 远程服务 public AdvertGroupVO foo(Integer groupId) { return service.findByGroupId(groupId); // 通过HTTP调用远程服务 }1
2
3
4
5
6
1
2
3
4
5
6
开发者通过
service.findByGroupId()就能完成发送HTTP请求和解码HTTP返回结果并封装成对象的过程。
Feign的定义
为了让Feign知道在调用方法时应该向哪个地址发请求以及请求需要带哪些参数,我们需要定义一个接口:@FeignClient(name = "ea") // [A] public interface AdvertGroupRemoteService { @RequestMapping(value = "/group/{groupId}", method = RequestMethod.GET) // [B] AdvertGroupVO findByGroupId(@PathVariable("groupId") Integer adGroupId) // [C] @RequestMapping(value = "/group/{groupId}", method = RequestMethod.PUT) void update(@PathVariable("groupId") Integer groupId, @RequestParam("groupName") String groupName)1
2
3
4
5
6
7
8
1
2
3
4
5
6
7
8
A:
@FeignClient用于通知Feign组件对该接口进行代理(不需要编写接口实现),使用者可直接通过
@Autowired注入。
B:
@RequestMapping表示在调用该方法时需要向
/group/{groupId}发送
GET请求。
C:
@PathVariable与
SpringMVC中对应注解含义相同。
Spring Cloud应用在启动时,Feign会扫描标有
@FeignClient注解的接口,生成代理,并注册到Spring容器中。生成代理时Feign会为每个接口方法创建一个
RequetTemplate对象,该对象封装了HTTP请求需要的全部信息,请求参数名、请求方法等信息都是在这个过程中确定的,Feign的模板化就体现在这里。
在本例中,我们将Feign与Eureka和Ribbon组合使用,
@FeignClient(name = "ea")意为通知Feign在调用该接口方法时要向Eureka中查询名为
ea的服务,从而得到服务URL。
Feign的Encoder、Decoder和ErrorDecoder
Feign将方法签名中方法参数对象序列化为请求参数放到HTTP请求中的过程,是由编码器(Encoder)完成的。同理,将HTTP响应数据反序列化为Java对象是由解码器(Decoder)完成的。默认情况下,Feign会将标有
@RequestParam注解的参数转换成字符串添加到URL中,将没有注解的参数通过Jackson转换成json放到请求体中。注意,如果在
@RequetMapping中的
method将请求方式指定为
POST,那么所有未标注解的参数将会被忽略,例如:
@RequestMapping(value = "/group/{groupId}", method = RequestMethod.GET) void update(@PathVariable("groupId") Integer groupId, @RequestParam("groupName") String groupName, DataObject obj);1
2
1
2
此时因为声明的是GET请求没有请求体,所以
obj参数就会被忽略。
在Spring Cloud环境下,Feign的Encoder*只会用来编码没有添加注解的参数*。如果你自定义了Encoder, 那么只有在编码
obj参数时才会调用你的Encoder。对于Decoder, 默认会委托给SpringMVC中的
MappingJackson2HttpMessageConverter类进行解码。只有当状态码不在200
~ 300之间时ErrorDecoder才会被调用。ErrorDecoder的作用是可以根据HTTP响应信息返回一个异常,该异常可以在调用Feign接口的地方被捕获到。我们目前就通过ErrorDecoder来使Feign接口抛出业务异常以供调用者处理。
Feign的HTTP Client
Feign在默认情况下使用的是JDK原生的URLConnection发送HTTP请求,没有连接池,但是对每个地址会保持一个长连接,即利用HTTP的
persistence connection。我们可以用Apache的HTTP Client替换Feign原始的http client, 从而获取连接池、超时时间等与性能息息相关的控制能力。Spring Cloud从
Brixtion.SR5版本开始支持这种替换,首先在项目中声明Apache
HTTP Client和
feign-httpclient依赖:
<!-- 使用Apache HttpClient替换Feign原生httpclient --> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> </dependency> <dependency> <groupId>com.netflix.feign</groupId> <artifactId>feign-httpclient</artifactId> <version>${feign-httpclient}</version> </dependency>1
2
3
4
5
6
7
8
9
10
1
2
3
4
5
6
7
8
9
10
然后在
application.properties中添加:
feign.httpclient.enabled=true1
1
总结
通过Feign, 我们能把HTTP远程调用对开发者完全透明,得到与调用本地方法一致的编码体验。这一点与阿里Dubbo中暴露远程服务的方式类似,区别在于Dubbo是基于私有二进制协议,而Feign本质上还是个HTTP客户端。如果是在用Spring Cloud Netflix搭建微服务,那么Feign无疑是最佳选择。
相关文章推荐
- 使用Spring Cloud Feign作为HTTP客户端调用远程HTTP服务的方法(推荐)
- 使用Spring Cloud Feign作为HTTP客户端调用远程HTTP服务
- 使用Spring Cloud Feign作为HTTP客户端调用远程HTTP服务
- 使用Spring Cloud Feign作为HTTP客户端调用远程HTTP服务
- 使用Spring Cloud Feign作为HTTP客户端调用远程HTTP服务
- 使用Spring Cloud Feign作为HTTP客户端调用远程HTTP服务
- 使用Spring Cloud Feign作为HTTP客户端调用远程HTTP服务
- 使用Spring Cloud Feign作为HTTP客户端调用远程HTTP服务
- 使用Spring Cloud Feign作为HTTP客户端调用远程HTTP服务
- Spring Boot 中使用Feign作为HTTP客户端调用远程HTTP服务
- Spring Cloud Feign作为HTTP客户端调用远程HTTP服务,feign熔断器
- 使用Feign作为HTTP客户端调用远程HTTP服务
- 使用Spring Cloud Feign作为HTTP客户端调用远程HTTP服务
- spring cloud 之 Feign 使用HTTP请求远程服务
- Spring Cloud 入门教程(六): 用声明式REST客户端Feign调用远端HTTP服务
- Spring Boot使用Feign客户端调用远程服务时出现:timed-out and no fallback available,failed and no fallback available的问题解决
- 使用Spring cloud Feign在后台服务之间调用传递Multipart无法传递的问题
- 关于Dalston.SR3版本的spring cloud,用feign客户端调用服务hystrix不能生效的问题
- spring boot / cloud (八) 使用RestTemplate来构建远程调用服务
- 微服务框架Spring Cloud介绍 Part4: 使用Eureka, Ribbon, Feign实现REST服务客户端