OpenFeign是Netflix在Feign的基础上开发的声明式、模板化的HTTP请求客户端,支持了Spring MVC的注解,如@RequesMapping等等。 OpenFeign的@FeignClient可以解析SpringMVC的@RequestMapping注解下的接口, 并通过动态代理的方式产生实现类,实现类中做负载均衡,并且可以更加便捷、优雅地调用其他http api服务。
OpenFeign会根据带有注解的函数信息构建出网络请求的模板,在发送网络请求之前,OpenFeign会将函数的参数值设置到这些请求模板中。
feign主要是构建微服务消费端。只要使用OpenFeign提供的注解修饰定义网络请求的接口类,就可以使用该接口的实例发送RESTful的网络请求。还可以集成Ribbon和Hystrix,提供负载均衡和断路器。
通过学习Eureka我们发现,在服务消费方想要调用服务提供方的API,需要通过RestTemplate,并传入一个URI参数。这种方式看起来并不和谐,在后期服务提供方出现接口变动时
主要功能
- 可插拔的注解支持,包括Feign注解和JAX-RS注解。
- 支持可插拔的HTTP编码器和解码器(Gson,Jackson,Sax,JAXB,JAX-RS,SOAP)。
- 支持Hystrix和它的Fallback。
- 支持Ribbon的负载均衡。
- 支持HTTP请求和响应的压缩。
- 灵活的配置:基于 name 粒度进行配置
- 支持多种客户端:JDK URLConnection、apache httpclient、okhttp,ribbon)
- 支持日志
- 支持错误重试
- url支持占位符
- 可以不依赖注册中心独立运行
OpenFeign配置
pom.xml配置
服务消费方的pom中需要添加OpenFeign依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
启动类配置
启动类中需要添加 @EnableFeignClients 注解
添加接口声明
添加与服务提供方保持一致的接口类,需要注意的是不能在类声明中添加 @RequestMapping 注解,需要在每个方法上写全映射URI,否则会在启动时报错,这里有可能是OpenFeign的bug。
@FeignClient(name="${service.name}")
public interface UserServiceApi {
@GetMapping("${api.user}/{id}")
Map<String, String> getUserById(@PathVariable("id")String id);
@PostMapping("${api.user}")
Map<String, String> addUser(@RequestBody Map<String, String> map);
}
通过接口调用服务
在服务消费方的类中,通过以下方式调用:
@Autowired
UserServiceApi userApi;
@GetMapping("${api.user}/{id:.+}")
public Map<String, String> getUserById(@PathVariable("id")String id) {
// 此处为示例,根据业务添加实际代码
return userApi.getUserById(id);
}
其他配置
压缩
服务端provider配置
#服务端开启压缩
server.compression.enabled=true
调用方consumer配置
#配置请求GZIP压缩
feign.compression.request.enabled=true
#配置响应GZIP压缩
feign.compression.response.enabled=true
#单位是B
feign.compression.request.min-request-size=100
超时
Feign默认支持Ribbon;Ribbon的重试机制和Feign的重试机制有冲突,所以源码中默认关闭Feign的重试机制,使用Ribbon的重试机制
#连接超时时间(ms)
ribbon.ConnectTimeout=1000
#业务逻辑超时时间(ms)
ribbon.ReadTimeout=6000
重试
#同一台实例最大重试次数,不包括首次调用
ribbon.MaxAutoRetries=1
#重试负载均衡其他的实例最大重试次数,不包括首次调用
ribbon.MaxAutoRetriesNextServer=1
#是否所有操作都重试
ribbon.OkToRetryOnAllOperations=false
使用ribbon重试机制,请求失败后,每隔6秒会重新尝试