Recently, I was onsite with a client who had one particular use case utilizing the TCP protocol. Their own customers register by opening a TCP connection to their server. Once the connection is open, their customers will receive a stream of updates from the server. More than one customer can connect to the same port. This is similar to JMS topics, but running on raw TCP and using a custom protocol.
Due to the custom protocol being widely used within the organisation, we were not allowed to change it. The reason being that all of the customers would have needed to make major changes. Hence technologies like JMS and ZeroMQ were immediately ruled out.
Our client already had a working system, so our job here was to come up with an easy to use transport that can do all of this in order to improve their system running on Mule. Our solution: create a new TCP transport based on Netty.
Netty is an asynchronous event-driven network application framework. It’s widely used to implement high performance protocol servers and clients.
Some of it’s features include:
- Unified API for various transport types – blocking and non-blocking socket
- Highly customisable thread model – single thread, one or more thread pools such as SEDA
- Minimised unnecessary memory copy
More information can be found on the Netty website.
I’ll walk you through an example of how to use this transport. On the connector, you configure the publishers you need, and their associated ports, like this:
<nettypublisher:config name="nettyPublisher" nettyPublisherName="nettyPublisher"> <nettypublisher:publishers> <nettypublisher:publisher key="publisher1">8091</nettypublisher:publisher> <nettypublisher:publisher key="publisher2">8092</nettypublisher:publisher> </nettypublisher:publishers> </nettypublisher:config>
Then in your flow, you can send messages on your publishers, like so:
<flow name="testFlow"> <vm:inbound-endpoint path="toPublisher" /> <logger message="#[payload]" level="INFO" /> <nettypublisher:publish publisher="publisher1" data="#[payload]"/> </flow>
In the above flow, any user connected to port 8091 (publisher1), will receive a copy of the messages received on the VM inbound endpoint.
Apart from having the ability to publish, the Netty transport can also start a server and be used like an inbound endpoint:
<flow name="testFlow"> <nettypublisher:server port="8090"/> <logger message="#[payload]" level="INFO" /> <!-- data="#[payload]" is the default --> <nettypublisher:publish publisher="publisher2" /> </flow>
The transport is published on GitHub and can be found here: https://github.com/Ricston/mule-transport-netty-publisher.
This transport at the moment is in its early stages of development. One limitation is that the payload is assumed to be a String. Also currently there isn’t a client implementation to replace the tcp:outbound-endpoint. Finally, the Netty threads cannot yet be configured. These features are in the pipeline.
The transport is released under the Apache 2.0 License. Feel free to use it as is, fork it and improve, or anything else that takes your fancy…