views:

436

answers:

4

(Edited to try to explain better)

We have an agent, written in C++ for Win32. It needs to periodically post information to a server. It must support disconnected operation. That is: the client doesn't always have a connection to the server.

Note: This is for communication between an agent running on desktop PCs, to communicate with a server running somewhere in the enterprise.

This means that the messages to be sent to the server must be queued (so that they can be sent once the connection is available).

We currently use an in-house system that queues messages as individual files on disk, and uses HTTP POST to send them to the server when it's available.

It's starting to show its age, and I'd like to investigate alternatives before I consider updating it.

  1. It must be available by default on Windows XP SP2, Windows Vista and Windows 7, or must be simple to include in our installer. This product will be installed (by administrators) on a couple of hundred thousand PCs. They'll probably use something like Microsoft SMS or ConfigMgr. In this scenario, "frivolous" prerequisites are frowned upon. This means that, unless the client-side code (or a redistributable) can be included in our installer, the administrator won't be happy. This makes MSMQ a particularly hard sell, because it's not installed by default with XP.

  2. It must be relatively simple to use from C++ on Win32. Our client is an unmanaged C++ Win32 application. No .NET or Java on the client.

  3. The transport should be HTTP or HTTPS. That is: it must go through firewalls easily; no RPC or DCOM.
  4. It should be relatively reliable, with retries, etc. Protection against replays is a must-have.
  5. It must be scalable -- there's a lot of traffic. Per-message impact on the server should be minimal.
  6. The server end is C#, currently using ASP.NET to implement a simple HTTP POST mechanism.
  7. (The slightly odd one). It must support client-side in-memory queues, so that we can avoid spinning up the hard disk. It must allow flushing to disk periodically.
  8. It must be suitable for use in a proprietary product (i.e. no GPL, etc.).
A: 

Last time I wanted to do any messaging I used C# and MSMQ. There are MSMQ libraries available that make using MSMQ very easy. It's free to install on both your servers and never lost a message to this day. It handles reboots etc all by itself. It's a thing of beauty and 100,000's of message are processed daily.

I'm not sure why you ruled out MSMQ and I didn't get point 2.

Quite often for queues we just dump record data into a database table and another process lifts rows out of the table periodically.

Robert
MSMQ is ruled out because it requires that the administrator install something other than our product on the PC. That is: we can't depend on anything external to our MSI unless it's installed on the vast majority of XP PCs.
Roger Lipscombe
Not considering MSMQ is a Big Mistake. It is *very* good at what it does, anything you come up to replace it is going to suck. Installing it is trivial.
Hans Passant
Is installing it in an automated fashion on 100,000 machines across an enterprise trivial?
Roger Lipscombe
A: 

How about using Asynchronous Agents library from .NET Framework 4.0. It is still beta though.

http://msdn.microsoft.com/en-us/library/dd492627(VS.100).aspx

Jagannath
Interesting, but: (a) we need queued/offline/disconnected operation, and (b) we're stuck with using Visual C++ 2008 runtimes for the client (no .NET). We are allowed to use .NET 3.5 on the server (but still no .NET 4.0)
Roger Lipscombe
+1  A: 

To be honest, the requirements listed don't make a lot of sense and show you have a long way to go in your MQ learning. Given that, if you don't want to use MSMQ (probably the easiest overall on Windows -- but with [IMO severe] limitations), then you should look into:

qpid - Decent use of AMQP standard

zeromq - (the best, IMO, technically but also requires the most familiarity with MQ technologies)

I'd recommend rabbitmq too, but that's an Erlang server and last I looked it didn't have usuable C or C++ libraries. Still, if you are shopping MQ, take a look at it...

[EDIT]

I've gone back and reread your reqs as well as some of your comments and think, for you, that perhaps client MQ -> server is not your best option. I would maybe consider letting your client -> server operations be HTTP POST or SOAP and allow the HTTP endpoint in turn queue messages on your MQ backend. IOW, abstract away the MQ client into an architecture you have more control over. Then your C++ client would simply be HTTP (easy), and your HTTP service (likely C# / .Net from reading your comments) can interact with any MQ backend of your choice. If all your HTTP endpoint does is spawn MQ messages, it'll be pretty darned lightweight and can scale through all the traditional load balancing techniques.

Shaun
Granted, I've never done anything with off-the-shelf MQ before. Educate me. I can't use HTTP POST, because the client and server may not be connected. I need the messages queued on the client...
Roger Lipscombe
Start with the whitepapers on the zeromq site as a good place to begin. The client architecture sounds more like a "smart client" type of thing with you deciding what to do with the "message" based on the detected connection state. That could be as simple as using something like Sqlite to store the "messages" while in offline state and then processing everything in the db once the connection is reestablished. No need to make it overly complex with full-blown MOM.
Shaun
A: 

How is your current solution showing its age?

I would push the logic on to the back end, and make the clients extremely simple.

  1. Messages are simply stored in the file system. Have the client write to c:/queue/{uuid}.tmp. When the file is written, rename it to c:/queue/{uuid}.msg. This makes writing messages to the queue on the client "atomic".

  2. A C++ thread wakes up, scans c:\queue for "*.msg" files, and if it finds one it then checks for the server, and HTTP POSTs the message to it. When it receives the 200 status back from the server (i.e. it has got the message), then it can delete the file. It only scans for *.msg files. The *.tmp files are still being written too, and you'd have a race condition trying to send a msg file that was still being written. That's what the rename from .tmp is for. I'd also suggest scanning by creation date so early messages go first.

  3. Your server receives the message, and here it can to any necessary dupe checking. Push this burden on the server to centralize it. You could simply record every uuid for every message to do duplication elimination. If that list gets too long (I don't know your traffic volume), perhaps you can cull it of items greater than 30 days (I also don't know how long your clients can remain off line).

This system is simple, but pretty robust. If the file sending thread gets an error, it will simply try to send the file next time. The only time you should be getting a duplicate message is in the window between when the client gets the 200 ack from the server and when it deletes the file. If the client shuts down or crashes at that point, you will have a file that has been sent but not removed from the queue.

If your clients are stable, this is a pretty low risk. With the dupe checking based on the message ID, you can mitigate that at the cost of some bookkeeping, but maintaining a list of uuids isn't spectacularly daunting, but again it does depend on your message volume and other performance requirements.

The fact that you are allowed to work "offline" suggests you have some "slack" in your absolute messaging performance.

Will Hartung
It's showing its age in that the queuing logic is tied up with the message formatting logic, and with the encryption logic. Unlike most messaging systems, the messages aren't opaque (making them difficult to evolve). Before I attempt to refactor or rewrite it (or just suck it up), I'd like to explore my options.
Roger Lipscombe
I see, so the problems isn't the tranport, it's the payload. All of these suggestions are pretty much payload neutral and deal with infrastructure. If you're more interested in payload, you may want to edit or post a new question.
Will Hartung