如何判断feign调用有没有存在循环调用?

在微服务架构中,Feign 调用可能会因为服务间的依赖关系导致 循环调用(即服务 A 调用服务 B,服务 B 又调用服务 A),从而引发无限递归、系统崩溃等问题。为了避免这种情况,可以通过以下方式实现 Feign 调用的循环调用检测:


1. 使用请求头传递调用链信息

通过在请求头中传递调用链信息,可以检测是否存在循环调用。

(1)实现步骤

  1. 定义调用链标识
    • 在每次 Feign 调用时,生成一个唯一的调用链标识(如 UUID),并将其添加到请求头中。
  2. 传递调用链信息
    • 在 Feign 客户端拦截器中,将调用链信息添加到请求头中。
  3. 检测循环调用
    • 在服务端拦截器中,检查请求头中的调用链信息,如果发现当前服务已经在调用链中,则抛出异常。

(2)代码示例

Feign 客户端拦截器
import feign.RequestInterceptor;
import feign.RequestTemplate;
import org.springframework.stereotype.Component;

import java.util.UUID;

@Component
public class FeignRequestInterceptor implements RequestInterceptor {
    @Override
    public void apply(RequestTemplate template) {
        // 生成调用链标识
        String callChainId = UUID.randomUUID().toString();
        // 将调用链标识添加到请求头
        template.header("Call-Chain-Id", callChainId);
    }
}
服务端拦截器
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashSet;
import java.util.Set;

public class CallChainInterceptor implements HandlerInterceptor {
    private static final ThreadLocal<Set<String>> callChainIds = ThreadLocal.withInitial(HashSet::new);

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        String callChainId = request.getHeader("Call-Chain-Id");
        if (callChainId != null) {
            Set<String> ids = callChainIds.get();
            if (ids.contains(callChainId)) {
                throw new RuntimeException("Detected cyclic call: " + callChainId);
            }
            ids.add(callChainId);
        }
        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        String callChainId = request.getHeader("Call-Chain-Id");
        if (callChainId != null) {
            Set<String> ids = callChainIds.get();
            ids.remove(callChainId);
        }
    }
}
注册拦截器
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new CallChainInterceptor());
    }
}

2. 使用分布式链路追踪工具

分布式链路追踪工具(如 ZipkinSkyWalking)可以自动记录服务调用链,并检测循环调用。

(1)实现步骤

  1. 集成链路追踪工具
    • 在项目中集成 Zipkin 或 SkyWalking,记录服务调用链。
  2. 检测循环调用
    • 在链路追踪工具中配置规则,检测是否存在循环调用。
  3. 告警与处理
    • 当检测到循环调用时,触发告警并记录日志。

(2)代码示例

集成 Zipkin

application.yml 中配置 Zipkin:

spring:
  zipkin:
    base-url: http://localhost:9411
  sleuth:
    sampler:
      probability: 1.0  # 采样率
检测循环调用

在 Zipkin 或 SkyWalking 的 UI 界面中,查看服务调用链,检查是否存在循环调用。


3. 使用服务注册中心

通过服务注册中心(如 EurekaNacos)记录服务间的依赖关系,检测循环调用。

(1)实现步骤

  1. 记录服务依赖
    • 在服务注册中心中记录每个服务的依赖关系。
  2. 检测循环调用
    • 在服务调用时,检查依赖关系是否存在循环。
  3. 告警与处理
    • 当检测到循环调用时,触发告警并记录日志。

(2)代码示例

使用 Nacos 记录依赖关系

application.yml 中配置 Nacos:

spring:
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
检测循环调用

在 Nacos 的 UI 界面中,查看服务依赖关系,检查是否存在循环调用。


4. 总结

实现 Feign 调用的循环调用检测可以通过以下方式:

  1. 请求头传递调用链信息:在请求头中传递调用链标识,检测循环调用。
  2. 分布式链路追踪工具:使用 Zipkin 或 SkyWalking 自动记录和检测循环调用。
  3. 服务注册中心:通过 Eureka 或 Nacos 记录服务依赖关系,检测循环调用。

通过以上方式,可以有效避免 Feign 调用中的循环调用问题,提升系统的稳定性和可靠性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

java干货仓库

觉得写的不错,就给博主投币吧

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值