Project Iris

Completely decentralized cloud messaging


Zero configuration, self organization and semantic addressing.
Perfect secrecy against passive and active attacks.
Beautiful, simple and language agnostic API.


Want to learn more? The book of Iris!

Javatars, javatars everywhere!!!

Published: Oct 6, 2014

Since the inception of the Iris messaging system, Go was the reference implementation of the client API and Erlang followed close by, these two being the only officially supported languages of the project. Alas, time went by, the project matured and it was high time to expand this exclusive club of two.

Without further ado, please welcome the JVM family of languages into the flock of officially supported Iris bindings. From today onward Java and Scala will be treated as first class citizens of Iris, including all goodies of the project: open source implementation, online executable playground (Java | Scala) and full developer documentation.

To cater for people just arriving to the project, the rest of the announcement will focus on a short but sweet quickstart guide into Iris through the JVM.

Iris background

Iris is an attempt at bringing the simplicity and elegance of cloud computing to the application layer. Consumer clouds provide unlimited virtual machines at the click of a button, but leaves it to developer to wire them together. Iris ensures that you can forget about networking challenges and instead focus on solving your own domain problems.

It is a completely decentralized messaging solution for simplifying the design and implementation of cloud services. Among others, Iris features zero-configuration (i.e. start it up and it will do its magic), semantic addressing (i.e. application use textual names to address each other), clusters as units (i.e. automatic load balancing between apps of the same name) and perfect secrecy (i.e. all network traffic is encrypted).

You can find further infos on the current website and details of the above features in the core concepts section of the book of Iris. For the scientifically inclined, a small collection of papers is also available featuring Iris. Slides and videos of previously given public presentations are published in the talks page.

There is a growing community on Twitter @iriscmf, Google groups project-iris and GitHub project-iris.

Quickstart

Iris uses a relaying architecture, where client applications do not communicate directly with one another, but instead delegate all messaging operations to a local relay process responsible for transferring the messages to the correct destinations. The first step hence to using Iris through any binding is setting up the local relay node. You can find detailed infos in the Run, Forrest, Run section of the book of Iris, but a very simple way would be to start a developer node.

> iris -dev
Entering developer mode
Generating random RSA key... done.
Generating random network name... done.

2014/10/06 07:13:47 main: booting iris overlay...
2014/10/06 07:13:47 scribe: booting with id 369650985814.
2014/10/06 07:13:57 main: iris overlay converged with 0 remote connections.
2014/10/06 07:13:57 main: booting relay service...
2014/10/06 07:13:57 main: iris successfully booted, listening on port 55555.

Since it generates random credentials, a developer node will not be able to connect with other remote nodes in the network. However, it provides a quick solution to start developing without needing to configure a network name and associated access key. Should you wish to interconnect multiple nodes, please provide the -net and -rsa flags.

Attaching to the relay

First thing's first, you'll need to obtain the JVM client library. As any decent JVM based project, the Iris client too is meant to be used through Maven Central dependencies. To get the package, add the following dependency (details for various build systems): group ID → com.karalabe.iris | artifact ID → iris | version → 1.0.0

After successfully booting, the relay opens a local TCP endpoint (port 55555 by default, configurable using -port) through which arbitrarily many entities may attach. Each connecting entity may also decide whether it becomes a simple client only consuming the services provided by other participants, or a full fledged service, also making functionality available to others for consumption.

Connecting as a client can be done trivially by invoking new Connection with the port number of the local relay's client endpoint. After the attachment is completed, a Connection instance is returned through which messaging can begin. A client cannot accept inbound requests, broadcasts and tunnels, only initiate them.

import com.karalabe.iris.*;

public static void main(String[] args) throws Exception {
  // Connect to the local relay (error handling omitted)
  final Connection connection = new Connection(55555);

  // Disconnect from the local relay
  connection.close();
}
import com.karalabe.iris._

def main(args: Array[String]) {
  // Connect to the local relay (error handling omitted) 
  val connection = new Connection(55555)

  // Disconnect from the local relay
  connection.close()
}

To provide functionality for consumption, an entity needs to register as a service. This is slightly more involved, as beside initiating a registration request, it also needs to specify a callback handler to process inbound events. First, the callback handler needs to implement the ServiceHandler interface. After creating the handler, registration can commence by invoking new Service with the port number of the local relay's client endpoint; sub-service cluster this entity will join as a member; handler itself to process inbound messages and an optional resource cap. Java shown below, Scala version can be found here.

// Implement all the methods defined by ServiceHandler (optional, defaults provided)
static class EchoHandler implements ServiceHandler {
    @Override public void init(Connection connection) throws InitializationException { }
    @Override public void handleBroadcast(byte[] message)                            { }
    @Override public byte[] handleRequest(byte[] request) throws RemoteException     { return request; }
    @Override public void handleTunnel(Tunnel tunnel)                                { }
    @Override public void handleDrop(Exception reason)                               { }
}

public static void main(String[] args) throws Exception {
    // Register a new service to the relay (error handling omitted)
    final Service service = new Service(55555, "echo", new EchoHandler());

    // Unregister the service
    service.close();
}

Upon successful registration, Iris invokes the handler's init method with the live Connection object - the service's client connection - through which the service itself can initiate outbound requests. The init is called only once and is synchronized before any other handler method is invoked.

Messaging through Iris

Iris supports four messaging schemes: request/reply, broadcast, tunnel and publish/subscribe. The first three schemes always target a specific cluster: send a request to one member of a cluster and wait for the reply; broadcast a message to all members of a cluster; open a streamed, ordered and throttled communication tunnel to one member of a cluster. The publish/subscribe is similar to broadcast, but any member of the network may subscribe to the same topic, hence breaking cluster boundaries.

Presenting each primitive is out of scope, but for illustrative purposes the request/reply was included. Given the echo service registered above, we can send it requests and wait for replies through any client connection. Iris will automatically locate, route and load balanced between all services registered under the addressed name. Scala shown below, Java version can be found here.

val request = "Some request binary".getBytes
Try(connection.request("echo", request, 1000)) match {
    case Success(reply) => System.out.println("Reply arrived: " + new String(reply))
    case Failure(error) => System.out.println("Failed to execute request: " + error.getMessage)
}

Advanced topics and goodies

To keep this announcement at a reasonable length, more advanced topics have been left for the official quickstart guides available at the project's GitHub repos: Java and Scala. Among others, these include details discussions on:

You can find a teaser presentation, touching on all the key features of the libraries through a handful of challenges and their solutions. The recommended versions are the playground ones (Java | Scala), containing modifiable and executable code snippets, but read only versions (Java | Scala) are also available.

Acknowledgments and wrap up

I would also like to take the opportunity to thank a handful of contributors for the valuable source code additions to the project, alphabetically: Bas van Ooyen (Go client), Lőrinc Pap (Java client), Philipp Brüll (Iris core) and Róbert Roth (Java client).

Finally, I am still actively looking for an official backer who would be interested in taking Iris to the next level and turning it into an industrial strength project. If you are interested, or know of such a person, please contact me at peterke@gmail.com.