OpenFeign源于Netflix的Feign,是http通信的客户端。屏蔽了网络通信的细节,直接面向接口的方式开发,让开发者感知不到网络通信细节。 所有远程调用,都像调用本地方法一样完成。
Spring Cloud OpenFeign 是 Spring Cloud 对 Feign 的二次封装,它具有 Feign 的所有功能,并在 Feign 的基础上增加了对 Spring MVC 注解的支持,例如 @RequestMapping、@GetMapping 和 @PostMapping 等。
场景:在system服务远程调用product的一个接口,在单体项目一般使用httpclient或restTemplate来实现,在微服务一般使用OpenFeign来实现,OpenFeign内部已经集成了负载均衡功能,不需要我们手动实现。
前置
- 版本
- 服务端和客户端都接入了Nacos注册中心
使用
服务端代码
product服务中增加如下代码
@RestController
@Slf4j
public class ProductController {
@Autowired
private ProductService userService;
@GetMapping("/getProductById")
public String getProductById(Integer id) {
log.info("入参:{}",id);
if(id==null){
log.error("getProductById 入参为 null");
id=1;
}
return userService.getProductById(id);
}
}
调用端代码
引入POM依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
启动Feign
在启动类增加@EnableFeignClients注解
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class SystemApplication {
public static void main(String[] args) {
SpringApplication.run(SystemApplication.class, args);
}
}
增加Feign接口
@FeignClient(contextId = "remoteProductService", name = "sky-product")
public interface RemoteProductService {
@GetMapping("/product/getProductById")
String getProductById(@RequestParam("id") Integer id);
}
注入并调用
在system服务中直接注入OpenFeign接口
@Service
@Slf4j
public class UserServiceImpl implements UserService {
@Autowired
private RemoteProductService remoteProductService;
@Override
public String getUserBuy(String userId) {
//获取一个随机的整数 1-100
int intnum = new Random().nextInt(100);
return remoteProductService.getProductById(intnum);
}
}
超时时间配置
OpenFeign默认readTimeout超时时间为60s
全局配置,对所有FeignClient生效
feign:
client:
config:
default:
connectTimeout: 5000 #配置连接超时间5s
readTimeout: 10000 #配置读取超时时间10s
指定某个微服务配置超时时间
将default替换成具体微服务contextId值:即对指定微服务生效,例如cremoteProductService
feign:
client:
config:
default:
connectTimeout: 5000 #单位毫秒
readTimeout: 10000 #单位毫秒
remoteProductService: #对应feign client的contextId
connectTimeout: 5000 #单位毫秒
readTimeout: 5000 #单位毫秒
指定微服务中指定方法设置超时时间
举例:商品服务调用交易服务中的getOrderById方法经常超时,只想对这个方法设置超时时间,但是不影响全局配置超时时间。
在feign接口中增加一个Request.Options参数,示例代码如如下
@FeignClient(contextId = "remoteProductService", name = "sky-product")
public interface RemoteProductService2 {
@GetMapping("/product/getProductById")
String getProductById(@RequestParam("id") Integer id, Request.Options options);
}
然后再调用的时候传入new Request.Options参数即可
Request.Options options = new Request.Options(3, TimeUnit.SECONDS, timeOut, TimeUnit.SECONDS, true);
public String getUserBuy2(String userId) {
//获取一个随机的整数 1-100
int intnum = new Random().nextInt(100);
//超时时间设置为3秒,可以定义在配置文件中
int timeOut = 3;
Request.Options options = new Request.Options(3, TimeUnit.SECONDS, timeOut, TimeUnit.SECONDS, true);
log.info("开始执行方法");
return remoteProductService2.getProductById(intnum,options);
}