Silky微服务框架在线文档Silky微服务框架在线文档
首页
文档
配置
源码解析
博文
github
gitee
  • 简体中文
  • English
首页
文档
配置
源码解析
博文
github
gitee
  • 简体中文
  • English
  • 简介

    • silky 框架介绍
  • 入门

    • 名词解释
    • 快速开始
    • 脚手架
    • 微服务模块化架构的最佳实践 & 约定
    • 示例
  • 主机与模块

    • 主机
    • 网关
    • 模块
    • 插件
  • 网关与 HTTP

    • Swagger 文档
    • 性能分析(MiniProfiler)
    • 跨域(CORS)
    • 审计日志
  • 服务与 RPC

    • 应用服务和服务条目
    • rpc通信
    • websocket通信
    •  服务注册中心
    • 服务治理
  • 数据与缓存

    • EFCore 数据访问
    • 缓存
    • 分布式锁
  • 安全与认证

    • 身份认证与授权
    • 分布式事务
  • 基础设施

    • 依赖注入
    • 对象到对象的映射
    • 参数验证
    • 链路跟踪
    • 日志(Serilog)
    • 健康检查
    • 消息总线(MassTransit)
    • 单元测试与集成测试

主机的概念

silky 的主机概念与 .NET 的主机概念一致,是封装应用资源的对象,用于托管应用和管理应用的生命周期。

silky 根据业务场景的不同,提供了四种主机类型:

主机类型构建方法RPC 服务提供HTTP 服务WebSocket
Web 主机ConfigureSilkyWebHostDefaults✅✅❌
通用主机ConfigureSilkyGeneralHostDefaults✅❌❌
WebSocket 主机ConfigureSilkyWebSocketDefaults✅❌✅
网关主机ConfigureSilkyGatewayDefaults❌✅❌

所有主机类型均通过安装 Silky.Agent.Host NuGet 包来使用。


业务主机类型

使用 Web 主机构建微服务应用

使用 Web 主机构建的 silky 应用具有如下特性:

  1. 同时提供 HTTP 服务和 RPC 服务,暴露 HTTP 端口和 RPC 端口
  2. 可以作为外部流量的入口,集群外部通过 HTTP 服务访问微服务应用集群
  3. 作为 RPC 服务提供者,通过 RPC 框架与其他微服务进行通信

host0.png

这种方式适合希望同时对外提供 HTTP 接口、对内参与 RPC 通信的微服务,也适合在不引入独立网关的中小型项目中使用。

使用默认 Web 主机模块

using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;

namespace Silky.Sample
{
    public class Program
    {
        public static async Task Main(string[] args)
        {
            await CreateHostBuilder(args).Build().RunAsync();
        }

        private static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureSilkyWebHostDefaults(webBuilder => webBuilder.UseStartup<Startup>());
    }
}

使用自定义启动模块

如果需要依赖自定义模块,可以通过 ConfigureSilkyWebHost<T> 指定自定义启动模块(需继承 WebHostModule):

private static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureSilkyWebHost<DemoModule>(webBuilder => webBuilder.UseStartup<Startup>());

自定义模块 DemoModule 示例:

// 通过 [DependsOn] 声明对其他模块的依赖
// [DependsOn(typeof(UserDefinedModule))]
public class DemoModule : WebHostModule
{
    public override Task Initialize(ApplicationInitializationContext context)
    {
        // 应用启动后执行的初始化逻辑
        return Task.CompletedTask;
    }

    public override Task Shutdown(ApplicationShutdownContext context)
    {
        // 应用停止前执行的清理逻辑
        return Task.CompletedTask;
    }

    public override void ConfigureServices(IServiceCollection services, IConfiguration configuration)
    {
        // 与 Startup.ConfigureServices 作用相同,适合在模块中统一注册服务
    }

    protected override void RegisterServices(ContainerBuilder builder)
    {
        // 通过 Autofac ContainerBuilder 注册服务
        // 优势:支持命名服务等 IServiceCollection 不支持的场景
    }
}

