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

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

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

概述

HTTP 网关是 silky 框架对外暴露 REST 接口的入口层。当外部请求到达网关时,请求会依次经过 ASP.NET Core 路由匹配 → 参数解析 → 服务条目执行 → 响应包装 四个阶段,最终将 RPC 执行结果以统一 JSON 格式返回。

本文聚焦于运行时请求管道的源码实现,说明每个阶段的核心组件与数据流转。


整体管道结构

外部 HTTP 请求
    │
    ▼
WrapperResponseMiddleware(拦截 Response.Body,准备统一包装)
    │
    ▼
ASP.NET Core 路由匹配(SilkyServiceEntryEndpointDataSource)
    │  ——→ 匹配失败:404
    ▼
MessageReceivedHandlerBase.Handle()
    │  1. 创建 HttpContextServerCallContext
    │  2. 初始化(设置超时令牌、上报活动追踪、解析用户声明)
    ▼
DefaultHttpMessageReceivedHandler.HandleCallAsyncCore()
    │  1. 解析 HTTP 参数 → object[]
    │  2. 解析 ServiceKey
    │  3. 启动 Monitor(可选)
    │  4. 调用 IHttpExecutor.Execute()
    │  5. 写入响应正文
    ▼
WrapperResponseMiddleware
    │  1. 读取 Response.Body 内容
    │  2. 包装为 { status, code, result / errorMessage }
    │  3. 写回响应
    ▼
客户端收到统一格式 JSON

阶段一:路由匹配

网关启动时,SilkyServiceEntryEndpointDataSource 将所有 ServiceEntry 注册为 ASP.NET Core Endpoint。路由匹配由标准 ASP.NET Core 路由机制完成,匹配成功后将 ServiceEntry 和 ServiceEntryDescriptor 写入 HttpContext.Items,供后续组件读取。

// SilkyHttpCoreCollectionExtensions.cs
services.AddSingleton<SilkyServiceEntryEndpointDataSource>();
services.AddSingleton<ServiceEntryEndpointFactory>();
services.AddSingleton<SilkyServiceEntryDescriptorEndpointDataSource>();

阶段二:消息接收处理器

路由匹配成功后,请求进入 DefaultHttpMessageReceivedHandler(IMessageReceivedHandler 的默认实现)。

MessageReceivedHandlerBase.Handle()

基类负责统一的初始化流程:

public virtual Task Handle(ServiceEntry serviceEntry, HttpContext httpContext)
{
    // 1. 构造 HttpContextServerCallContext(绑定超时令牌、活动追踪)
    var serverCallContext = new HttpContextServerCallContext(
        httpContext, serviceEntry.ServiceEntryDescriptor,
        _serializer, GatewayOptions, Logger);

    // 2. 初始化:设置 CancellationToken、写入追踪标签
    serverCallContext.Initialize();
    httpContext.RequestAborted = serverCallContext.CancellationToken;

    // 3. 派发给子类实现
    return HandleCallAsyncCore(httpContext, serverCallContext, serviceEntry);
}

HttpContextServerCallContext.Initialize() 内部会:

  • 获取当前 Activity 并写入 serviceentry.id 标签
  • 调用 SilkyRpcEventSource.Log.CallStart() 上报指标
  • 解析请求头中的用户声明(SetUserClaims)

DefaultHttpMessageReceivedHandler.HandleCallAsyncCore()

子类完成参数解析、执行和结果写入:

protected override async Task HandleCallAsyncCore(
    HttpContext httpContext,
    HttpContextServerCallContext serverCallContext,
    ServiceEntry serviceEntry)
{
    // 1. 解析 HTTP 参数
    var parameters = await _parameterParser.Parser(httpContext.Request, serviceEntry);

    // 2. 将请求参数写入 RpcContext(用于审计)
    RpcContext.Context.SetRequestParameters(_auditSerializer.Serialize(parameters));

    // 3. 解析 ServiceKey(来自请求头 serviceKey)
    var serviceKey = ResolveServiceKey(httpContext);
    if (!serviceKey.IsNullOrEmpty())
        RpcContext.Context.SetServiceKey(serviceKey);

    // 4. 可选:启动调用监控
    if (rpcOption.EnableMonitor)
        serverHandleInfo = serverHandleMonitor?.Monitor(...);

    // 5. 执行服务条目(本地或远程)
    var executeResult = await _executor.Execute(serviceEntry, parameters, serviceKey);

    // 6. 写入响应正文(JSON 序列化或 IActionResult 执行)
    await serverCallContext.HttpContext.Response.WriteAsync(responseData);
}

