Ideas
- Only use TCP.
- Use ASCII. Binary protocols are harder.
- Eliminate multiple exchanges per virtual server. server = exchange.
- Eliminate multiple types of exchanges. Only have the "topic" exchange (which is the one which allows matching on simple regular expressions).
- Eliminate message priorities. (Handle this in the application. e.g. append
.emergencyto the routing key.) - Eliminate message meta-data. Mime-types? give me a break. The application can handle that.
- Eliminate transactions. Just a simple response once the message has been received by the exchange. (Applications can implement transactions themselves on top of the protocol.)
- Eliminate resuming message uploads. (Applications can split large pieces of data into multiple messages themselves.) Might even have an explicit maximum message size, say, 500kb.
- Keep the various queue settings (durable, exclusive, auto-delete).
- Eliminate possibility of durable messages. Queues too? Disk access = death.
- Do not include timestamps in the protocol. Allow applications to handle that themselves. (Although it would be nice for a consumer to know how many seconds the message has been sitting in queue.)
- Eliminate complex bindings. Only use pattern matching. One or more bindings per queue - the bindings are deleted when the queue is deleted. Bindings are created with queue creation and afterwards immutable.
- I'm torn on the issue of access control. AMQP itself doesn't specify much. user/password logins without SSL are arguably more harm than benefit - and it certainly complicates clients. Maybe just leave access control out of the specification and if it is needed use SSL. Systems like memcached have been wildly successful without ACL.
- Possibly split the server across two ports. One for producers one for consumers. This would simplify SSL settings.
So the protocol might look like this (client commands in red, server responses in black)
- Producers only produce messages. Nothing else. They connect and send messages like this:
MESSAGE irc.ruby_lang 11 hello world\r\n
The stringirc.ruby_langis the routing key. 11 is the content-length. The server responds withMESSAGE_CREATED 1\r\n
meaning it got the message and it was put into one queue. - Consumers deal with the bulk of the processing. First the they can create queues and bindings
CREATE_QUEUE irc.ruby_lang\r\n CREATE_BINDING irc.ruby_lang irc.ruby*\r\n
The server would respond withQUEUE_CREATED\r\n BINDING_CREATED\r\n
Then they can subscribe to a queueSUBSCRIBE irc.ruby_lang\r\n
And the server will start sending them messages which will look like thisMESSAGE (queue) (message-id) (message-routing-key) (seconds-in-queue) (content-length) (data)
For exampleMESSAGE irc.ruby_lang 1234554321 irc.ruby_lang 0 11 hello world\r\n
After each message received by the consumer it should send an acknowledgment.MESSAGE_RECEIVED 1234554321\r\n
Then there will be the various other commandsUNSUBSCRIBE irc.ruby_lang\r\n DELETE_BINDING irc.ruby_lang irc.ruby*\r\n DELETE_QUEUE irc.ruby_lang\r\n
To which the server respondsUNSUBSCRIBED irc.ruby_lang\r\n BINDING_DELETED\r\n QUEUE_DELETED irc.ruby_lang\r\n
- Producers, consumers, and servers should all respond to
PINGwithPONG.