接上文。

上文说到Clients.All.SendAsync实际上是调用AllClientProxy的SendCoreAsync方法。其实主要是调用IClientProxy的SendCoreAsync。在上文说到的HubClients类里。就有很多IClientProxy的实现类。比如刚刚说到的All其实是AllClientProxy对象。

public IClientProxy AllExcept(IReadOnlyList<string> excludedConnectionIds){return new AllClientsExceptProxy<THub>(_lifetimeManager, excludedConnectionIds);}public IClientProxy Client(string connectionId){return new SingleClientProxy<THub>(_lifetimeManager, connectionId);}public IClientProxy Group(string groupName){return new GroupProxy<THub>(_lifetimeManager, groupName);}public IClientProxy GroupExcept(string groupName, IReadOnlyList<string> excludedConnectionIds){return new GroupExceptProxy<THub>(_lifetimeManager, groupName, excludedConnectionIds);}public IClientProxy Clients(IReadOnlyList<string> connectionIds){return new MultipleClientProxy<THub>(_lifetimeManager, connectionIds);}public IClientProxy Groups(IReadOnlyList<string> groupNames){return new MultipleGroupProxy<THub>(_lifetimeManager, groupNames);}public IClientProxy User(string userId){return new UserProxy<THub>(_lifetimeManager, userId);}public IClientProxy Users(IReadOnlyList<string> userIds){return new MultipleUserProxy<THub>(_lifetimeManager, userIds);}

  这些实现类其实里面都是千篇一律的构造函数和SendCoreAsync。真正起作用的还是HubLifetimeManager对象。上文中说了。在AdRedis的时候就已经把RedisHubLifetimeManager注入进去了。所以这里其实真正调用的还是RedisHubLifetimeManager中的SendAllAsync方法。

public override Task SendAllAsync(string methodName, object[] args, CancellationToken cancellationToken = default){var message = _protocol.WriteInvocation(methodName, args);return PublishAsync(_channels.All, message);}

  在WriteInvocation方法中完成广播的发送。(这段代码太晦涩。我没看懂,只是猜个大概)。在PublishAsync实现的是Redis的推送。

那么其他服务器是怎么收到广播的呢?

同样是在RedisHubLifetimeManager中。重写了OnConnectedAsync方法。

public override async Task OnConnectedAsync(HubConnectionContext connection){await EnsureRedisServerConnection();var feature = new RedisFeature();connection.Features.Set<IRedisFeature>(feature);var connectionTask = Task.CompletedTask;var userTask = Task.CompletedTask;_connections.Add(connection);connectionTask = SubscribeToConnection(connection);if (!string.IsNullOrEmpty(connection.UserIdentifier)){userTask = SubscribeToUser(connection);}await Task.WhenAll(connectionTask, userTask);}

  在这里通过SubscribeToConnection方法完成了Redis的订阅。这个OnConnectedAsync方法在HubConnectionHandler中的OnConnectedAsync中被调用。从名字就可以看出来HubConnectionHandler是处理HubConnection的。而HubConnectionHandler的调用则是在我们一开始UseHub的时候。

public static IConnectionBuilder UseHub<THub>(this IConnectionBuilder connectionBuilder) where THub : Hub{var marker = connectionBuilder.ApplicationServices.GetService(typeof(SignalRCoreMarkerService));if (marker == null){throw new InvalidOperationException("Unable to find the required services. Please add all the required services by calling " +"'IServiceCollection.AddSignalR' inside the call to 'ConfigureServices(...)' in the application startup code.");}return connectionBuilder.UseConnectionHandler<HubConnectionHandler<THub>>();}

  至此。整个广播流程就讲解完毕了。

这里说一下为什么前言中的方法不好。因为用接口暴露的形式其实是走Http协议。而Redis的订阅与发布是走RESP协议。Http是超文本传输协议在子房间多的情况下会额外用掉很多带宽与IIS的处理资源。而且用Redis的订阅发布模式,Channel的方式与Signalr的Group等其他方式的思路其实是相同的。

最后贴一下微软的官方说明。

设置 ASP.NET Core SignalR 横向扩展 Redis 底板

https://docs.microsoft.com/zh-cn/aspnet/core/signalr/redis-backplane?view=aspnetcore-2.2

教程:ASP.NET Core SignalR 入门

https://docs.microsoft.com/zh-cn/aspnet/core/tutorials/signalr?view=aspnetcore-2.2&tabs=visual-studio

转载于:https://www.cnblogs.com/dbdn/p/11390928.html