在 Startup.cs 中配置服务和中间件

public class Startup
{
    public IConfiguration Configuration { get; }

    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public void ConfigureServices(IServiceCollection services)
    {
        services
            .AddSilkyHttpCore()          // Silky HTTP 核心服务(必须)
            .AddSwaggerDocuments()       // Swagger 在线文档
            .AddRouting()
            .AddSilkyIdentity()          // JWT 身份认证(可选)
            .AddSilkyMiniProfiler();     // 性能分析(可选)
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
            app.UseSwaggerDocuments();
            app.UseMiniProfiler();
        }

        app.UseRouting();
        app.UseSilkyIdentity();          // 启用身份认证中间件(可选)
        app.UseSilkyWebSocketsProxy();   // 启用 WebSocket 代理(如需转发 ws 请求)

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapSilkyRpcServices(); // 映射 Silky 服务条目路由(必须)
        });
    }
}

使用通用主机构建微服务应用

使用通用主机构建的 silky 应用具有如下特性:

  1. 只提供 RPC 服务,不提供 HTTP 服务,集群外部无法直接访问
  2. 必须通过网关或具有 HTTP 服务的微服务间接访问
  3. 资源占用更少,适合纯后端业务逻辑服务

host1.png

使用默认通用主机模块

using Microsoft.Extensions.Hosting;

var hostBuilder = Host.CreateDefaultBuilder(args)
    .ConfigureSilkyGeneralHostDefaults();

await hostBuilder.Build().RunAsync();

使用自定义启动模块

private static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureSilkyGeneralHost<DemoModule>();

自定义模块需继承 GeneralHostModule(注意与 Web 主机的 WebHostModule 区分):

// [DependsOn(typeof(UserDefinedModule))]
public class DemoModule : GeneralHostModule
{
    public override Task Initialize(ApplicationInitializationContext context)
    {
        return Task.CompletedTask;
    }

    public override Task Shutdown(ApplicationShutdownContext context)
    {
        return Task.CompletedTask;
    }

    public override void ConfigureServices(IServiceCollection services, IConfiguration configuration)
    {
        // 注册服务
    }

    protected override void RegisterServices(ContainerBuilder builder)
    {
        // 通过 Autofac 注册服务
    }
}

注意

通用主机不提供 HTTP 服务,因此无法配置 HTTP 中间件(配置了也不生效)。

通用主机中通过 IConfigureService 接口注册服务:

public class ConfigureService : IConfigureService
{
    public void ConfigureServices(IServiceCollection services, IConfiguration configuration)
    {
        services
            .AddSilkySkyApm()              // SkyAPM 链路追踪(可选)
            .AddMessagePackCodec();        // MessagePack 编解码(可选)

        // 集成 EFCore
        services.AddDatabaseAccessor(
            options => { options.AddDbPool<DefaultContext>(); },
            "Demo.Database.Migrations");

        // 集成消息总线(CAP、MassTransit 等)
        // services.AddCap(x => { ... });
    }

    public int Order => 1;  // 多个 IConfigureService 时通过 Order 控制执行顺序
}

构建具有 WebSocket 服务能力的微服务应用

具有 WebSocket 服务能力的微服务应用具有如下特性:

  1. 同时提供 RPC 服务和 WebSocket 服务(WebSocket 默认端口 3000)
  2. 可以通过网关的 WebSocket 代理中间件与该微服务的 WebSocket 服务进行握手
  3. 服务端可主动向客户端推送消息

host2.png

构建 WebSocket 主机

using Microsoft.Extensions.Hosting;

var hostBuilder = Host.CreateDefaultBuilder(args)
    .ConfigureSilkyWebSocketDefaults();

await hostBuilder.Build().RunAsync();

使用自定义启动模块

自定义模块需继承 WebSocketHostModule:

