Openfeign的使用
-
简单实例
Openfeign的使用和feign几乎没有区别,以下为使用Openfeign + springboot(2.4.2版本) + nacos实现跨服务远程调用的一个实例:
- 添加pom依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>3.0.1</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
<version>3.0.1</version>
</dependency>
2. Application启动类上添加注解
- 创建调用接口
@RequestMapping("/user/orders")
// 调用接口的服务名
@FeignClient(name = "orders-service")
public interface UserOrdersService {
//调用的接口url
@GetMapping("list/{userId}")
//调用的接口,参数与被调用方一致
String getUserOrdersByUserId(@PathVariable String userId);
}
4. 写好之后不需要写实现接口,你就可以在其他地方像调用本地接口一样调用
5.此时接口调用已经能够看到结果:
-
添加熔断器
以上一个简单的Openfeign跨服务调用就写好了,但是当被调用的服务出错或无法访问时,往往需要给被调用服务降级,此时需要添加熔断器
- 引入pom包
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
<version>2.2.10.RELEASE</version>
</dependency>
// hystrix已停止更新进入维护,推荐使用spring-cloud-starter-circuitbreaker-resilience4j进行替代,但是我本地跑了会报错,还没解决,暂时使用hystrix
- yml文件添加:
feign:
//hystrix版本问题,有些可能是使用hystrix进行配置,当hystrix不生效时可使用circuitbreaker替代
# hystrix:
# enabled: true
circuitbreaker:
enabled: true
3. 这里有两种方式写熔断:fallback和fallbackfactory
- fallback
写一个@FeignClient的实现类,并在@FeignClient中配置fallback
@Component
public class UserOrdersFallback implements UserOrdersService{
@Override
public String getUserOrdersByUserId(String userId) {
return "暂时找不到服务";
}
}
- fallbackFactory(可以获取到异常信息,推荐使用)
写一个FallbackFactory接口实现类,并在@FeignClient中配置fallbackFactory
@Component
public class UserOrdersFallback implements FallbackFactory<UserOrdersService> {
@Override
public UserOrdersService create(Throwable cause) {
return new UserOrdersService() {
@Override
public String getUserOrdersByUserId(String userId) {
return "现在用这个";
}
};
}
}
配置好之后,当调用的接口发生异常后,就会走到实现类的方法中进行业务处理
-
操作过程中遇到的问题
网上查询说是URL重复,不能在@feignClient的接口上写@requestMapper,需要改成:
@RequestMapping("/user/orders")
@FeignClient(name = "orders-service")
public interface UserOrdersService {
@GetMapping("list/{userId}")
String getUserOrdersByUserId(@PathVariable String userId);
}
改成下面的:
@FeignClient(name = "orders-service")
public interface UserOrdersService {
@GetMapping("/user/orders/list/{userId}")
String getUserOrdersByUserId(@PathVariable String userId);
}