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

    • silky 框架介绍
  • 入门

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

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

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

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

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

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

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

简介

silky 框架通过 WebSocketSharp 支持微服务应用提供 WebSocket 通信能力。silky 网关实现了 WebSocket 代理中间件,前端可以通过网关地址与 WebSocket 服务建立会话。

工作原理:

  1. 客户端通过网关 WebSocket 地址(ws://gateway/api/wsservice?hashkey=xxx)发起握手
  2. 网关通过 hashkey 参数使用哈希算法路由到固定的 WebSocket 服务实例
  3. hashkey 与 SessionId 的对应关系缓存在 BusinessSessionIds 字典中
  4. 其他微服务可调用 WebSocket 服务的接口方法,通过 SessionManager 向指定客户端推送消息

构建支持 WebSocket 通信的主机

使用 ConfigureSilkyWebSocketDefaults() 构建 WebSocket 主机(推荐方式):

using Microsoft.Extensions.Hosting;

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

await hostBuilder.Build().RunAsync();

或使用自定义启动模块(继承 WebSocketHostModule):

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

定义和实现 WebSocket 服务

定义应用服务接口

WebSocket 服务接口与普通应用服务接口定义相同,使用 [ServiceRoute] 标识,接口方法可以与其他微服务通过 RPC 通信,也可以承载向 WebSocket 客户端推送消息的逻辑:

[ServiceRoute]
public interface IWsTestAppService
{
    /// <summary>
    /// 向指定 businessId 的 WebSocket 客户端推送消息
    /// </summary>
    Task Echo(string businessId, string msg);
}

实现应用服务

实现类需要同时继承 WsAppServiceBase 基类(提供 WebSocket 会话管理能力):

public class WsTestAppService : WsAppServiceBase, IWsTestAppService
{
    private readonly ILogger<WsTestAppService> _logger;

    public WsTestAppService(ILogger<WsTestAppService> 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: {Message}", e.Data);
        // 向当前客户端回送消息
        Send($"Echo: {e.Data}");
    }

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

    // 由其他微服务通过 RPC 调用,向指定客户端推送消息
    public async Task Echo(string businessId, string msg)
    {
        if (BusinessSessionIds.TryGetValue(businessId, out var sessionIds))
        {
            foreach (var sessionId in sessionIds)
            {
                SessionManager.SendTo($"[Server Push] {msg}", sessionId);
            }
        }
        else
        {
            throw new BusinessException($"不存在 businessId 为 {businessId} 的 WebSocket 会话");
        }
    }
}

关键属性说明:

属性/方法说明
ID当前 WebSocket 会话的 SessionId
BusinessSessionIdshashkey → SessionId[] 的字典,记录所有已建立的会话映射
SessionManager.SendTo(msg, sessionId)向指定 SessionId 的客户端推送消息
Send(msg)向当前客户端发送消息(在 OnMessage 中使用)

网关配置 WebSocket 代理

在网关的 Startup.Configure 中启用 WebSocket 代理中间件:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    // ... 其他中间件
    app.UseRouting();
    app.UseSilkyWebSocketsProxy();  // WebSocket 代理中间件(必须在 UseEndpoints 之前)
    app.UseEndpoints(endpoints =>
    {
        endpoints.MapSilkyRpcServices();
    });
}

注意

WebSocket 服务对应的网关只能部署一个实例,以确保客户端每次都路由到同一个 WebSocket 服务实例(hashkey 哈希路由的前提)。


客户端建立 WebSocket 会话

客户端通过网关地址与 WebSocket 服务建立会话,连接格式:

ws://gateway_host:port/api/{serviceName}?hashkey={businessId}

必须通过 querystring 参数或请求头传入 hashkey(即 businessId),否则无法建立会话。

示例(以上述 WsTestAppService 为例):

ws://127.0.0.1:5000/api/wstest?hashkey=user_100

连接建立后效果:

ws1.png

通过调用 WebAPI 触发服务端向 WebSocket 客户端推送消息:

ws2.png

WebSocket 客户端接收到服务端推送的消息:

ws3.png

如果指定 hashkey 对应的会话不存在,则抛出异常:

ws4.png

编辑当前页
Prev
rpc通信
Next
 服务注册中心