SOFA RPC是如何用责任链模式实现调用链的

SOFA RPC是如何用责任链模式实现调用链的

在 SOFA RPC 框架中,责任链模式是实现调用链(Filter Chain)的核心机制,它通过将多个过滤器(Filter)串联成链,使请求在被处理前后依次经过每个过滤器,实现横切逻辑的解耦和复用。以下是其实现原理的详细说明:

1. 责任链模式的核心结构

SOFA RPC 通过三个关键组件实现责任链模式:

1.1 Filter 接口

定义拦截逻辑,通过invoke方法连接下一个处理节点:

public interface Filter {
    // 处理请求并调用下一个节点
    SofaResponse invoke(Invoker next, SofaRequest request) throws SofaRpcException;
    
    // 可选:处理响应(默认实现为空)
    default SofaResponse onResponse(SofaResponse response, Invoker invoker, SofaRequest request) {
        return response;
    }
}
1.2 Invoker 接口

定义服务调用的基本行为,是责任链中节点的抽象:

public interface Invoker {
    // 执行请求并返回响应
    SofaResponse invoke(SofaRequest request) throws SofaRpcException;
}
1.3 FilterInvoker 类

连接FilterInvoker的桥梁,将过滤器包装为责任链的节点,链的最后一个节点通常是 ConsumerInvoker(客户端)或 ProviderInvoker(服务端),负责执行真正的调用逻辑。:

@ThreadSafe
public class FilterInvoker implements Invoker {
    protected Filter nextFilter;
    protected FilterInvoker invoker;
    protected AbstractInterfaceConfig config;

    public FilterInvoker(Filter nextFilter, FilterInvoker invoker, AbstractInterfaceConfig config) {
        this.nextFilter = nextFilter;
        this.invoker = invoker;
        this.config = config;
    }

    @Override
    public SofaResponse invoke(SofaRequest request) throws SofaRpcException {
        if (nextFilter == null && invoker == null) {
            throw new SofaRpcException(RpcErrorType.SERVER_FILTER,
                LogCodes.getLog(LogCodes.ERROR_NEXT_FILTER_AND_INVOKER_NULL));
        }
        return nextFilter == null ?
            invoker.invoke(request) :
            nextFilter.invoke(invoker, request);
    }
}
1.4 ConsumerInvoker 类

ConsumerInvoker 是责任链中的最后一个调用者,负责实际的客户端调用。它会调用 ConsumerBootstrapcluster 发送消息到服务端。

@Override
public SofaResponse invoke(SofaRequest sofaRequest) throws SofaRpcException {
    RpcInvokeContext.getContext().put(RpcConstants.INTERNAL_KEY_CONSUMER_INVOKE_START_TIME_NANO, System.nanoTime());
    // 设置下服务器应用
    ProviderInfo providerInfo = RpcInternalContext.getContext().getProviderInfo();
    String appName = providerInfo.getStaticAttr(ProviderInfoAttrs.ATTR_APP_NAME);
    if (StringUtils.isNotEmpty(appName)) {
        sofaRequest.setTargetAppName(appName);
    }

    // 目前只是通过client发送给服务端
    SofaResponse sofaResponse = consumerBootstrap.getCluster().sendMsg(providerInfo, sofaRequest);
    RpcInvokeContext.getContext().put(RpcConstants.INTERNAL_KEY_CONSUMER_INVOKE_END_TIME_NANO, System.nanoTime());
    return sofaResponse;
}
1.5 ProviderInvoker 类

ProviderInvoker 用于服务端调用业务实现类。它会反射调用业务代码,并处理可能出现的异常。

public class ProviderInvoker<T> extends FilterInvoker {
    private final ProviderConfig<T> providerConfig;

    public ProviderInvoker(ProviderConfig<T> providerConfig) {
        super(providerConfig);
        this.providerConfig = providerConfig;
    }

