Java continues to be a go-to language for the development of various desktop and server applications, and as such our developers continue to use Java to fit our clients’ specifications. However, we’ve found that Java tends to be a bit lacking when it comes to developing redundant software. Clients expect that their services be up and running 100% of the time, and if you’re using Java that’s nearly impossible to do without building redundant systems. We needed to develop a library that provided the easy transmission of application data between backend instances so that, in conjunction with properly-configured load balancing software, we could provide backend instances to power our services that would, in the eyes of the user, always be available.
Java already has the ability to open network connections over TCP to other applications, but the specification by which data was transmitted hasn’t been clearly defined from application to application — clearly because each application is different. We needed to build something that acted as the middle ground. That is, we needed the ability to define the specification for the data that would be transmitted between applications, but we certainly did not want to re-invent the wheel for each application we wrote. While some solutions existed that would allow peer-to-peer connectivity, none provided the general functionality that we needed. Our solution to this problem was BoneMesh — an application-level fully-connected network for Java. It works by passing JSON messages (which can be easily serialized and deserialized) between nodes, while allowing the developer to specify the node instead of needing to manually track down the IP addresses of various nodes.
Features of Interest
We took advantage of the nature of the higher levels of the OSI model that BoneMesh operates on by passing entire JSON objects instead of handcrafted messages. The JSON object contains the name of the intended target, the scope of the message, and the data itself — which allows for embedded metadata within the object itself to route the message to various modules in the intended target.
As previously mentioned, BoneMesh allows us to easily stand up redundant backend instances without needing to rely on self-synchronizing databases. This allows us to upgrade instances in true blue-green fashion one instance at a time without impacting the user experience in a negative fashion. Developers can leverage the ability to embed custom metadata to indicate message versions and write adapters accordingly, so that old data formats can be transformed into new data formats while upgrades are in progress without making it necessary to shut down the backend ecosystem in its entirety.
In addition, BoneMesh provides for interoperability between different kinds of applications, because TCP and JSON are certainly not dependent on language or platform. If two different applications are written in Java, they can both use BoneMesh to communicate, even if their inherent functions are different. If an application is written in a language other than Java and is able to send and read from TCP sockets, it can still send messages to a BoneMesh-enabled application (though we haven’t provided a library to do so in other languages). Of course, the application-specific transmission specification would still need to be codified.
The version currently published (version 1.2.1) acts as a fully-connected network, but there are many improvements that need to be developed. For one, we want BoneMesh to eventually be a virtual mesh network — but point-to-point connections are currently required. For a node (one of n nodes) to be fully connected, it must connect to all other (n-1) nodes. We find this to be okay for stationary applications, but one-time applications or applications that do not have physical access to the n-1 nodes will have a hard time pushing data to nodes that are not immediate neighbors without an extra application relay, which unnecessarily burdens the developer.
Second, BoneMesh only supports push notifications from node to node. This is excellent for asynchronous applications or for actions that take a while to fully execute, but it requires a dedicated endpoint for at least one out of any two nodes that are connected. For roaming applications, the workaround is to provide at least one dedicated endpoint, but forces the network into a star-like topology and can increase the risk of forming a bottleneck. Furthermore, it makes it harder for nodes behind firewalls to communicate with the rest of the network (although, WireGuard provides us with a workaround for this).
Third, BoneMesh does not inherently encrypt data. At Axonibyte, we often use BoneMesh in conjunction with WireGuard and other application-level libraries to encrypt data transmissions from server to server. However, this is yet another burden on the developer, so we plan on making it an option to encrypt BoneMesh communications in the future.
We hope to implement these additions in the very near future.
Free, Libre, Open Source Software (FLOSS)
At Axonibyte, we want to contribute to the open source community, and so we’ve released BoneMesh to the community. It is available on Maven Central and through our website at bonemesh.axonibyte.com. It should be noted that this software is still strongly in beta — it can stand to undergo many improvements. As such, we encourage members of the community to take a look, contribute, audit, and use the library as they see fit.