.NET Core SignalR Redis底板详解(二)相关推荐

  1. .NET Core SignalR Redis底板详解(前言)

    SignalR毫无疑问是.Net中很好使的实时消息处理系统.在我之前的公司的聊天功能就是用SinglaR进行广播推送的.不过他们没有用到Group的概念.用的最多的就是All广播推送.甚至部分Clie ...

  2. .NET Core SignalR Redis底板详解(一)

    其实微软在.NET Framework时代就有Redis和Signalr的解决方案了.只不过我没有花心思去找源码..NET Core版本的源码倒是很全.我们在用signalR的时候.是会先创建一个Ch ...

  3. java集成redis集群_spring集成redis cluster详解

    客户端采用最新的jedis 2.7 1.maven依赖: redis.clients jedis 2.7.3 2.增加spring 配置 classpath:connect-redis.propert ...

  4. python操作redis set_Python操作redis学习系列之(集合)set,redis set详解 (六)

    #-*- coding: utf-8 -*- importredis r= redis.Redis(host="126.56.74.190",port=639,password=& ...

  5. redis 数据类型详解 以及 redis适用场景场合

    redis 数据类型详解 以及 redis适用场景场合 1. MySql+Memcached架构的问题 实际MySQL是适合进行海量数据存储的,通过Memcached将热点数据加载到cache,加速访 ...

  6. Redis主从复制详解(入门教程)

    文章目录 概念 环境配置 一主二从 配置 测试 复制原理 哨兵模式 概述 测试 哨兵模式全部配置 以下是Redis相关笔记总结,方便自己以后复习,同时也希望对大家有所帮助. 内容 地址链接 Redis ...

  7. 全志 android 编译,全志Android SDK编译详解(二)

    注意要确定安装了jdk) 第一步: cd  lichee; ./build.sh  -p sun5i_elite -k 3.0  (apt-get install uboot-mkimage需要安装m ...

  8. Spring和Redis整合详解

    Spring和Redis整合详解 官方主页 Spring Spring Redis 概述 Redis是一个开源(BSD许可)的内存数据结构存储,用作数据库,缓存和消息代理. 简单来说,它是一个以(ke ...

  9. PackageManagerService启动详解(二)之怎么通过packages.xml对已安装应用信息进行持久化管理?

    PKMS启动详解(二)之怎么通过packages.xml对已安装应用信息进行持久化管理? Android PackageManagerService系列博客目录: PKMS启动详解系列博客概要 PKM ...

最新文章

  1. ADAS系统长篇综述(下)
  2. 用神经网络分类过去与未来
  3. python数据结构与算法40题_Python数据结构与算法刷题(2)——挖掘机技术哪家强...
  4. 避免使用FOR –反假战役
  5. 专刊文章 - Web UI框架引领J2EE新开发模式(代码生成器+手工merge半智能开发)
  6. Wait-for-it之参考
  7. 开发的一款IDEA电子阅读器功能介绍
  8. ifen.os x pe.dmg天翼云_3.3K屏显纵览天下 11代酷睿横行职场 华硕灵耀X纵横值得选择...
  9. 论文中的统计学如何计算机,统计学教学中如何利用Excel软件及其利弊分析论文...
  10. linux 隧道服务器,Linux下建立和使用隧道访问IPV6网络的方法 - 如何用隧道搭建ipv6...
  11. 麦肯锡著名的三大结构化工具:金字塔原理、MECE和逻辑树
  12. shell脚本检查域名证书是否过期
  13. YOLOv5和YOLOv7环境(GPU)搭建测试成功
  14. [已解决]“TypeError: Cannot read property ‘xxx‘ of undefined“报错情况分析
  15. CStdioFile 追加文件内容
  16. 文件下载(浏览器下载与迅雷下载)
  17. 你在SOA实现中应用筒仓分析了吗?
  18. 古诺双寡头模型MATLAB求解(博弈论)
  19. 大数据与云计算学习计划 (一) 云计算系统管理 6 Linux中RPM软件包管理操作 、 Yum软件包仓库操作(概念与实操)
  20. 亚马逊AWS成为温德姆酒店集团首选云服务提供商;阿布扎比建设世界最大水族馆 | 全球旅报...

热门文章

  1. bootsect.s文件阅读问题集
  2. javascript 中this 的用法:
  3. ffmpeg源码实现抽取音频并保存 --C++实现
  4. 编写一程序,有2个文本框,在第一个文本框中输入一个整数,当焦点从第一个文本框离开时,第二个文本框将显示这个数的绝对值(使用FocusListener)。
  5. STM32开发 -- 启动流程
  6. Altium Designer -- PCB布线面试题(转)
  7. pat天梯赛L1-054. 福到了
  8. Android Telephony分析(三) ---- RILJ详解
  9. layui 自定义排序_thinkphp5+layui异步修改排序
  10. c++ vector 赋值_C++中vector用法