微服务速成-OpenFeign远程调用

快速入门使用:

引入依赖

spring-cloud-starter-openfeign

启动类加上注解:@EnableFeignclient

OpenFeign的使用和SpringMvc完全是反过来的,非常好理解,接下来我们举例说明

|------------------|---------------|---------------|---------|
| 注解 | SpringMVC | OpenFeign | 通用性 |
| @Controller | 后端页面控制器 | 不使用 | 不通用 |
| @RestController | JSON 接口控制器 | 不使用 | 不通用 |
| @RequestMapping | 定义请求路径 | 定义远程接口路径 | 通用 |
| @Get/PostMapping | 限定请求方式 | 限定远程请求方式 | 通用 |
| @RequestParam | 获取 url 参数 | 拼接查询参数 | 通用 |
| @PathVariable | 获取路径变量 | 填充路径占位符 | 通用 |
| @RequestBody | 接收 JSON 请求体 | 传递 JSON 请求体 | 通用 |

代码举例对比

SpringMVC

复制代码
@RestController
public class OrderController{

    @GetMapping("/order/{orderId}")
    public Order getOrderInfo(@PathVariable ("orderId")Long orderId){}
}

OpenFeign

注意事项:openfeign远程调用自动实现负载均衡,只要是业务相关的代码,Controller里面的代码可以直接拿到FeignClient里面用

负载均衡

服务端负载均衡:订单服务-→请求商品服务-→负载均衡调用商品服务的实例

客户端的负载均衡:多个用户点击服务-→请求到统一网关→负载均衡的分配到对应的服务器来处理请求

日志开启(openfeign默认调用远程是不输出日志的)

第一步:配置中修改日志级别

logging.level. 类的reference路径 :debug

第二步:配置bean

超时处理

防止某个服务单点长时间卡死,导致整体系统不可用

默认超时时间: 连接超时(连接服务事件):10s 读超时(业务处理事件):60s

修改默认的全局超时配置

spring.cloud.openfeign.client.config.defalt.......

对单个服务进行配置

只需要在defalut下方再起一行,写上对应的服务名称即可

测试一下,我们在productController里面让线程睡眠5秒,触发连接超时:

连接重试

复制代码
  @Configuration
public class FeignConfig {

      @Bean
      public Retryer feignRetryer() {
          // 参数:每100ms重试一次,最多等1000ms,最多重试3次
          return new Retryer.Default(100, 1000, 3);
      }
  }

RequestInterce请求拦截器:每次发送远程调用前,进行拦截

复制代码
  @Component
  public class FeignAuthInterceptor implements RequestInterceptor {

      @Override
      public void apply(RequestTemplate template) {
          // 给每个 Feign 请求加一个请求头
          template.header("Authorization", "Bearer xxx-token-xxx");

          // 或者从当前请求上下文拿 Token
          // RequestAttributes attributes = RequestContextHolder.getRequestAttributes();
          // String token = ((ServletRequestAttributes) attributes).getRequest().getHeader("Authorization");
          // template.header("Authorization", token);
      }
  }

和SpringMVC的请求拦截器的对比

复制代码
  @Component
  public class MyInterceptor implements HandlerInterceptor {

      @Override
      public boolean preHandle(HttpServletRequest request,
                               HttpServletResponse response, Object handler) {
          System.out.println("请求来了:" + request.getRequestURI());
          return true; // true = 放行,false = 拦截
      }
  }

  然后在配置类里注册才能生效:

  @Configuration
  public class WebConfig implements WebMvcConfigurer {
      @Override
      public void addInterceptors(InterceptorRegistry registry) {
          registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**");
      }
  }

远程调用的fallback兜底机制 即发生调用错误的时候

更改配置:openfeign.sentinel.enabled:true

在远程调用的注解中加上fallback

复制代码
@FeignClient(value = "service-product",fallback = ProductClientFallback.class)
public interface ProductClient {

    @GetMapping("/product")
     Product getProduct(@RequestParam Long productId);
}

编写一个类实现当前远程调用的接口

复制代码
@Component
public class ProductClientFallback implements ProductClient {
    @Override
    public Product getProduct(Long productId) {
        Product product = new Product();
        product.setId(String.valueOf(productId));
        product.setName("fallback-未知商品");
        product.setDescription("未知");
        product.setPrice(0D);
        product.setNumber(0L);
        return product;
    }
}