【问题标题】:Use static dictionary in asp.net web application在 asp.net Web 应用程序中使用静态字典
【发布时间】:2019-12-03 20:00:48
【问题描述】:

我在我的 asp.net Web 应用程序中使用 SignalR。 SignalR 集线器中不存在会话状态,因此我决定将 username <-> connectionId 对保存在静态字典中。

public static class UsernameConnectionsMaps
{
    private static Dictionary<string, string> data = new Dictionary<string, string>();

    public static void Add(string username, string connectionId)
    {
       data[username] = connectionId;
    } 

    public static string Get(string username)
    {
       return data[username];
    }

    public static void Remove(string username)
    {
       return data.Remove(username);
    }  
}

在特定的控制器请求中,我想使用 signalR 向客户端发送数据。知道当前用户的用户名,我可以很容易地为客户端获取 connectionId 并发送数据。

我在控制器中使用Get 方法。 我在 hub 的 OnConnected()OnDisconnected() 方法中分别使用了 AddRemove 方法。

我感兴趣的是,此解决方案是否会对我的 Web 应用程序中的线程安全(或其他)有任何问题?有什么更好的方法?

【问题讨论】:

  • 我假设任何给定点只有一个会话将用于一个用户
  • 我能想到的主要问题是,如果应用程序池被回收(通常在 IIS 中定期自动发生),那么您将丢失内存中的连接列表,这显然会给您带来问题。最好将其保存在数据库之类的地方,恕我直言
  • 如果你要使用字典,你应该使用ConcurrentDictionary 来保证线程安全。话虽如此,更常见的做法是将会话标识符存储在 cookie 中,使用加密随机标识符或某种形式的加密或防篡改。

标签: c# asp.net signalr


【解决方案1】:

如果您使用静态字典,您将无法使用scale out 您的 API。 每个实例都会保留一个不同的静态字典,因此通知不会总是到达它们的目的地,考虑azure signalr 或某种持久性存储,如 redis。

【讨论】:

  • 没有计划扩展这个应用程序,但如果有的话,这是个好点
  • 即使您不打算横向扩展,如果应用程序池回收,您也会丢失数据。
【解决方案2】:

您可以做的最好的事情就是 Microsoft 文档中所说的,将用户映射到组,即使它会生成具有单个用户的组或具有实际上是同一用户的许多用户的组。即使您将使用Redis backplaneAzure SignalR,您也将拥有所有上下文中的组,并且可以与它们进行通信、添加、删除等......

单个用户可以与 SignalR 应用建立多个连接。例如,用户可以在他们的桌面和手机上进行连接。每个设备都有一个单独的 SignalR 连接,但它们都与同一个用户相关联。如果向用户发送消息,则与该用户关联的所有连接都会收到该消息。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-12-18
    • 2019-08-10
    • 1970-01-01
    • 1970-01-01
    • 2018-08-04
    • 1970-01-01
    • 1970-01-01
    • 2010-10-30
    相关资源
    最近更新 更多