【问题标题】:Best way to share data between .NET application instance?在 .NET 应用程序实例之间共享数据的最佳方式?
【发布时间】:2011-08-11 11:34:12
【问题描述】:

我在负载平衡服务器上创建了 WCF 服务(Windows 服务上的主机)。每个服务实例都维护当前用户的列表。例如。实例A有用户A001、A002、A005,实例B有用户A003、A004、A008等。

每个服务都有用于获取用户列表的接口,我希望此方法返回所有服务实例中的所有用户。例如。从实例 A 或实例 B 获取用户列表将返回 A001、A002、A003、A004、A005 和 A008。

目前我认为我会将当前用户的列表存储在数据库中,但这个列表似乎经常更新。

我想知道,是否有另一种适合我情况的 WCF 服务之间共享数据的方式?

【问题讨论】:

标签: wcf state load-balancing


【解决方案1】:

就个人而言,仅基于存储当前用户的概念,数据库选项对我来说听起来有点过头了。如果您实际上存储的不止这些,那么使用数据库可能是有意义的。但假设您只需要 WCF 服务的两个实例中的当前用户列表,我将使用内存解决方案,类似于静态通用字典。只要可以唯一标识服务,我就会使用唯一的服务 ID 作为字典中的键,并将每个键与该服务的通用用户名列表(或一些适当的用户数据结构)配对。比如:

private static Dictionary<Guid, List<string>> _currentUsers;

由于此字典将在两个 WCF 服务之间共享,因此您需要同步对它的访问。这是一个例子。

public class MyWCFService : IMyWCFService
{
    private static Dictionary<Guid, List<string>> _currentUsers =
        new Dictionary<Guid, List<string>>();

    private void AddUser(Guid serviceID, string userName)
    {
        // Synchronize access to the collection via the SyncRoot property.
        lock (((ICollection)_currentUsers).SyncRoot)
        {
            // Check if the service's ID has already been added.
            if (!_currentUsers.ContainsKey(serviceID))
            {
                _currentUsers[serviceID] = new List<string>();
            }
            // Make sure to only store the user name once for each service.
            if (!_currentUsers[serviceID].Contains(userName))
            {
                _currentUsers[serviceID].Add(userName);
            }
        }
    }

    private void RemoveUser(Guid serviceID, string userName)
    {
        // Synchronize access to the collection via the SyncRoot property.
        lock (((ICollection)_currentUsers).SyncRoot)
        {
            // Check if the service's ID has already been added.
            if (_currentUsers.ContainsKey(serviceID))
            {
                // See if the user name exists.
                if (_currentUsers[serviceID].Contains(userName))
                {
                    _currentUsers[serviceID].Remove(userName);
                }
            }
        }
    }
}

鉴于您不希望用户为特定服务列出两次,将 List&lt;string&gt; 替换为 HashSet&lt;string&gt; 可能是有意义的。

【讨论】:

  • 如何在服务之间同步这些数据?
【解决方案2】:

数据库似乎提供了一个持久性存储,它可能对您的应用程序有用或重要。此外,它还支持可能对您有用的交易等。大量更新可能是性能问题,但这取决于确切的数字、查询模式是什么、使用的数据库引擎、位置等。

此选项的替代方案可能是某种内存缓存服务器,例如 memcached。虽然这可以以与数据库服务器类似(某种)的方式共享和访问,但有一些警告。首先,这些平台通常没有某种永久存储支持。当 memcached 服务器死机时会发生什么?其次,它们可能不够符合 ACID 标准,无法供您使用。在添加和更新方面在负载下会发生什么?

【讨论】:

    【解决方案3】:

    我喜欢记忆中的方式。实际上,我正在为我现在正在工作的一个项目设计相同的机制。这适用于您没有机会访问数据库或某些人真的不愿意创建表来存储简单信息(例如针对机器名称的用户列表)的情况。

    只有更新我会做一个节点只会将其可用用户列表返回给其对等方,并且对等方会将其与其现有列表相结合。然后将其现有列表返回给调用的对等方。这就是所有对等点如何与同一个列表同步。

    【讨论】:

      【解决方案4】:

      DB 选项听起来不错。如果没有性能问题,那么它应该是一个简单的设计。如果你能负担得起半实时和非持久性的一种方法是在每个服务的内存中维护列表,然后每个服务在新用户加入时更新另一个服务。这可以通过集中式服务或使用 msmq 等作为某种广播来完成。

      【讨论】:

        【解决方案5】:

        如果您重新考虑并使用 IIS 进行托管,您会发现只需在配置文件中添加一行即可使 ASP 全局、应用程序和会话对象可用。这个技巧也很方便,因为它意味着您可以在 ASP 应用程序和 WCF 服务之间共享会话状态。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2010-10-11
          • 2011-11-06
          • 2017-06-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多