在.NET应用程序实例之间共享数据的最佳方式?

时间:2009-09-04 01:46:22

标签: wcf state load-balancing

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

在每个服务上都有用于获取用户列表的界面,我希望这个方法能够返回所有服务实例中的所有用户。例如。从实例A或实例B获取用户列表将返回A001,A002,A003,A004,A005和A008。

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

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

5 个答案:

答案 0 :(得分:2)

就个人而言,基于存储当前用户的概念,数据库选项对我来说听起来有些过分。如果您实际存储的不止于此,那么使用数据库可能有意义。但假设您只需要来自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<string>替换为HashSet<string>可能是有意义的。

答案 1 :(得分:1)

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

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

答案 2 :(得分:1)

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

只有更新我会这样做有一个节点只会将其可用用户列表返回给它的对等体,而对等体将把它与现有列表结合起来。然后将其现有列表返回给调用的对等方。这就是所有同行如何与同一个列表同步。

答案 3 :(得分:0)

数据库选项听起来不错。如果没有性能问题,那么它应该是一个简单的设计。如果您能够实现半实时和非持久性,则可以在每个服务中维护内存中的列表,然后每个服务在新用户加入时更新另一个服务。这可以通过集中服务或使用msmq等进行某种广播。

答案 4 :(得分:0)

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