阶段三:HTTP 参数解析

DefaultHttpRequestParameterParser 负责从 HttpRequest 各数据源提取参数,构造 object[] 传递给执行器。

参数来源映射

ParameterFrom数据来源说明
Formrequest.Formmultipart/form-data 表单数据及文件上传
Queryrequest.QueryURL 查询字符串
Headerrequest.Headers请求头,同时写入 RpcContext 附件
Bodyrequest.BodyJSON 请求体(非 GET 请求)
Path路由参数通过 Router.ParserRouteParameters() 解析路由段

参数解析流程

public async Task<object[]> Parser(HttpRequest httpRequest, ServiceEntry serviceEntry)
{
    // 1. 收集各来源原始数据
    var requestParameters = await ParserHttpRequest(httpRequest, serviceEntry);

    // 2. 委托给 HttpParameterResolver,将原始数据按 RpcParameter 定义绑定为方法参数列表
    var httpParameterResolver =
        EngineContext.Current.ResolveNamed<IParameterResolver>(ParameterType.Http.ToString());
    return httpParameterResolver.Parser(serviceEntry, requestParameters, httpRequest.HttpContext);
}

HttpParameterResolver 根据 ServiceEntry.Parameters(由启动时生成的 RpcParameter[])将各来源数据映射到对应的方法参数位置。


阶段四:HTTP 执行器

DefaultHttpExecutor 是网关专用的执行器适配器,将网关的 HttpRequest 路径桥接到通用的 IExecutor:

public class DefaultHttpExecutor : IHttpExecutor
{
    private readonly IExecutor _executor;

    public async Task<object> Execute(ServiceEntry serviceEntry, object[] parameters, string serviceKey = null)
        => await _executor.Execute(serviceEntry, parameters, serviceKey);
}

IExecutor(DefaultExecutor)随后根据 ServiceEntry.IsLocal 决定走本地执行还是远程 RPC 调用,详见 executor 文档。


阶段五:响应包装中间件

WrapperResponseMiddleware 拦截 Response.Body,在所有中间件执行完成后,将原始响应正文包装为统一格式。

直通场景(不包装)

以下情况 WrapperResponseMiddleware 会直通,不做包装:

  1. 请求路径匹配 GatewayOptions.IgnoreWrapperPathPatterns 中的正则(且为 GET 请求)
  2. ServiceEntry.ReturnType 是 IActionResult 的子类
  3. ServiceEntryDescriptor.IsUnWrapperResult() 返回 true(通常通过 [UnWrapperResult] 特性标注)

包装格式

private async Task HandleResponseAsync(HttpContext context, string body, int httpStatusCode)
{
    var status = context.Response.GetResultCode(httpStatusCode);
    var responseResultDto = new ResponseResultDto
    {
        Status = (int)status,
        Code = status.ToString(),
        Result = _serializer.Deserialize<dynamic>(body),  // 成功时
    };
    // 失败时填充 ErrorMessage
    var jsonString = _serializer.Serialize(responseResultDto);
    context.Response.StatusCode = (int)status;
    await context.Response.WriteAsync(jsonString);
}

成功响应格式:

{
  "status": 200,
  "code": "Success",
  "result": { /* 业务数据 */ }
}

失败响应格式:

{
  "status": 500,
  "code": "ServerError",
  "errorMessage": "具体错误描述"
}

核心组件汇总

组件类型职责
SilkyServiceEntryEndpointDataSourceSingleton将 ServiceEntry 注册为 ASP.NET Core Endpoint
MessageReceivedHandlerBaseScoped(抽象)构造 HttpContextServerCallContext,初始化追踪和超时
DefaultHttpMessageReceivedHandlerScoped参数解析、执行、结果写入
DefaultHttpRequestParameterParserScoped从 Form/Query/Header/Body/Path 解析方法参数
DefaultHttpExecutorTransient桥接 HTTP 请求到 IExecutor
WrapperResponseMiddlewareMiddleware拦截并包装为统一响应 JSON
HttpContextServerCallContextPer-request持有请求上下文、超时令牌、追踪活动
编辑当前页
Prev
分布式事务(TCC)
Next
过滤器执行管道