Silky微服务框架在线文档Silky微服务框架在线文档
首页
文档
配置
源码解析
博文
github
gitee
首页
文档
配置
源码解析
博文
github
gitee
  • 启动时

    • 主机的构建
    • 服务引擎
    • 模块
    • 服务与服务条目的解析
    • Silky服务主机
    • 依赖注入约定
    • RPC 服务代理
  • 运行时

    • 终结点与路由
    • 执行器与调度
    • 本地执行器与服务端过滤器
    • 远程执行器与 RPC 调用
    • RPC 服务端消息处理
    • 服务治理
    • 缓存拦截器
    • 分布式事务(TCC)
    • HTTP 网关请求管道
    • 过滤器执行管道
    • Polly 弹性策略管道
    • 端点健康监控

概述

silky 框架的 RPC 过滤器管道设计参考了 ASP.NET Core MVC 的过滤器系统,通过状态机驱动各类型过滤器按固定顺序执行。框架在服务端(LocalInvoker)和客户端(RemoteInvoker)分别维护独立的过滤器管道。

本文聚焦于过滤器管道的运行时执行机制,说明各组件如何协作、过滤器的执行顺序和短路规则。


过滤器类型体系

服务端过滤器接口

接口执行时机说明
IServerAuthorizationFilter / IAsyncServerAuthorizationFilter最早,Action 执行之前鉴权过滤器,可通过设置 Result 短路整个管道
IServerExceptionFilter / IAsyncServerExceptionFilter异常发生后捕获并处理 Action 或 ResultFilter 抛出的异常
IServerFilter / IAsyncServerFilterAction 执行前后通用 Action 过滤器,可在执行前短路
IServerResultFilter / IAsyncServerResultFilterResult 写出前后可修改或替换执行结果
IAlwaysRunServerResultFilter / IAsyncAlwaysRunServerResultFilter无论是否短路,始终执行用于清理等保证执行的操作

客户端过滤器接口

与服务端对称,前缀替换为 Client:

接口说明
IClientFilter / IAsyncClientFilter客户端 Action 过滤器
IClientExceptionFilter / IAsyncClientExceptionFilter客户端异常过滤器
IClientResultFilter / IAsyncClientResultFilter客户端结果过滤器
IAlwaysRunClientResultFilter始终执行的客户端结果过滤器

自定义过滤器的方式

继承 ServerFilterAttribute 或 ClientFilterAttribute(均实现了对应的同步 + 异步接口),重写所需方法:

[AttributeUsage(AttributeTargets.Interface | AttributeTargets.Method,
    AllowMultiple = true, Inherited = true)]
public class TimingServerFilter : ServerFilterAttribute
{
    private Stopwatch _sw;

    public override void OnActionExecuting(ServerInvokeExecutingContext context)
    {
        _sw = Stopwatch.StartNew();
    }

    public override void OnActionExecuted(ServerInvokeExecutedContext context)
    {
        _sw.Stop();
        // context.ServiceEntry.Id 可获取服务条目标识
        Console.WriteLine($"Elapsed: {_sw.ElapsedMilliseconds}ms");
    }
}

过滤器解析:从 ServiceEntry 到执行列表

FilterDescriptor 的生成

在 ServiceEntry 构造时,框架从接口和方法上收集所有 IFilterMetadata 特性,按以下规则构建 FilterDescriptor 列表:

  • 接口级过滤器:FilterScope.Global(实际为接口级范围)
  • 方法级过滤器:FilterScope.Action
  • 通过 IOrderedFilter.Order 值决定同类过滤器内的执行顺序(值越小越先执行)

DefaultFilterProvider

DefaultFilterProvider(ISingletonDependency)在每次调用时将 FilterDescriptor 实例化为可执行的 FilterItem:

public class DefaultFilterProvider : IFilterProvider
{
    public void ProviderFilters(List<FilterItem> filterItems)
    {
        foreach (var filterItem in filterItems)
        {
            var filter = filterItem.Descriptor.Filter;
            if (filter is IServerFilterFactory factory)
            {
                // 工厂型过滤器:每次从 DI 容器创建新实例
                filterItem.Filter = factory.CreateInstance(serviceProvider);
                filterItem.IsReusable = factory.IsReusable;
            }
            else
            {
                // 特性型过滤器:直接复用特性实例
                filterItem.Filter = filter;
                filterItem.IsReusable = true;
            }
        }
    }
}

