1

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

我使用 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 并且在这方面有很多经验,所以我选择了这篇文章

我包含了 nuget 包并将我的Startup课程修改为以下内容

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

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

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

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

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

我不知道问题出在哪里,我检查了 SQL 数据库,可以看到背板已经创建了 SQL 表并且数据正在进入它们。我也尝试使用与上述相同的问题来实现 Redis 解决方案。

有没有人实施过这个并遇到同样的问题?或者任何人都可以解释一下这个问题可能是什么?

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

  • UserA登录SiteA
  • SiteA增加UserAUserList_SiteA
  • SiteAhub.Connect(...)从客户端执行,然后Clients.Client(...).DrawTree(...)执行Clients.AllExcept(...).addUser(...)
  • 上述调用更新SiteA用户列表,并通知所有连接的客户端有一个新用户
  • SiteA已连接且没有活动用户
  • UserB登录SiteB
  • SiteB增加UserBUserList_SiteB
  • SiteBhub.Connect(...)从客户端执行,然后Clients.Client(...).DrawTree(...)执行Clients.AllExcept(...).addUser(...)
  • 前面的调用更新SiteB用户列表,并通知所有连接的客户端有一个新用户——这addUserSiteA客户端上执行以添加UserB到用户列表
  • SiteB已连接且没有活动用户,而SiteA有一个活动用户

我认为问题在于 SQL 背板只会在消息发送时处理它们,并且已经从 SQL 数据库中表的命名约定中确认了这一点。然而,内部UserList负载平衡服务器之间不同步。SiteA更新的事实UserB仅是由于连接addUser时的广播(意味着仅包含且仅包含)UserBSiteBSiteBUserBSiteAUserA

所以要更新我上面的问题,我将如何维护UserList服务器之间的关系?我会使用 SQL 背板来实现这一点吗?

4

0 回答 0