1. 日志

openFeign可以设置请求日志,在每次请求调用时输出详细的请求信息

1.设置日志级别:

#设置com.ting.order.feign包下日志级别为debug
logging:
  level:
    com.ting.order.feign: debug

2. 配置 OpenFeign 的完整请求日志输出

    @Bean
    Logger.Level feignLoggerLevel() {
        return Logger.Level.FULL;
    }

放在配置类即可

2. 超时控制

OpenFeign 调用远程服务时:

  • 超过指定时间还没返回
  • 就直接报错,不继续等待
  • 避免请求阻塞、拖垮整个服务

这就是 超时控制

  • 连接超时(connectTimeout):发起 HTTP 请求,建立连接的最大时间连不上就报错。
  • 读取超时(readTimeout):连接建立成功后,等待服务返回数据的最大时间服务处理太慢 → 超时。

OpenFeign 默认:

  • connectTimeout:10 秒
  • readTimeout:60 秒

配置方法:

spring:
  cloud:
    openfeign:
      client:
        config:
          #当前服务所有接口生效
          default:
            connect-timeout: 1000
            read-timeout: 2000
spring:
  cloud:
    openfeign:
      client:
        config:
          # 只对 servers-product 生效
          #注意这里对应的是openFeign客户端接口
          #即@FeignClient(value = "service-product")中的value
          service-product:
            connect-timeout: 1000
            read-timeout: 2000

也可以合并:

spring:
  cloud:
    openfeign:
      client:
        config:
          default:
            connect-timeout: 2000
            read-timeout: 5000
          service-product:
            connect-timeout: 1000
            read-timeout: 2000

表示除了service-product使用1秒和2秒配置,其它使用2秒和5秒配置

如果超时会返回报错信息:

Read timed out 或connect timed out,对应读取超时和连接超时

示例:

新建一个配置文件单独配置feign,注意要在application文件种使用spring.profiles.include包含feign,让其生效

3. 重试机制

OpenFeign提供了一个组件可以在远程调用失败后自动进行重试:

在配置类中把下面bean注册到spring容器中:

    @Bean
    public Retryer feignRetryer() {
        // 参数说明:
        // 1. 重试间隔(初始间隔):100ms
        // 2. 最大重试间隔:1000ms
        // 3. 最大重试次数:3次(总共会执行 1+2=3次请求),第一次请求和两次重试请求
        //注意,只有第一次重试间隔是100ms,以后每次会由之前的间隔*1.5
        //即第二次是100ms * 1.5 = 150ms,第三次则是150ms * 1.5
        //直到达到最大重试时间定格为最大重试时间即这里设置的1000ms
        return new Retryer.Default(100, 1000, 3);
    }

OpenFeign默认采用的是Retryer.NEVER.RETRY 即永不重试。

注意:即使这里设置了重试,也只会重试GET请求,防止自动重试了其它非幂等的请求造成意料之外的结果

4. 拦截器

OpenFeign提供了一套拦截器机制,可以在发送远程请求时对请求进行增强,例如携带一个令牌,也可也在接收响应时提前对响应做一个预处理,用法和springboot的拦截器相同,需要实现对应的拦截器接口:

import feign.RequestInterceptor;
import feign.RequestTemplate;
import org.springframework.stereotype.Component;

import java.util.UUID;
@Component
public class FeignRequestTokenInterceptor implements RequestInterceptor {
    @Override
    public void apply(RequestTemplate requestTemplate) {
        // 1. 添加令牌
        requestTemplate.header("Feign-Token", UUID.randomUUID().toString());

        // 2. 添加用户ID
        requestTemplate.header("userId", "1001");

        //还可以修改请求体、URL
        // requestTemplate.method("POST");
        // requestTemplate.uri("/new/url");
    }
}
package com.ting.order.interceptor;

import feign.InvocationContext;

import feign.ResponseInterceptor;
import org.springframework.stereotype.Component;

@Component
public class FeignResponseInterceptor implements ResponseInterceptor {
    @Override
    public Object intercept(InvocationContext invocationContext, Chain chain) throws Exception {
        // 调用链继续执行,拿到返回值(可能是Response,也可能是业务对象)
        Object result = chain.next(invocationContext);
        
        if (result != null) {
            System.out.println("Feign 返回业务对象:" + result.getClass().getSimpleName());
        }
        return result;
    }
}

5. Fallback 降级机制

在我们之前的代码中,如果远程请求失败了例如连接超时或者读取超时,会直接报错,有的情况,我们需要即使请求失败了业务也有数据继续运行下去,这时我们就可以使用Fallback机制,当请求失败时,返回一个预设的数据,这个数据可以是缓存的旧数据,也可以是假数据等,Fallback 不是 Feign 自带的,需要Sentinel。

1.导入依赖:

        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>

2.实现要做fallback兜底返回的feign客户端接口:

package com.ting.order.feign.fallback;

import com.ting.order.feign.ProductFeignClient;
import com.ting.product.bean.Product;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;

@Component
public class ProductFeignClientFallback implements ProductFeignClient {
    @Override
    public Product getProductById(Long id) {
        Product product = new Product();
        product.setId(666L);
        product.setPrice(new BigDecimal("636"));
        product.setProductName("xiaomi666");
        product.setNum(777);
        return product;
    }
}

3.在被实习fallback的客户端接口的@FeignClient注解里添加fallback属性并指定为实习的fallback类

package com.ting.order.feign;

import com.ting.order.feign.fallback.ProductFeignClientFallback;
import com.ting.product.bean.Product;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

@FeignClient(value = "service-product", fallback = ProductFeignClientFallback.class)
public interface ProductFeignClient {
    @GetMapping("/product/{id}")
    Product getProductById(@PathVariable("id") Long id);
}

4.添加配置

#让 OpenFeign 接口支持 Sentinel 的熔断、降级、限流功能
feign:
  sentinel:
    enabled: true

配置完成后,当ProductFeignClient 中的请求失败时就会调用ProductFeignClientFallback 中对应方法获取兜底数据返回

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