服务端过滤器管道执行顺序

LocalInvokerBase 通过状态机(State 枚举驱动的 while 循环)串联各过滤器阶段。以下是完整的执行顺序:

InvokeBegin
    │
    ▼
① AuthorizationFilter(鉴权)
    │  设置 Result → AuthorizationShortCircuit → ⑤ AlwaysRunResultFilter
    │  通过 ↓
    ▼
② ExceptionFilter 注册(包裹后续所有阶段)
    │
    ▼
③ ActionFilter.OnActionExecuting
    │  设置 Result → 短路,跳过 ActionInside → ④ ActionFilter.OnActionExecuted
    │  通过 ↓
    ▼
   ActionInside(调用实际服务方法:ObjectMethodExecutor.Execute)
    │
    ▼
③' ActionFilter.OnActionExecuted(逆序执行)
    │  如有异常 → ② ExceptionFilter 处理
    ▼
④ ResultFilter.OnResultExecuting
    ▼
   WriteResult(将 _result 写回 ServiceEntryContext)
    ▼
④' ResultFilter.OnResultExecuted(逆序执行)
    ▼
⑤ AlwaysRunResultFilter(无论是否短路,始终执行)
    ▼
InvokeEnd(完成)

FilterCursor 工作原理

FilterCursor 是轻量的游标结构体,在 _filters 数组上按类型逐步推进:

public FilterCursorItem<TFilter?, TFilterAsync?> GetNextFilter<TFilter, TFilterAsync>()
{
    while (_index < _filters.Length)
    {
        var filter = _filters[_index] as TFilter;
        var filterAsync = _filters[_index] as TFilterAsync;
        _index += 1;
        if (filter != null || filterAsync != null)
            return new FilterCursorItem<TFilter?, TFilterAsync?>(filter, filterAsync);
    }
    return default;
}

每个阶段开始时调用 _cursor.Reset() 重置游标,确保遍历同一过滤器列表的不同类型切面。

短路规则

  • Authorization 短路:任一 IServerAuthorizationFilter 设置了 context.Result,管道跳过 ExceptionFilter 和 ActionFilter,直接进入 AlwaysRunResultFilter
  • Action 短路:OnActionExecuting 中设置了 context.Result,跳过实际方法执行,直接进入 OnActionExecuted(Canceled = true)
  • 异步过滤器短路:IAsyncServerFilter.OnActionExecutionAsync 若未调用 next(),则 _serviceEntryInvokeExecutedContext.Canceled = true

客户端过滤器管道

RemoteInvoker(继承 RemoteInvokerBase)对称地实现客户端过滤器管道。执行顺序与服务端一致,主要差异:

  • ActionInside 对应发送 RPC 消息(ITransportClient.SendAsync),而非调用本地方法
  • 使用 ClientInvokeExecutingContext / ClientInvokeExecutedContext 替代服务端上下文
  • 客户端鉴权过滤器用于在发出调用前进行权限检查
// 客户端过滤器示例:在 RPC 调用前追加自定义请求头
public class AppendTraceHeaderClientFilter : ClientFilterAttribute
{
    public override void OnActionExecuting(ClientInvokeExecutingContext context)
    {
        RpcContext.Context.SetInvokeAttachment("X-Custom-Trace", Guid.NewGuid().ToString());
    }
}

过滤器注册方式汇总

注册方式作用范围示例
特性标注在接口上接口下所有服务条目[TimingServerFilter] 标注 IOrderAppService
特性标注在方法上单个服务条目[TimingServerFilter] 标注 GetByIdAsync
实现 IServerFilterFactory可通过 DI 容器注入依赖工厂类创建带依赖的过滤器实例

注意:过滤器特性均设置了 AllowMultiple = true,同一目标可标注多个同类过滤器;通过 Order 属性控制同类过滤器的执行顺序(值小的先执行)。

编辑当前页
Prev
HTTP 网关请求管道
Next
Polly 弹性策略管道