Question

I recently worked in a larger project where I touched the topic of distributed systems in the c# world the first time.
I found that wcf is fantastic for remote procedure calls, but how do you add event communication between services using only wcf?

Here the project requirements:

  • We had ~15 different services for different aspects of the whole system
  • each service ran in its own process
  • WPF clients could use RPC on the services and could subscribe to service events
  • the services needed to do RPC on each other and also subscribed to events of other services
  • services were hosted on the same machine and on different machines within local ethernet
  • communication was via TCP
  • They were all long running services (planned uptime ~2 years)
  • The system manages long running company workflows
  • eventing was realized via a publisher and subscriber
  • events must not be lost
  • during busy hours many events have to be managed between all services

Now the evil part: for event communication, a central publish-subscribe service was used. For every subscriber it had (multiple) callback channels and kept them open forever (via a keep-alive-ping). Well I read: keeping WCF channels open forever is kind of a WCF-antipattern. We also had many problems with that solution.

Is there a better alternative than one of these?

  1. Use a message queueing system (like MSMQ, RabbitMQ, ZeroMQ...)
    Downsides:

    • You can not only use WCF
    • you have to deploy an addtitional Queueing system (while ZeroMQ would only be a dll!)
    • more wrapping code will be needed to handle the queues
    • as far as I saw you normally need to poll the queues
  2. Use simple or long polling
    Downside:

    • this will produce quite some network traffic
  3. Use Observer Pattern (implement RegisterListener/HandleEvent RPCs with WCF)
    Downsides:

    • Events can only be consumed by WCF services, not by WPF clients
    • Additional wrapping code is needed
Was it helpful?

Solution

The requirements hint towards "message queueing". Essentially, the need to never lose events requires persistence. That, along with the need to track which events were processed (to "consume" them), is elegantly solved by using a message queueing system, and many of them would also give you the Publish/Subscribe capabilities out of the box.

WCF supports transparent message queueing via special bindings. WCF comes out of the box with a binding for MSMQ. There are 3rd party bindings for other messaging systems, like a RabbitMQ binding. These bindings allow you to keep the simple WCF programming model and avoid polling.

In any case, even if you let go of WCF, you don't need to poll the queues: most queueing systems support push-based APIs. In .NET it is manifested as either event-based API (an OnMessage event) or an IEnumerable which you can use in a foreach loop.

Licensed under: CC-BY-SA with attribution
scroll top