【微服务之Feign】Feign

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。该做法除非一些特殊场景,不推荐使用。

猜你喜欢

转载自blog.csdn.net/qq_35789269/article/details/128571751