Elixir is a fascinating programming language that is built on top of Erlang and puts a modern twist on a very robust programming language. One of the many intriguing features about the programming language is that it inherently promotes building distributed systems by having a built-in distribution protocol. In this post, I’ll describe this distribution protocol, its shortcomings, and how coupling it with an event broker can make distributed programming with Elixir more robust.
In Elixir, a node is a running instance of an Elixir process. Elixir also has message passing functionality built into the language and takes care of moving messages between nodes – no matter where the node is running. The nodes could be on the same VM on the same underlying host, or they could be on multiple machines within your network, or they can even be spread across the network – the location of the node is not something you have to be concerned about when coding in Elixir.
To show you how simple it is to spin up a node and add a hello world function, here are the commands you would run using the Interactive Elixir CLI:
$ iex --sname node1 Interactive Elixir - press Ctrl + C to exit (type h() ENTER for help) iex(node1@localhost)1> defmodule Hello do ...> def world, do: IO.puts "hello world" ...> end
Now what if we wanted to call this “hello world” code from another node and link it to the node?
$ iex --sname node2 iex> Node.spawn_link :"node1@localhost", fn -> Hello.world end #PID<9014.59.0> hello world
Pretty nifty right? With just a few lines of code, we spun up two Elixir nodes and linked them together.
While the built-in distributed messaging constructs within Elixir are convenient, it does suffer from some draw backs which I’d like to highlight below:
Solace PubSub+ Event Broker is a multi-protocol, enterprise-grade event broker that can help us close the gaps we mentioned above. In addition, it comes in multiple form factors a Hardware Appliance, a Software Broker and a SaaS offering – all three are completely interoperable. Also you can use it for FREE as a software container or in the cloud.
Now let’s look at how introducing an event broker into your Elixir architecture will alleviate the concerns I listed above.
Now let’s see how you would integrate Elixir and Solace PubSub+ together with some sample code. Since one of the protocols that Solace supports is MQTT, we will be using the Tortoise MQTT Elixir Library for this purpose.
There are two components to this program, the requestor which sends a request and listens to a response, and the replier which listens to the request and publishes a response. The high-level architecture diagram is listed below:
Here are the relevant code snippets:
def start_connection do Logger.info "Attempting a connection to #{Application.fetch_env!(:elixir_solace, :host)}:#{Application.fetch_env!(:elixir_solace, :port)}" Tortoise.Supervisor.start_child( client_id: "solace_hello_requestor", user_name: Application.fetch_env!(:elixir_solace, :user_name), password: Application.fetch_env!(:elixir_solace, :password), handler: {Solace.Hello.Requestor, []}, server: {Tortoise.Transport.SSL, host: Application.fetch_env!(:elixir_solace, :host), port: Application.fetch_env!(:elixir_solace, :port), verify: :verify_none}, subscriptions: [{"hello/response",1}]) end
Now let’s look at the code for what happens when you receive a message:
def handle_message(topic, payload, state) do Logger.info "Received #{payload}" {:ok, state} end
When a message is received, the handle message function will be called asynchronously.
A few notes about the message exchange pattern here, if you notice above – you subscribe on a topic. In the above example, its ‘hello/response’.
Think of this as an address that you can subscribe on. Whenever a publisher publishes on the topic ‘hello/response’, the Solace PubSub+ Event Broker will push the event out to all interested subscribers. In addition, subscribers can use wildcards to capture a subset of the flows. For example, if you wanted to limit subscriptions to a specific region, the Elixir nodes would publish on the topic us-east/hello/request and perhaps you had an audit process that needed to capture all requests no matter where the requests originate from. They would simply express a subscription with the following pattern: ‘+/hello/request’ which captures requests from all regions.
Here is a high-level architecture diagram of a potential workflow:
If you want to see a fully working code sample with instructions to spin up a Solace PubSub+ Event Broker, you can find it on github here.