.NET Core SignalR Redis底板详解(二)

时间:2019-08-21
本文章向大家介绍.NET Core SignalR Redis底板详解(二),主要包括.NET Core SignalR Redis底板详解(二)使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

接上文。

上文说到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