// [DependsOn(typeof(UserDefinedModule))]
public class DemoModule : WebSocketHostModule
{
    public override Task Initialize(ApplicationContext applicationContext)
    {
        return Task.CompletedTask;
    }

    public override Task Shutdown(ApplicationContext applicationContext)
    {
        return Task.CompletedTask;
    }
}

实现 WebSocket 服务

提供 WebSocket 服务的实现类需要继承 WsAppServiceBase,在建立会话后可通过 SessionManager 向客户端推送消息:

public class TestAppService : WsAppServiceBase, ITestAppService
{
    private readonly ILogger<TestAppService> _logger;

    public TestAppService(ILogger<TestAppService> logger)
    {
        _logger = logger;
    }

    // 建立 WebSocket 会话时触发
    protected override void OnOpen()
    {
        base.OnOpen();
        _logger.LogInformation("WebSocket session established, SessionId: {SessionId}", ID);
    }

    // 收到客户端消息时触发
    protected override void OnMessage(MessageEventArgs e)
    {
        _logger.LogInformation("Received: {Message}", e.Data);
        // 向当前客户端回送消息
        Send($"Server received: {e.Data}");
    }

    // 会话关闭时触发
    protected override void OnClose(CloseEventArgs e)
    {
        base.OnClose(e);
        _logger.LogInformation("WebSocket session closed, reason: {Reason}", e.Reason);
    }
}

WebSocket 代理要求

前端需要通过网关的 WebSocket 代理中间件与 WebSocket 服务建立会话,需满足以下要求:

  1. 通过请求头或 querystring 参数指定 hashkey(即 bussinessId),框架使用该值通过哈希算法路由到固定的 WebSocket 服务实例
  2. 为保证每次都路由到同一个服务实例,对应的网关只能部署一个实例
  3. 网关必须启用 WebSocket 代理中间件:
// 在网关的 Configure() 中配置 WebSocket 代理中间件
app.UseSilkyWebSocketsProxy();

建议

可以考虑将普通业务服务对应一组网关(支持多实例),WebSocket 应用对应另一组网关(只允许单实例),分开部署以满足各自需求。


构建网关

网关作为微服务集群对外的统一流量入口,具有如下特性:

  1. 只提供 HTTP 服务,作为集群流量入口
  2. 不提供 RPC 服务,只能作为服务消费者,不能作为 RPC 服务提供者
  3. 通过引用各微服务的应用接口层,自动获得各服务的路由信息和 RPC 代理能力

host3.png

网关 vs Web 主机

  • 网关:只能作为服务消费者,转发外部 HTTP 请求;无 RPC 服务注册
  • Web 主机:除了转发 HTTP 请求外,还能作为 RPC 服务提供者,注册服务到注册中心

使用默认网关模块

using Microsoft.Extensions.Hosting;

private static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureSilkyGatewayDefaults(webBuilder => webBuilder.UseStartup<Startup>());

使用自定义启动模块

自定义模块需继承 GatewayHostModule:

private static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureSilkyGateway<DemoModule>(webBuilder => webBuilder.UseStartup<Startup>());

网关 Startup 配置

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services
            .AddSilkyHttpCore()        // Silky HTTP 核心服务(必须)
            .AddRouting()
            .AddSwaggerDocuments()     // 聚合所有微服务的 Swagger 文档
            .AddSilkyIdentity()        // 统一身份认证(可选)
            .AddSilkyMiniProfiler();   // 性能分析(可选)
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
            app.UseSwaggerDocuments();
        }

        app.UseRouting();
        app.UseSilkyIdentity();        // 统一身份认证中间件
        app.UseSilkyWebSocketsProxy(); // WebSocket 代理(如需支持 ws 转发)

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapSilkyRpcServices(); // 映射路由(必须)
        });
    }
}

说明:silky 框架在 v3.x 中,网关无需逐个引用各微服务应用接口层的包,只需与业务微服务接入同一个服务注册中心,网关即可自动获取所有微服务的服务条目信息并生成路由和 Swagger 文档。

编辑当前页
Next
网关