首先加入对feign和hyStrix的依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
其次在启动类中加入对feign的支持
@EnableFeignClients
创建HelloService接口
在FeignClient注解中添加fallback,指定Hystrix熔断异常回调类HelloServiceHystrix,代码如下:
package com.tairan.chapter.feign.api;
import com.tairan.chapter.feign.api.hystrix.HelloServiceHystrix;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
@FeignClient(value = "test",fallback = HelloServiceHystrix.class)
public interface HelloService {
@RequestMapping("/hello")
String getMessage() throws Exception;
}
创建HelloServiceHystrix类
创建HelloServiceHystrix类,并实现HelloService接口,代码如下:
package com.tairan.chapter.feign.api.hystrix;
import com.tairan.chapter.feign.api.HelloService;
import org.springframework.stereotype.Component;
/**
* 当HelloService中的Feign调用失败或超时时,会调用该实现类的方法
* 需要注意的是fallback指定的类一定要添加@Component将其加入到Spring容器
*/
@Component
public class HelloServiceHystrix implements HelloService {
@Override
public String getMessage() throws Exception {
return "Get Message Failed!";
}
}
注意:fallback指定的类一定要添加@Component将其加入到Spring容器
开启Feign对Hystrix的支持
在application.yml文件中添加如下配置:
feign:
# Dalston SR1(待定)之后的版本默认关闭hystrix对feign的支持,如果想要使用fallback功能这里必须启用
hystrix:
enabled: true
运行测试:
- 启动服务注册中心tairan-spring-cloud-eureka
- 启动服务提供方tairan-spring-cloud-feign-provider
- 启动服务消费方tairan-spring-cloud-feign-consumer
- 访问tairan-spring-cloud-feign-consumer工程的/feign-hello接口,链接:http://localhost:8080/feign-hello,查看访问结果
- 关闭服务提供方tairan-spring-cloud-feign-provider
- 访问tairan-spring-cloud-feign-consumer工程的/feign-hello接口,链接:http://localhost:8080/feign-hello,查看访问结
执行4操作后,访问链接http://localhost:8080/feign-hello后,接口返回结果如下所示:
执行5操作后,访问链接http://localhost:8080/feign-hello后,接口返回结果如下所示:
feign的超时机制
目前基本使用Feign都是与ribbon结合使用的,最重要的两个超时是连接超时ConnectTimeout和读超时ReadTimeout
在Spring Cloud中使用Feign进行微服务调用分为两层:Ribbon的调用及Hystrix的调用。所以Feign的超时时间就是Ribbon和Hystrix超时时间的结合,而如果不启用Hystrix则Ribbon的超时时间就是Feign的超时时间配置,Feign自身的配置会被覆盖。
而如果开启了Hystrix,那么Ribbon的超时时间配置与Hystrix的超时时间配置则存在依赖关系,因为涉及到Ribbon的重试机制,所以一般情况下都是Ribbon的超时时间小于Hystrix的超时时间,否则会出现以下错误:
2019-07-12 11:10:20,238 397194 [http-nio-8084-exec-2] WARN o.s.c.n.z.f.r.s.AbstractRibbonCommand - The Hystrix timeout of 40000ms for the command operation is set lower than the combination of the Ribbon read and connect timeout, 80000ms.
在Ribbon超时但Hystrix没有超时的情况下,Ribbon便会采取重试机制;而重试期间如果时间超过了Hystrix的超时配置则会立即被熔断(fallback)。
下面按优先级从高到低配置
默认配置
在默认配置下,Feign的超时时间配置如下:
public class DefaultClientConfigImpl implements IClientConfig {
public static final int DEFAULT_READ_TIMEOUT = 5000;
public static final int DEFAULT_CONNECT_TIMEOUT = 2000;
从上面一看是2s和5s,但是这是个坑,因为在构造完这个类后,又使用ribbon的配置把默认配置覆盖掉了:
@Bean
@ConditionalOnMissingBean
public IClientConfig ribbonClientConfig() {
DefaultClientConfigImpl config = new DefaultClientConfigImpl();
//此处还将DefaultClientConfigImpl内部的一个属性enableDynamicProperties改成了ture
config.loadProperties(this.name);
config.set(CommonClientConfigKey.ConnectTimeout, DEFAULT_CONNECT_TIMEOUT);
config.set(CommonClientConfigKey.ReadTimeout, DEFAULT_READ_TIMEOUT);
return config;
}
ribbon全局配置:
ribbon:
ReadTimeout: 60000
ConnectTimeout: 60000
ribbon指定服务配置:
app-server为服务名
app-server:
ribbon:
ReadTimeout: 30000
ConnectTimeout: 30000
Feign全局配置
需要注意的是connectTimeout和readTimeout必须同时配置,要不然不会生效,还是以ribbon为准
feign:
client:
config:
default:
connectTimeout: 10000
readTimeout: 10000
Feign指定服务配置
和全局配置类似
feign:
client:
config:
app-server:
connectTimeout: 10000
readTimeout: 10000
hystrix指定方法配置:
hystrix.command.xxx#yyy(zzz).execution.isolation.thread.timeoutInMilliseconds=mmm
xxx:要设置的某个FeignClient的类名
yyy:方法名
zzz:参数,如果是基础类型,就直接填基础类型:String/int;如果是某个对象,就直接填对象的类名
mmm:要设置的超时时间(毫秒)
示例:
hystrix.command.HelloService#getMessage().execution.isolation.thread.timeoutInMilliseconds=10000
上述设置可以使feign的方法超时时间设置为10秒钟