19 June 2015

Idea: Messaging over WebSocket

WebSockets seems to be an ideal protocol for messaging systems. However there are scarcely any specs that take advantage of it. Some of the ones I found are SwaggerSocket and WAMP (Web Application Messaging Protocol, not to be confused with Windows, Apache, MySQL, and PHP). But these don't quite hit the target I'm going for. WAMP, for instance, concentrates on RPC and pub/sub. SwaggerSocket goes a step too far and implements REST over WebSocket. So, I began to wonder what it would take to make an effective messaging system over WebSockets.

The minimum things (I can think of) needed to process a message on the server are: A way to route the message, and a way to deserialize the message payload. An added wrinkle is that web sockets are fully asynchronous, unlike HTTP which is typically request/response with only I/O being asynchronous (on the client anyway).

The perfect candidate to specify routing is a URI path (e.g. /system/boundedcontext/aggregate/message). And my first thought for a "wire" format for the message payload was JSON. So it naturally follows that an HTTP message would fit as a wire format for messaging over a web socket, since it has path and payload. Using HTTP messages, you could also specify different message formats with headers.

However with messaging, one feature we really don't need from HTTP is verb usage. The route (aka message name) is semantic and, if following CQRS patterns, is itself already a verb which conveys intent. Likely, a lot of the other parts of the HTTP spec are also unnecessary for messaging. A default subset could be used so it works with existing HTTP parsers. For instance, always using POST or PUT so a payload can be included. For HTTP verb militants, either verb could be argued: creating new messages to process or sending message payloads which update some other resource.

Aside
Another pattern that some people use is posting messages to return view data. That would typically be the domain of a regular HTTP GET. However, a GET can be insufficient when performing a query with complex parameters, since GETs can't have a message payload attached, and complex query parameters are troublesome. This (messaging for views) is also handy when you need to coordinate resources across different read models / services before returning a coherent view. Such a pattern would also fit nicely into messaging over web socket, but is optional.

How to implement? On the server side, there are already numerous web server implementations which parse and handle HTTP requests. One of these could be leveraged. The next step is to register a route with a handler so the message can be delivered. Deserialization can also be part of the pipeline if the deserialization format (e.g. class) is registered along with the route. The handlers themselves could be agents or actors or whatever computational model suits your fancy. One of the things I'm interested in based on reading about the Orleans framework is the virtual actor approach.

This approach could already be used on top of regular HTTP without websockets, so all the components are already out there. They just need to be assembled in such a way to easily take advantage of websocket performance, and mitigate the difficulty of full asynchrony. Maybe in my spare time... hah!

No comments: