OpenFeign
OpenFeign 提供了一种声明式的远程调用接口。
OpenFeign 的原理
使用了动态代理来封装远程服务调用的过程。
远程服务调用的信息被写在了 FeignClient 接口中。

- 扫描所有的被
@FeignClient修饰的接口 - 生成代理对象 FeignProxyService,继承第一步查找的接口。
- 注入代理对象,动态代理对象会被添加到 spring 上下文中,并注入到对应的服务里。
- 调用远程服务,由代理对象发起一个远程服务调用。

OpenFeign 集成
maven 引入 org.springframework.cloud.spring-cloud-starter-openfeign
@FeignClient 标记被 OpenFeign 托管的接口。
- value 目标服务的名词(需要与 Nacos 服务器上显示的服务注册名称是一样的)
- ptah 可选项,前置访问路径。
OpenFeign 接口中定义的路径和参数必须与你要调用的目标服务中的保持一致。
OpenFeign 不光可以提高代码可读性和可维护性,还降低了远程调用的 Coding 成本。
@EnableFeignClients 用于配置要扫描 @FeignClient 注解的包。
OpenFeign 进阶使用
1. 异常信息排查
修改 @OpenFeign 所在接口的日志等级。因为 OpenFeign 组件默认将日志以 debug 模式输出。
logging:
level:
com.broadview.coupon: info
com.geekbang.coupon.customer.feign.TemplateService: debug
com.geekbang.coupon.customer.feign.CalculationService: debug
声明 Feign 组件的日志级别(这个是 OpenFeign 组件自定义的一种日志级别,用来控制 OpenFeign 组件向日志中写入什么内容。)。
OpenFeign 的日志级别有 4 个
- NONE 不记录任何信息
- BASIC 只记录 url,http method,状态码,服务调用时间。
- HEADERS 在 BASIC 基础上增加了请求和响应的 HTTP Headers
- FULL 全部信息,body,metadata
@Bean
Logger.Level feignLogger() {
// NONE, BASIC, HEADERS, FULL
return Logger.Level.FULL;
}
2. 超时判定
如果请求处于一个长时间挂起的状态,可能会造成服务雪崩,即一个服务失败,导致整条链路的服务都失败的情形。
可以设置一个超时判定的阈值,响应时间超过这个阈值,程序会自动取消这次调用,并返回一个异常。
- connectTimeout 建立网络连接阶段
- readTimeout 服务请求响应阶段
feign:
client:
config:
default: # 全局层面,对所有的 OpenFeign 发起的远程调用生效。
connectTimeout: 1000
readTimeout: 2000
coupon-template-serv: # 只针对指定服务 的 OpenFeign 发起的远程调用生效
connectTimeout: 1000
readTimeout: 1500
3. 服务降级
服务降级指的是在远程服务调用超时或者异常时,自动执行一段业务逻辑(如执行一段兜底逻辑将服务请求从失败状态中恢复或发送一个失败通知到相关团队提醒他们来线上排查问题)。
比较知名的组件有 Sentinel, Hystrix(SpringCloud 已废除)。 Sentinel 这个就比较重量级了。对于一些简单的服务降级可以使用 OpenFeign 来实现。
OpenFeign 的服务降级使用的是 Hystrix,因为其已经在 springcloud 中被移除,所以需要通过 maven 手动引入
<!-- hystrix组件,专门用来演示openfeign降级 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
<version>2.2.10.RELEASE</version>
<exclusions>
<!-- 移除Ribbon负载均衡器 -->
<exclusion>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix-ribbon</artifactId>
</exclusion>
</exclusions>
</dependency>
编写好 OpenFeign 的降级类,有 2 种方式
- fallback 方式,指定一个类,这个类需要使用 feign 接口
- fallback 工厂方式,指定一个工厂类,这个工厂类需要实现
FallbackFactory接口
@FeignClient(value = "coupon-template-serv", path = "/template",
// fallback = TemplateServiceFallback.class,
fallbackFactory = TemplateServiceFallbackFactory.class)
public interface TemplateService {
// 读取优惠券
@GetMapping("/getTemplate")
CouponTemplateInfo getTemplate(@RequestParam("id") Long id);
// 批量获取
@GetMapping("/getBatch")
Map<Long, CouponTemplateInfo> getTemplateInBatch(@RequestParam("ids") Collection<Long> ids);
}