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 类
连接Filter
和Invoker
的桥梁,将过滤器包装为责任链的节点,链的最后一个节点通常是 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
是责任链中的最后一个调用者,负责实际的客户端调用。它会调用 ConsumerBootstrap
的 cluster
发送消息到服务端。
@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. 责任链的执行流程
- 请求进入链头:客户端调用链头的
FilterInvoker
。 - 过滤器前置处理:每个
FilterInvoker
调用其包装的Filter
的invoke
方法,过滤器可以在调用next.invoke(request)
之前添加自定义逻辑。 - 传递至下一个节点:
Filter
通过next.invoke(request)
将请求传递给下一个Invoker
(可能是另一个FilterInvoker
或末端ConsumerInvoker
)。 - 末端节点处理:最终的
ConsumerInvoker
执行实际的服务调用(如网络传输)。 - 响应返回:响应沿原路返回,每个过滤器可以在响应返回时执行后置逻辑。
4. 服务端责任链示例
服务端的责任链类似,但末端是ProviderInvoker
,负责反射调用业务实现类:
// 服务端过滤器链构建
Invoker serverChain = FilterChain.buildProviderChain(
providerConfig, // 提供者配置
new ProviderInvoker(providerConfig) // 末端 Invoker,负责反射调用业务方法
);
// 服务端接收到请求时
SofaResponse response = serverChain.invoke(request); // 从链头开始执行
5. 责任链模式的优势
- 解耦核心逻辑与扩展逻辑:
- 核心调用逻辑(如网络传输、反射调用)由
ConsumerInvoker
/ProviderInvoker
实现。 - 横切逻辑(如日志、权限)由过滤器实现,不侵入核心代码。
- 核心调用逻辑(如网络传输、反射调用)由
- 高扩展性:
- 新增功能只需添加新的过滤器,无需修改现有代码。
- 过滤器可以通过配置灵活启用或禁用。
- 灵活排序:
- 过滤器的执行顺序可以通过配置调整,适应不同场景需求。
- 可复用性:
- 同一个过滤器可以在客户端和服务端的不同链中复用。
总结
SOFA RPC 通过责任链模式实现调用链的核心机制是:
- Filter 接口定义拦截逻辑,通过
invoke(next, request)
方法连接下一个处理节点。 - FilterInvoker 类作为责任链的节点,包装
Filter
并持有下一个Invoker
的引用。 - FilterChain 类负责按配置顺序构建过滤器链,将多个
FilterInvoker
串联成完整的调用链。
这种设计使 SOFA RPC 能够在不修改核心代码的前提下,通过插件化的过滤器灵活扩展功能,是实现框架高扩展性的关键机制之一。