views:

349

answers:

4

I have create WCF Service (host on Windows Service) on load balance server. Each of this service instance maintain list of current user. E.g. Instance A has user A001, A002, A005, instance B has user A003, A004, A008 and so on.

On each service has interface that use to get user list, I expect this method to return all user in all service instance. E.g. get user list from instance A or instance B will return A001, A002, A003, A004, A005 and A008.

Currently I think that I will store the list of current users on database but this list seem to update so often.

I want to know, is it has another way to share data between WCF service that suit my situation?

+1  A: 

A database would seem to offer a persistent store which may be useful or important for your application. In addition it supports transactions etc which may be useful to you. Lots of updates could be a performance problem, but it depends on the exact numbers, what the query patterns are, database engine used, locality etc.

An alternative to this option might be some sort of in-memory caching server like memcached. Whilst this can be shared and accessed in a similar (sort of) way to a database server there are some caveats. Firstly, these platforms are generally not backed by some sort of permanent storage. What happens when the memcached server dies? Second they may not be ACID-compliant enough for your use. What happens under load in terms of additions and updates?

BrianLy
A: 

The DB option sounds good. If there are no performance issues it is a simple design that should work. If you can afford to be semi realtime and non persistent one way would be to maintain the list in memory in each service and then each service updates the other when a new user joins. This can be done as some kind of broadcast via a centralised service or using msmq etc.

Pratik
+1  A: 

Personally, the database option sounds like overkill to me just based on the notion of storing current users. If you are actually storing more than that, then using a database may make sense. But assuming you simply want a list of current users from both instances of your WCF service, I would use an in-memory solution, something like a static generic dictionary. As long as the services can be uniquely identified, I'd use the unique service ID as the key into the dictionary and just pair each key with a generic list of user names (or some appropriate user data structure) for that service. Something like:

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

Since this dictionary would be shared between two WCF services, you'll need to synchronize access to it. Here's an example.

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);
                }
            }
        }
    }
}

Given that you don't want users listed twice for a specific service, it would probably make sense to replace the List<string> with HashSet<string>.

Matt Davis
How to synchronize this data between services?
In The Pink
A: 

If you reconsider and host using IIS you will find that with a single line in a config file you can make the ASP Global, Application and Session objects available. This trick is also very handy because it means you can share session state between an ASP application and a WCF service.

Peter Wone