1、Feign简介
Feign is a declarative web service client. It makes writing web service clients easier. To use Feign create an interface and annotate it. It has pluggable annotation support including Feign annotations and JAX-RS annotations. Feign also supports pluggable encoders and decoders. Spring Cloud adds support for Spring MVC annotations and for using the sameHttpMessageConverters used by default in Spring Web. Spring Cloud integrates Ribbon and Eureka to provide a load balanced http client when using Feign.这是官网API中的介绍,主要是说Feign是一个声明式的web 服务客户端;它支持可插拔的注解,包含Feign注解和JAX-RS注解;并且支持可插拔的编码、解码;Spring Cloud增加了对Spring MVC注解的集成;Feign集成了Ribbon和Eureka来提供对http客户端的负载均衡。
说到Feign的功能是负载均衡,那必须和前一章的Ribbon进行比较一下:
2、下面是用实例来说明:
pom:
<!-- fegin相关 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-feign</artifactId> </dependency> |
代码:
//@FeignClient(value="MICROSERVICECLOUD1-DEPT") 值开启这个就表示只有Feign来用,负载均衡服务名称为“MICROSERVICECLOUD1-DEPT”, @FeignClient(value="MICROSERVICECLOUD1-DEPT",fallbackFactory=DeptClientServiceFallbackFactory.class)下面这个注解和Feign与Hystrix结合在一起使用的,也需要在yml里面开启(feign.hystrix. enabled: true) public interface DeptClientService { @RequestMapping(value="/dept/add",method=RequestMethod.POST) public boolean add(@RequestBody Dept dept); @RequestMapping(value="/dept/get/{id}",method=RequestMethod.GET) public Dept get(@PathVariable("id") Long id); @RequestMapping(value="/dept/list",method=RequestMethod.GET) public List<Dept> list(); } | @SpringBootApplication @EnableEurekaClient @EnableFeignClients(basePackages="com.jrj.springcloud") @ComponentScan(basePackages="com.jrj.springcloud") public class DeptConsumerFegin_App { public static void main(String[] args) { SpringApplication.run(DeptConsumerFegin_App.class, args); } } |
@Autowired private DeptClientService service; @RequestMapping(value = "/consumer/dept/add", method = RequestMethod.POST) public boolean add(@RequestBody Dept dept) { return service.add(dept); } | /** * 千万不要忘记在类上面新增@Component注解,大坑!!! 这个是那个Hystrix有关系 */@Component public class DeptClientServiceFallbackFactory implements FallbackFactory<DeptClientService>{ @Override public DeptClientService create(Throwable cause) { return new DeptClientService(){ @Override public boolean add(Dept dept) { return false; } @Override public Dept get(Long id) { return new Dept().setDeptno(id).setDname("服务正在降级处理").setDb_source("no this database mysql"); } @Override public List<Dept> list() { return null; } }; } } |
需要注意的是:
fegin的两个坑是不支持:
1、不支持@GetMapping这个注解
2、还有就是@PathVariable("id")Integer id 必须这样写,不能写成 @PathVariable Integer id
3、如果请求参数是复杂对象,即使指定了是get方法,fegin依然会以post方法进行发送。
在访问这个项目的时候可能会出现,timeout超时异常:null
原因是fegin集成了hystrix,他默认的时间是1秒钟,
我们可以通过设置这个就可以解决这个问题:把时间设置长一点
hystrix.command.default.execution.isolation.timeoutInMillseconds:
或者:
hystrix.command.default.execution.timeout.enabled:false
或者:
fegin.hystrix.enabled:false fegin禁用hytrix
|
3、Feign的一写其他操作
3.1、覆盖Feign默认值
3.2、手动创建Feign客户端
3.3、Feign Hystrix支持
如果Hystrix在类路径上,feign.hystrix.enabled=true
,Feign将用断路器包装所有方法。还可以返回com.netflix.hystrix.HystrixCommand
。这样就可以使用无效模式(调用.toObservable()
或.observe()
或异步使用(调用.queue()
))。
要在每个客户端基础上禁用Hystrix支持创建一个带有“原型”范围的香草Feign.Builder
,例如:
@Configuration
public class FooConfiguration {
@Bean
@Scope("prototype")
public Feign.Builder feignBuilder() {
return Feign.builder();
}
}
警告
| 在Spring Cloud达尔斯顿发布之前,如果Hystrix在类路径Feign中默认将所有方法包装在断路器中。这种默认行为在Spring Cloud达尔斯顿改变了赞成选择加入的方式。 |
3.4、Feign Hystrix回退
Hystrix支持回退的概念:当电路断开或出现错误时执行的默认代码路径。要为给定的@FeignClient
启用回退,请将fallback
属性设置为实现回退的类名。
@FeignClient(name = "hello", fallback = HystrixClientFallback.class)
protected interface HystrixClient {
@RequestMapping(method = RequestMethod.GET, value = "/hello")
Hello iFailSometimes();
}
static class HystrixClientFallback implements HystrixClient {
@Override
public Hello iFailSometimes() {
return new Hello("fallback");
}
}
如果需要访问导致回退触发的原因,可以使用@FeignClient
内的fallbackFactory
属性。
@FeignClient(name = "hello", fallbackFactory = HystrixClientFallbackFactory.class)
protected interface HystrixClient {
@RequestMapping(method = RequestMethod.GET, value = "/hello")
Hello iFailSometimes();
}
@Component
static class HystrixClientFallbackFactory implements FallbackFactory<HystrixClient> {
@Override
public HystrixClient create(Throwable cause) {
return new HystrixClientWithFallBackFactory() {
@Override
public Hello iFailSometimes() {
return new Hello("fallback; reason was: " + cause.getMessage());
}
};
}
}
警告
| 在Feign中执行回退以及Hystrix回退的工作方式存在局限性。当前返回com.netflix.hystrix.HystrixCommand 和rx.Observable 的方法目前不支持回退。 |
3.4.1Feign和@Primary
当使用Feign与Hystrix回退时,在同一类型的ApplicationContext
中有多个bean。这将导致@Autowired
不起作用,因为没有一个bean,或者标记为主。要解决这个问题,Spring Cloud Netflix将所有Feign实例标记为@Primary
,所以Spring Framework将知道要注入哪个bean。在某些情况下,这可能是不可取的。要关闭此行为,将@FeignClient
的primary
属性设置为false。
@FeignClient(name = "hello", primary = false)
public interface HelloClient {
// methods here
}
3.5、Feign继承支持
Feign通过单继承接口支持样板apis。这样就可以将常用操作分成方便的基本界面。
public interface UserService {
@RequestMapping(method = RequestMethod.GET, value ="/users/{id}")
User getUser(@PathVariable("id") long id);
}
@RestController
public class UserResource implements UserService {
}
package project.user;
@FeignClient("users")
public interface UserClient extends UserService {
}
注意
| 通常不建议在服务器和客户端之间共享接口。它引入了紧耦合,并且实际上并不适用于当前形式的Spring MVC(方法参数映射不被继承)。 |
3.6、Feign请求/响应压缩
您可以考虑为Feign请求启用请求或响应GZIP压缩。您可以通过启用其中一个属性来执行此操作:
feign.compression.request.enabled=true
feign.compression.response.enabled=true
Feign请求压缩为您提供与您为Web服务器设置的设置相似的设置:
feign.compression.request.enabled=true
feign.compression.request.mime-types=text/xml,application/xml,application/json
feign.compression.request.min-request-size=2048
这些属性可以让您对压缩介质类型和最小请求阈值长度有选择性。
3.7、Feign日志记录
为每个创建的Feign客户端创建一个记录器。默认情况下,记录器的名称是用于创建Feign客户端的接口的完整类名。Feign日志记录仅响应DEBUG
级别。
logging.level.project.user.UserClient: DEBUG
您可以为每个客户端配置的Logger.Level
对象告诉Feign记录多少。选择是:
NONE
,无记录(DEFAULT)。BASIC
,只记录请求方法和URL以及响应状态代码和执行时间。HEADERS
,记录基本信息以及请求和响应标头。FULL
,记录请求和响应的头文件,正文和元数据。
参考文章有如下:
https://blog.csdn.net/jeson0725/article/details/70226292
http://www.ccblog.cn/97.htm