    @Override
    public SofaResponse invoke(SofaRequest request) throws SofaRpcException {
        SofaResponse sofaResponse = new SofaResponse();
        try {
            // 反射 真正调用业务代码
            Method method = request.getMethod();
            if (method == null) {
                throw new SofaRpcException(RpcErrorType.SERVER_FILTER,
                    LogCodes.getLog(LogCodes.ERROR_NEED_DECODE_METHOD));
            }
            Object result = method.invoke(providerConfig.getRef(), request.getMethodArgs());
            sofaResponse.setAppResponse(result);
        } catch (Exception e) {
            sofaResponse.setErrorMsg(e.getMessage());
        } finally {
            // 记录业务处理时间
            RpcInvokeContext.getContext().put(RpcConstants.INTERNAL_KEY_PROVIDER_INVOKE_END_TIME_NANO, System.nanoTime());
        }
        return sofaResponse;
    }
}

2. 责任链的构建过程

2.1 过滤器链的初始化

FilterChain 是过滤器链的管理者,它会根据配置选择合适的过滤器,并将它们包装成 FilterInvoker 对象,按顺序构建调用链。在 invoke 方法中,它会调用调用链的头部 FilterInvoker 来开始处理请求。

ublic class FilterChain implements Invoker {
    private FilterInvoker invokerChain;
    private List<Filter> loadedFilters;

    @Override
    public SofaResponse invoke(SofaRequest sofaRequest) throws SofaRpcException {
        return invokerChain.invoke(sofaRequest);
    }
}
2.2 客户端调用链示例

客户端的调用链通常包含多个过滤器(如日志、超时控制),最终连接到ConsumerInvoker

// 构建客户端过滤器链
Invoker clientChain = FilterChain.buildConsumerChain(
    consumerConfig,  // 消费者配置
    new ConsumerInvoker(consumerBootstrap)  // 末端 Invoker,负责实际调用
);

// 客户端发起调用时
SofaResponse response = clientChain.invoke(request);  // 从链头开始执行

3. 责任链的执行流程

  1. 请求进入链头:客户端调用链头的FilterInvoker
  2. 过滤器前置处理:每个FilterInvoker调用其包装的Filterinvoke方法,过滤器可以在调用next.invoke(request)之前添加自定义逻辑。
  3. 传递至下一个节点Filter通过next.invoke(request)将请求传递给下一个Invoker(可能是另一个FilterInvoker或末端ConsumerInvoker)。
  4. 末端节点处理:最终的ConsumerInvoker执行实际的服务调用(如网络传输)。
  5. 响应返回:响应沿原路返回,每个过滤器可以在响应返回时执行后置逻辑。

4. 服务端责任链示例

服务端的责任链类似,但末端是ProviderInvoker,负责反射调用业务实现类:

// 服务端过滤器链构建
Invoker serverChain = FilterChain.buildProviderChain(
    providerConfig,  // 提供者配置
    new ProviderInvoker(providerConfig)  // 末端 Invoker,负责反射调用业务方法
);

// 服务端接收到请求时
SofaResponse response = serverChain.invoke(request);  // 从链头开始执行

5. 责任链模式的优势

  1. 解耦核心逻辑与扩展逻辑
    • 核心调用逻辑(如网络传输、反射调用)由ConsumerInvoker/ProviderInvoker实现。
    • 横切逻辑(如日志、权限)由过滤器实现,不侵入核心代码。
  2. 高扩展性
    • 新增功能只需添加新的过滤器,无需修改现有代码。
    • 过滤器可以通过配置灵活启用或禁用。
  3. 灵活排序
    • 过滤器的执行顺序可以通过配置调整,适应不同场景需求。
  4. 可复用性
    • 同一个过滤器可以在客户端和服务端的不同链中复用。

总结

SOFA RPC 通过责任链模式实现调用链的核心机制是:

  • Filter 接口定义拦截逻辑,通过invoke(next, request)方法连接下一个处理节点。
  • FilterInvoker 类作为责任链的节点,包装Filter并持有下一个Invoker的引用。
  • FilterChain 类负责按配置顺序构建过滤器链,将多个FilterInvoker串联成完整的调用链。

这种设计使 SOFA RPC 能够在不修改核心代码的前提下,通过插件化的过滤器灵活扩展功能,是实现框架高扩展性的关键机制之一。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值