dispatching events to web services

Hello,

In my architecture, which is somewhat constrained due to my client’s corporate IT’s fear of the cloud and anything non-Windows, I am looking at how to dispatch events to web services that can handle them. I have two load-balanced web servers where the web services live, and a SQL Server active/passive cluster of 2 servers. Currently I have EventStore running as a Single Node service on the cluster, set up with failover, etc (I am considering other clustered alternatives for ES). I am trying to decide how best to handle subscriptions/dispatch of events in this setup. I can think of a few options, but am wondering if anyone has any advice, or alternative/better approaches.

1 - Services can subscribe directly to ES streams, would have to handle idempotence/competing consumer issues

2 - I can write my own “simple” bus process, that subscribes to events and dispatches them to services via a load-balanced URI, so that only one consumer handles them.

  • in this approach, consumers could subscribe to streams/event types using a standard API (e.g. a POST of the event itself to a URI), or it could be more complex where the bus actually does some mapping of the event to a related command, but that seems like too much coupling

3 - I could stick something like RabbitMQ in between ES and services to handle the competing consumers and other stuff, but saw in other threads most consider this overkill, which I can appreciate.

Has anyone done something similar? Any critiques or suggestions?

Thanks!

Brian

Brian,

I’m still new to ES so I hope someone will correct me if I’m making any major mistakes, but I think your tradeoffs are in scale and development / deployment convenience.

Services which subscribe directly to the streams seems like the canonically correct solution. You have to deploy a windows service for each consumer, which is a pain (albeit a small one) to develop and test. If you need competing consumers, it shouldn’t be too much trouble to deal with idempotence, but I’d suggest trying a single consumer per bounded context or event stream and see how it goes performance-wise. If your contexts are granular enough, then you should be able to process a lot of messages without needing the gold-plating of concurrency handling.

I’ve used the http dispatch method, and I like developing for it a lot. It’s really easy to build, test, and deploy small web services, and keeping things small and simple is very agile. On the other hand, I was using IronMQ in that project, and they had already build the dispatcher for me, and in your scenario you would have to maintain some sort of subscription table on the “simple bus”, so you still have a complex piece to build and support. (Definitely needs good monitoring and troubleshooting interfaces in the dispatcher…otherwise you’re blind when things go sideways.)

I don’t have much to say about using Rabbit in addition to ES. I haven’t gotten that far myself :slight_smile:

Having written all that out, I think my first essay at it would be to write single service consumers per stream, and deciding if it is painful enough to upgrade to one of the other mechanisms after trying that out a bit. (Don’t try and get it perfect the first time!)

Josh

Thanks, Josh. It might be the programmer in me, but your comments actually are making me want to go the subscription-manager route. The monitoring and coupling (or applied decoupling) of multiple single server instances seems more work, and more worrisome to me because I have some monolithic apps I need to break up already. Having something that enables easy subscription and reporting on failed event handling, downtime, etc seems more appealing, allowing me to slowly break things apart and add event pub/sub as needed. Of course, I’m probably greatly under-estimating the complexity of this, since I am a programmer. :slight_smile:

Isn’t this what relays are for? Could be wrong but that’s my understanding.

I’m a noob. What’s a relay, and how does it fit in the picture?

http://azure.microsoft.com/en-us/documentation/articles/fundamentals-service-bus-hybrid-solutions/#relays

Hope I’ve not missunderstood your problem.

Thanks. Given that I can’t use azure and am stuck with the server setup provided, I’m not sure what my relay options are or how that would

Ugh. Accidental send via my 5 year old.

Anyway, curious if/how I should set up a relay in my environment.

It seems like using the Azure Service Bus relay would be much the same as your previously discussed idea of using Rabbit do distribute the work. With the advantages and disadvantages of using the cloud for the service (which is, of course, a non-starter in your case). If the Microsoft solution is desirable, I think you can run the ‘same’ thing on premisis with Service Bus for Windows Server: http://msdn.microsoft.com/en-us/library/dn282144.aspx

I agree that implementing your own distributor sounds like a fun project. And since you’d end up essentially re-implementing RabbitMQ, you can use their source code to get you started. A gazillion other options to look at here: http://queues.io

The ZeroMQ documentation is a unbelievable reference for low level patterns in message handling ( http://zguide.zeromq.org/page:all ) that can help you make the basic decisions without the opinions and choices being made for you like they are at a higher level project. 0MQ is also blazing fast.

I think I’d still go with direct subscribers to EventStore, and work toward single-threaded processors for anything that doesn’t have the highest volume, and then handle my own idempotence when I do need a huge processing volume. But I understand the allure of making your own!

Josh

I am learning toward a very simple model of registering http callbacks for specific streams/events with a service that just manages those subscription callbacks, subscribes to ES and dispatches to callbacks, logging success or failure. I think I’d just keep the callbacks simple, with a POST to the url with the message as the body, and it can deserialize and handle as it sees fit. Again, I may be missing something, but it feels like it would work for what I need right now, and I can consider something more advanced later. I think I’ll give it a shot when I can free up some time. At the very least, it will probably show me what I’m missing :slight_smile: