WCF Duplex Communications in a clustered environment

邮差的信 提交于 2019-12-05 20:03:23

Assuming you have zero control of your environment beyond what you can install on each server (i.e. no MSMQ, no ESB, etc.), then I would look into using WCF to communicate between servers. The simple problem seems to be that you have an in-memory list that needs to remain synced between the two servers, and whenever the contents of the list changes, users of both servers need to be notified.

With an internal WCF service that both servers host and use, you could use simple fire-and-forget messaging to keep the lists in sync. Imagine the following scenario:

  1. 'User A' logs in to Server A
    1. Add 'User A' to list of online users
    2. Fire message to Server B to notify it of added 'User A'
      1. Causes Server B to add 'User A' to its list of online users
      2. Causes Server B to notify all users of user login
    3. Notify all users on Server A of user login
  2. 'User B' logs in to Server B
    1. Add 'User B' to list of online users
    2. Fire message to Server A to notify it of addd 'User B'
      1. Causes Server A to add 'User B' to its list of online users
      2. Causes Server A to notify all users of user login
    3. Notify all users on Server B of user login
  3. 'User A' logs off of Server A
    1. Remove 'User A' from list of online users
    2. Fire message to Server B to notify it of removed 'User A'
      1. Causes Server B to remove 'User A' from its list of online users
      2. Causes Server B to notify all users of user logoff
    3. Notify all users on Server A of user logoff
  4. Periodically, have Server A and Server B sync their lists with each other (Could be implemented Ping-Pong style...one server pings its list to other server, other server merges and pongs merged list back)

The above scenario obviously assumes that you have the ability to install WCF services on your hosted servers such that they can communicate with each other. I am not sure if you have the ability, internally to each server, to know of the other servers, as you mentioned all traffic had to go through a load balancer.

Assuming you don't need real time type of notification, a typical method would be to use a backend Session database or dedicated session server so that all your current logged in users are visible to all clustered machines. Then you could write a polling service to sent change notifications, or something more advanced depending on your requirements.

In your example, you would move the 'in-memory' user list to a shared memory server or shared database. You could of course implement some sort of cluster update notification to send to all machines, but the complexity of that could be way beyond your needs.

Can the servers communicate directly with each other? If so, you might want to set up private endpoints that only other servers in the farm can connect to. Then when server C receives a message, it sends a message to server A informing it of this fact, and then server A can forward this along to its clients.

Use Memcached or MSMQ.

With Memcached, you would use it as the single point of truth for all items that need to be broadcast. So, when you get a client login, you dump some simple data into Memcached. It notifies the other server and updates the other server's list. Then, when you publish the information, query Memcached.

With MSMQ, push the login info to a queue, then implement listeners on both servers, reading from the queue and updating their in-memory lists of "publishable" information. That way, both servers are kept informed of the data that needs to get published.

Does your solutions provider use MS SQL for a database server? If you have full rights to MS SQL database, you could implement T-SQL triggers. You could write a trigger that executes code when a database CRUD operation occurs. With the current version of MS SQL you can even execute managed (C#/VB#) code.

This solution would be very complex but possible. I would use a central MS SQL for your cluster and write some T-SQL trigger code. When the records you care about are modified/etc I would have the SQL server send special HTTP web request messages to the other servers in the cluster (Assuming that a server IN the cluster, can arbitrarily talk to other/all cluster servers) to let them know about any changes. Then each server could use the global application cache to broadcast changes to each session on the server.

That's my off-the-top suggestion.

-Jeff

Looks like you need to use a peer-peer network (netPeerTcpBinding). I'm not sure if you're hosting environment would support this.

http://msdn.microsoft.com/en-us/library/cc297274.aspx

You can configure your web farm with "Sticky IP".

That means that when a client connects to a web farm he is routed to one machine. All following requests from that client will go to the same machine on the farm. This works a bit like the routing service you've described in your question.

EDIT

It is probably simplest to implement a polling system where the silverlight client asks the web server "is there anything new for me", that request would contain the time of the last time the client asked. The list of new things would be stored in a database table. So no problem which web server you hit.

Also, you need to watch out for limitations in Silverlight WCF, if I understand correctly it does not implement all of WCF.

EDIT 2

In the case that you need to communicate to all users at the same time, the call does not need to go all the way down to the database. This can be cached in memory at the WCF service level, the other clients will get this from memory, giving you better performance and less load on the database.

EDIT 3

As long as you are using a silverlight client it is difficult for the clients to communicate directly with each other. There are two possiblities although they require extra work/cost:

  • use Azure service bus, each client talks to an endpoint in the cloud which is converted to direct communication.
  • Drop using silverlight, use a client that can expose a WCF service endpoint. When the client starts up it registers the endpoint with the server. Each client can then ask the server who is online and send a message directly to the client.

the velocity project from MS might be a faster solution for you than a database backend; it's a in-memory cache layer with all the clustering/fail-over fancy stuff...you can slide it in between WEB and DB layer; its API is quite simple and consistent with the rest of .NET too.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!