使用SQL背板扩展SignalR并在服务器之间维护UserList

时间:2015-12-08 11:38:17

标签: c# sql signalr signalr-backplane

我希望那里有人遇到这个,或者至少可以发现我的代码有什么问题。

我使用MVC和SignalR创建了一个基于浏览器的聊天应用程序,因为我需要用户登录聊天我已经针对MVC控制器实现了一个注册,将用户添加到内部UserList

public static void Register(string userName, string userRole, string userBase, string userLocation)
{
    var userInfo = (from user in UsersList where user.Name == userName select user).FirstOrDefault();
    if (userInfo != null)
    {
        userInfo.Location = userLocation;
        userInfo.Role = userRole;
        userInfo.Base = userBase;
        return;
    }

    var rgx = new Regex("[^a-zA-Z0-9 -]");
    UsersList.Add(
        new UserInfo
        {
            Name = userName,
            NameId = rgx.Replace(userName, "").Replace(" ", ""),
            Base = userBase,
            Location = userLocation,
            Role = userRole,
            Group = "Cleo",
            Container = userLocation,
            ContainerId = rgx.Replace(userLocation, "").Replace(" ", "").Trim()
        });
}

从客户端我实例化chatHub然后调用Connect

$(function () {
    var objHub = $.connection.chatHub;
    loadClientMethods(objHub);
    $.connection.hub.start().done(function () {
        loadEvents(objHub);
    });

function loadEvents(objHub) {
    $('#hState').val('open');
    objHub.server.connect(gloalUserNameId);
}

所有这些在单个服务器上运行良好,并且所有连接都保存在内存中,顺便说一句,这已经生产了一年多。

现在,我需要为我们的聊天应用程序建立更好的弹性,例如在负载平衡环境中,但由于一切都在内存中,我立即遇到了用户A连接到服务器X和用户B连接到服务器Y的问题(都看不到另一个,你可以看到问题)。

因此,经过长时间在网上挖掘后,我遇到了几篇关于使用Redis或SQL扩展SignalR的文章。由于我们公司使用SQL并且有很多经验,所以我选择了this article

我包含了nuget包并将我的Startup类修改为以下

string connectionString = "Server=.;Trusted_Connection=True;Database=CleoChatHost;";
GlobalHost.DependencyResolver.UseSqlServer(connectionString);
app.MapSignalR();

我在IIS中的不同端口上配置了两个网站,以模拟负载平衡环境以进行测试,例如。我将称之为SiteA和SiteB的http://localhost:21215/http://localhost:21216/

运行每个站点时会发生以下情况:

  • 使用?userName = TestUserA启动SiteA,然后使用?userName = TestUserB启动SiteB - 结果是SiteA加载(最初没有联系人),然后SiteB加载,SiteA用户列表使用TestUserB更新。 SiteB没有用户。

注意:执行与上述相反的操作会得到相同的结果。

我不知道问题是什么,我检查了SQL数据库,可以看到背板已经创建了SQL表,数据进入了它们。我试图用与上述相同的问题实现Redis解决方案。

有没有人实现过这个并遇到同样的问题?或者任何人都可以对这个问题有所了解吗?

修改 经过一些进一步的诊断/测试后,似乎问题可能与每个服务器上维护的内部UserList有关,我相信事件的顺序如下:

  • UserA登录SiteA
  • SiteAUserA添加到UserList上的SiteA
  • SiteA从客户端执行hub.Connect(...),后者又执行Clients.Client(...).DrawTree(...)Clients.AllExcept(...).addUser(...)
  • 上述呼叫更新SiteA用户列表,并通知所有已连接的客户端新用户
  • SiteA已连接且没有活跃用户
  • UserB登录SiteB
  • SiteBUserB添加到UserList上的SiteB
  • SiteB从客户端执行hub.Connect(...),后者又执行Clients.Client(...).DrawTree(...)Clients.AllExcept(...).addUser(...)
  • 上述呼叫更新SiteB用户列表,并通知所有已连接的客户端新用户 - 这会在addUser客户端上执行SiteA以将UserB添加到用户列表
  • SiteB已关联且没有有效用户,而SiteA有一个有效用户

我认为问题在于SQL背板只会在发送消息时处理消息,并且已经从SQL数据库中表的命名约定中确认了这一点。但是,负载平衡服务器之间的内部UserList未同步。使用SiteA更新UserB的事实仅归因于addUserUserB SiteB连接时的SiteB广播(仅UserB包含SiteAUserA仅包含UserList

所以要更新上面的问题,我将如何在服务器之间维护{{1}}?我会使用SQL背板来实现这一目标吗?

0 个答案:

没有答案