Feign 是一个声明web服务客户端,这使得编写web服务客户端更容易,使用Feign 创建一个接口并对它进行注解,它具有可插拔的注解支持包括Feign注解与JAX-RS注解,Feign还支持可插拔的编码器与解码器,Spring Cloud 增加了对 Spring MVC的注解,Spring Web 默认使用了HttpMessageConverters, Spring Cloud 集成 Ribbon 和 Eureka 提供的负载均衡的HTTP客户端 Feign.简单来说就是:像调本地方法一样调用远程方法,但是注意这个不是RPC。可以看作一个低阶的RPC。
平时使用rest请求是这样的
@GetMapping("/buy/{id}")
public Product order() {
Product product = restTemplate.getForObject("http://shop-service-product/product/1", Product.class);
return product;
}
由代码可知,我们是使用拼接字符串的方式构造URL的,该URL只有一个参数。但是,在现实中,URL 中往往含有多个参数。这时候我们如果还用这种方式构造URL,特别是在微服务架构下,如何快速进行编写代码,而不用费心去构建http客户端,所有有了声明式,模板化的HTTP客户端。
Feign是Netflix开发的声明式,模板化的HTTP客户端,其灵感来自Retrofit,JAXRS-2.0以及WebSocket.
Feign可帮助我们更加便捷,优雅的调用HTTP API。
在SpringCloud中,使用Feign非常简单——创建一个接口,并在接口上添加一些注解,代码就完 成了。
Feign支持多种注解,例如Feign自带的注解或者JAX-RS注解等。
SpringCloud对Feign进行了增强,使Feign支持了SpringMVC注解,并整合了Ribbon和Eureka, 从而让Feign的使用更加方便。
基于Feign的服务调用
在服务消费者 shop_service_order 添加Fegin依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>。
(2)启动类添加Feign的支持
@SpringBootApplication(scanBasePackages="cn.itcast.order")
@EntityScan("cn.itcast.entity")
@EnableFeignClients
public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class, args);
}
}
通过@EnableFeignClients注解开启Spring Cloud Feign的支持功能
(3)启动类激活FeignClient
创建一个Feign接口,此接口是在Feign中调用微服务的核心接口
在方法提供侧,添加一个 ProductFeginClient 接口(可以不提供实现,这个接口必须和调用者共享),并提供一个findById方法,供外部进行调用, @FeignClient里的名称为Eureka里注册的需要调用的服务名称
//指定需要调用的微服务名称
@FeignClient(name="shop-service-product")
public interface ProductFeginClient {
//调用的请求路径
@RequestMapping(value = "/product/{id}",method = RequestMethod.GET)
public Product findById(@PathVariable("id") Long id);
}
定义各参数绑定时,@PathVariable、@RequestParam、@RequestHeader等可以指定参数属 性,在Feign中绑定参数必须通过value属性来指明具体的参数名,不然会抛出异常
@FeignClient:注解通过name指定需要调用的微服务的名称,用于创建Ribbon的负载均衡器。 所以Ribbon会把 shop-service-product 解析为注册中心的服务。
(4)配置请求提供者的调用接口
修改 OrderController ,添加ProductFeginClient的自动注入,并在order方法中使用 ProductFeginClient 完成微服务调用
@RestController
@RequestMapping("/order")
public class OrderController {
@Autowired
private ProductFeginClient productFeginClient;
@GetMapping("/buy/{id}")
public Product order(@PathVariable Long id) {
return productFeginClient.findById(id);
}
}
可以看到,使用feign之后,我们调用eureka 注册的其他服务,在代码中就像各个service之间相互调用那么简单。
FeignClient注解的一些属性
@FeignClient标签的常用属性如下:
name/value:指定FeignClient的名称,如果项目使用了Ribbon,name属性会作为微服务的名称,用于服务发现
contextId:指定beanID
url: url一般用于调试,可以手动指定@FeignClient调用的地址
decode404:当发生http 404错误时,如果该字段位true,会调用decoder进行解码,否则抛出FeignException
configuration: Feign配置类,可以自定义Feign的Encoder、Decoder、LogLevel、Contract
fallback: 定义容错的处理类,当调用远程接口失败或超时时,会调用对应接口的容错逻辑,fallback指定的类必须实现@FeignClient标记的接口
fallbackFactory: 工厂类,用于生成fallback类示例,通过这个属性我们可以实现每个接口通用的容错逻辑,减少重复的代码
path: 定义当前FeignClient的统一前缀
注意:当前工程中有和Feign Client中一样的Endpoint时,Feign Client的类上不能用@RequestMapping注解否则,当前工程该endpoint http请求且使用accpet时会报404
Feign请求超时问题
Hystrix默认的超时时间是1秒,如果超过这个时间尚未响应,将会进入fallback代码。而首次请求往往会比较慢(因为Spring的懒加载机制,要实例化一些类),这个响应时间可能就大于1秒了解决方案有三种,以feign为例。
方法一
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds: 5000该配置是让Hystrix的超时时间改为5秒
方法二
hystrix.command.default.execution.timeout.enabled: false该配置,用于禁用Hystrix的超时时间
方法三
feign.hystrix.enabled: false该配置,用于索性禁用feign的hystrix。该做法除非一些特殊场景,不推荐使用。