I was confined to the idea of exposing a single API to all clients. This approach from Netflix provides an alternate way to better serve clients. A good read.
I have renamed the classes from my previous example to suit the naming convention of the Disruptor-net v1.1.0 (Port of the Java Disruptor 2.7.1). Events are published by Publishers and consumed by a Consumer.
The Events (of type
Event) are Binary serilialized using ProtoBufNet and publised by multiple WCF Clients (
EventPublisher) to an WCF Service (
NetNamedPipeBinding (This can be replaced with other types of Bindings based on the need).
The Consumer consists of the
Disruptor, setup to invoke a chain of
EventHandlers in a Diamond Path configuration. The
DiamondPathEventHandlingSequencer is a simple DSL based class that encapsulates the setting of the
Disruptor for a Diamond Path event handling sequence. The
RingBuffer is filled up with instances of type
ISequencerEntry. This interface provides methods for the
IEventHandlers to read and write state of the
Event as it traverses through the Diamond Path event handling Sequence.
Three event handlers are hooked up using the
Disruptor in a Diamond Path Configuration. They resemble the architecture of LMAX explained here. They are the Journaler, UnMarshaller and Business Logic Processor. To keep the example simple I have not included the Replicator.
EventJournaler journals all incoming events to a persistant store provided by Redis.
EventAssembler deserialises the incoming Binary stream and writes the assembled Event instance back to the
EventTracker plays the role of the Business Logic Processor. In the context of this example, it just reference counts the number of events coming from each
The above 3 handlers are setup inside the
EventSequencer, a singleton wrapper over the
EventService publishes the incoming events to the
EventSequencer, which internally is publised to the
RingBuffer through the
DiamondPathEventHandlingSequencer. Subsequently the
RingBuffer takes care of invoking the Event Handlers in the appropriate sequence.
I also ran a few simple tests on my laptop, a Core i7 2.20GHz machine with 4GB memory. Below are the results.
A very trivial inference is that the Throughput of the Consumer almost equals to that of the Publiser, when there is minimal latency in the Event Handling path. So
Distruptor does its job of sequencing the events across threads in an most effective way without incurring a lock over head.
The source is available here. The Code is self explanatory. It has two parts, a Publisher and Consumer. Ensure that the Consumer is started before running the Publiser.
This had been my second adventure with
Disruptor, so any feedback on incorrect or better usage of the
Disruptor would be much appreciated.
Many of you should have been quite familiar with the Disruptor from the LMAX team. I happened to read through and did try out a sample project to see how the RingBuffer can be used with WCF.
The sample code is very simple and straight forward. It illustrates how the RingBuffer can be used to sequence calls from Multiple Producers to a Single Consumer.
The code is self explanatory if you are familiar with Disruptor internals. Here is a very brief summary of the code.
A Consumer WCF Service receives Byte Stream messages from Producers and dumps them into the
MP1CSequencingBuffer is a wrapper class around the
RingBuffer. This class abstracts away the details of setting up the
RingBuffer, the logic of adding an entry to the
RingBuffer and finally getting notified when an new item is available through the
ByteArrayItemProcessor simulates the the Business Logic processing. The incoming byte stream is de-serialized and a simple message counter is maintained to track messages from each Producer.
The Solution has 4 projects. The Disruptor, a Producer (WCF Client Console App) and a Consumner (WCF Service Console App) and a shared project with utility and shared classes.
Make sure to start the Consumer before starting the Producer.
This is my first attempt on understanding and using the Disruptor. So any feedback or improvements would be gladly accepted and greatly appreciated.
The code can be downloaded from here.
This article of mine on code project talks about one of the applications of Decorator pattern. Any GUI based application that are menu driven would have some logic to turn on / off the menu items based on different set of attributes like ( Licensing policies, user roles, application state etc ). Decorator comes handy on keeping this implementation extensible and maintainable. Here is the link to the article. Happy reading!