概述
当一个服务条目被判定为本地执行(IsLocal = true)时,框架通过 本地执行器(ILocalExecutor) 完成实际的业务方法调用。本地执行的核心特点是:
- 在调用业务方法之前和之后,执行服务端过滤器管道(Server Filter Pipeline)
- 过滤器支持异步和同步两种接口,框架通过状态机驱动管道执行,与 ASP.NET Core 的 ActionFilter 机制高度相似
- 支持身份认证过滤、异常过滤、结果过滤等多种类型
DefaultLocalExecutor — 本地执行入口
DefaultLocalExecutor 是 ILocalExecutor 的默认实现:
public class DefaultLocalExecutor : ILocalExecutor
{
private readonly IServerLocalInvokerFactory _serverLocalInvokerFactory;
public async Task<object> Execute(ServiceEntry serviceEntry, object[] parameters, string? serviceKey = null)
{
// 1. 根据 serviceKey 解析服务实现类实例(支持多实现路由)
var instance = EngineContext.Current.ResolveServiceInstance(serviceKey, serviceEntry.ServiceType);
// 2. 构建 ServiceEntryContext(封装 ServiceEntry、参数、实现实例)
// 3. 通过工厂创建 LocalInvoker(含过滤器链)
var localInvoker =
_serverLocalInvokerFactory.CreateInvoker(
new ServiceEntryContext(serviceEntry, parameters, serviceKey, instance));
// 4. 执行过滤器管道 + 业务方法
await localInvoker.InvokeAsync().ConfigureAwait(false);
// 5. 返回执行结果
return localInvoker.Result;
}
}
关键步骤解析:
- 多实现路由(ServiceKey):通过
ResolveServiceInstance(serviceKey, serviceType)根据serviceKey从 IoC 容器中解析对应的实现类实例。当同一接口有多个实现时,不同的实现通过ServiceKey区分。 - ServiceEntryContext:这是贯穿整个本地调用过程的上下文对象,包含服务条目元数据、解析后的参数数组、目标实现类实例。
- LocalInvoker 工厂:由
IServerLocalInvokerFactory负责创建LocalInvoker,工厂在创建时会扫描并排序所有适用的服务端过滤器。
ServiceEntryContext — 调用上下文
ServiceEntryContext 是本地调用的"会话"对象,在整个过滤器管道中流转:
| 属性 | 类型 | 说明 |
|---|---|---|
ServiceEntry | ServiceEntry | 当前服务条目元数据(包含路由、参数描述符、治理参数等) |
Parameters | object[] | 已解析的参数数组(与方法签名顺序一致) |
ServiceKey | string? | 本次调用使用的服务键(用于多实现路由) |
Instance | object | 业务实现类的实例 |
Result | object | 调用完成后的返回值 |
IServiceEntryContextAccessor 是线程安全的上下文访问器(基于 AsyncLocal<T>),允许过滤器或业务代码在任意位置访问当前调用的上下文。
服务端过滤器类型
silky 服务端过滤器体系与 ASP.NET Core 的 ActionFilter 设计保持一致,提供以下几种过滤器类型:
1. 身份认证过滤器(Authorization Filter)
public interface IAsyncServerAuthorizationFilter : IServerFilterMetadata
{
Task OnAuthorizationAsync(ServerAuthorizationFilterContext context);
}
public interface IServerAuthorizationFilter : IServerFilterMetadata
{
void OnAuthorization(ServerAuthorizationFilterContext context);
}
- 最先执行(在 Action 过滤器和结果过滤器之前)
- 如果鉴权失败,将
context.Result设置为非空值可短路后续执行 - silky 框架内置了基于
[Authorize]特性的身份认证过滤器
2. Action 过滤器(Server Filter)
public interface IAsyncServerFilter : IServerFilterMetadata
{
Task OnActionExecutionAsync(ServerInvokeExecutingContext context, ServerExecutionDelegate next);
}
public interface IServerFilter : IServerFilterMetadata
{
void OnActionExecuting(ServerInvokeExecutingContext context);
void OnActionExecuted(ServerInvokeExecutedContext context);
}
- 在业务方法执行前后各触发一次
OnActionExecuting(或异步的OnActionExecutionAsync中await next()之前):可修改参数、执行前置逻辑OnActionExecuted(或await next()之后):可访问返回值、处理异常- 在
OnActionExecuting中设置context.Result可短路后续过滤器和业务方法
3. 异常过滤器(Exception Filter)
public interface IAsyncServerExceptionFilter : IServerFilterMetadata
{
Task OnExceptionAsync(ServerInvokeExceptionContext context);
}
public interface IServerExceptionFilter : IServerFilterMetadata
{
void OnException(ServerInvokeExceptionContext context);
}
- 当业务方法或后续过滤器抛出未处理异常时执行
- 可通过将
context.ExceptionHandled = true标记异常已被处理,阻止异常继续传播 - silky 内置的参数验证(
ValidationException)、UserFriendlyException等友好异常的格式化均通过异常过滤器实现
4. 结果过滤器(Result Filter)
public interface IAsyncServerResultFilter : IServerFilterMetadata
{
Task OnResultExecutionAsync(ServerResultExecutingContext context, ServerResultExecutionDelegate next);
}
// 始终运行(即使发生短路)的结果过滤器
public interface IAsyncAlwaysRunServerResultFilter : IAsyncServerResultFilter { }
- 在业务方法执行成功后、结果写入响应之前触发
IAsyncAlwaysRunServerResultFilter即使 Action 过滤器或身份认证过滤器发生短路,也会执行- 常用于响应格式转换、结果后处理
过滤器执行状态机
LocalInvokerBase 采用**状态机(State Machine)**驱动整个过滤器管道,这是对 ASP.NET Core 源码模式的复用。状态机通过 State 枚举逐步推进:
State.ActionBegin
│ 参数绑定(BindArgumentsAsync)
▼
State.AuthorizationBegin
│ 依次执行身份认证过滤器
│ 任意过滤器设置 context.Result → 短路至 State.AuthorizationShortCircuit
▼
State.ActionBegin(实际执行过滤器链)
│
├─ State.ActionExecutionFilter(每个 Server Filter)
│ OnActionExecuting → 设置 context.Result 则短路
│ await next() → 执行下一个过滤器或业务方法
│ OnActionExecuted
│
▼
State.ActionInside(执行业务方法)
│ 调用 ObjectMethodExecutor.ExecuteAsync(instance, parameters)
│ 将结果存入 context.Result
▼
State.ResultBegin(执行结果过滤器)
│
├─ State.ResultExecutionFilter(每个 Result Filter)
│ OnResultExecuting → await next() → OnResultExecuted
│
▼
State.InvokeEnd
│ 将最终 result 写回 localInvoker.Result 供调用方获取
短路机制
当任一过滤器决定短路(设置 context.Result 不调用 next())时:
- Action 过滤器管道停止继续推进
- 仍然执行已进入过滤器链中
OnActionExecuted(已执行过OnActionExecuting的过滤器) IAsyncAlwaysRunServerResultFilter无论短路与否都会运行
过滤器的注册与排序
全局注册
在模块的 ConfigureServices 中通过 AddServerFilter<T>() 注册全局服务端过滤器:
services.AddServerFilter<MyGlobalFilter>();
特性方式注册(方法级)
在服务接口方法上标注派生自 ServerFilterAttribute 的特性,实现方法级过滤器:
public interface IOrderAppService
{
[MyServerFilter] // 只对这个方法生效
Task<OrderDto> CreateAsync(CreateOrderInput input);
}
排序规则
过滤器按 Order 属性从小到大排序(默认 Order = 0)。同 Order 时,全局过滤器先于方法特性过滤器执行。
[AttributeUsage(AttributeTargets.Method)]
public class MyServerFilter : ServerFilterAttribute, IAsyncServerFilter
{
public override int Order => -100; // 越小越先执行
public async Task OnActionExecutionAsync(ServerInvokeExecutingContext context, ServerExecutionDelegate next)
{
// Before
await next();
// After
}
}
ObjectMethodExecutor — 业务方法执行
ServiceEntry 内部持有一个 ObjectMethodExecutor(来自 Silky.Core.MethodExecutor),它封装了对业务方法的高效反射调用,并特别针对以下返回类型做了处理:
| 返回类型 | 处理方式 |
|---|---|
Task<T> | await executor.ExecuteAsync() 取 Result |
ValueTask<T> | 解包为 Task<T> 后 await |
Task | await 后返回 null |
| 同步方法 | 包装为 Task.FromResult() 统一处理 |
这样业务方法无论是同步还是异步,对过滤器管道都表现出统一的异步接口。
缓存拦截器(CachingInterceptor)
silky 支持在服务条目上声明分布式缓存拦截,通过 [GetCachingIntercept]、[UpdateCachingIntercept]、[RemoveCachingIntercept] 等特性实现:
public interface IOrderAppService
{
[GetCachingIntercept("order:{id}")]
Task<OrderDto> GetByIdAsync(long id);
[UpdateCachingIntercept("order:{id}")]
Task<OrderDto> UpdateAsync(long id, UpdateOrderInput input);
[RemoveCachingIntercept("order:{id}")]
Task DeleteAsync(long id);
}
缓存拦截通过 Silky.Rpc.CachingInterceptor 包实现,在本地执行之前先查缓存;命中则直接返回,不进入过滤器管道和业务方法。缓存的 key 模板支持参数占位符(如 {id}),框架在运行时从参数中动态提取值。
完整执行序列图
本地调用请求
│
▼
DefaultLocalExecutor
│ ResolveServiceInstance(serviceKey)
│
▼
ServiceEntryContext 创建
│
▼
LocalInvoker(服务端过滤器链)
│
├── [Auth Filter 1] OnAuthorizationAsync
├── [Auth Filter N] OnAuthorizationAsync
│
├── [Server Filter 1] OnActionExecutingAsync ──────────┐
├── [Server Filter N] OnActionExecutingAsync ─────┐ │
│ │ │
│ ObjectMethodExecutor.ExecuteAsync() │ │
│ (执行业务实现类方法) │ │
│ │ │
├── [Server Filter N] OnActionExecutedAsync ─────┘ │
├── [Server Filter 1] OnActionExecutedAsync ───────────┘
│
├── [Result Filter 1] OnResultExecutingAsync
│ ......
├── [Result Filter N] OnResultExecutedAsync
│
▼
LocalInvoker.Result(返回给调用方)
