Understanding actor concurrency, Part 1: Actors in Erlang

A new way to think about structuring concurrent applications

1 2 Page 2
Page 2 of 2

You've no doubt noticed that depending on the circumstance, clauses and functions are separated by , (comma), ; (semicolon), and . (period). In Erlang, these punctuation marks serve much the same purpose as their use in English. The comma separates phrases (often subsequent expressions to evaluate). The semicolon indicates a related but separate phrase. The period terminates a complete statement.

We can then spawn a process to run this function and send messages to it, as shown in Listing 8.

Listing 8. Running the temperature converter process

1> c(temperature).
{ok,temperature}
2> Pid = spawn(fun temperature:temperatureConverter/0).
<0.128.0>
3> Pid ! {toC, 32}.
32F is 0.0 C
{convertToC,32}
4> Pid ! {toF, 100}.
100C is 212.0 F
{convertToF,100}
5> Pid ! {stop}.
Stopping
{stop}

In this trace in the shell, we load and compile the temperature module, then spawn a process running the temperatureConverter function. In return we get the process ID of the converter process. We can then send it messages using the ! operator.

RPC in Erlang

In the example in Listing 7 we simply printed the answer in the process, but it's probably far more useful to get a response to our question. A remote procedure call (RPC) is easy to build by simply including the process identifier of the source as part of the message. We must rework our converter function to expect a source identifier and to respond with a message instead of printing, as shown in Listing 9.

Listing 9. Reworking the converter for RPC

temperatureConverter() ->
 receive
 {From, {toF, C}} ->
 From ! {self(), 32+C*9/5},
 temperatureConverter();
 ...etc

We can then add some functions to hide the spawn and the remote call behind a simpler interface, as shown in Listing 10.

Listing 10. Wrapping the RPC

start() ->
 spawn(fun() -> temperatureConverter() end).

convert(Pid, Request) ->
 Pid ! {self(), Request},
 receive
 {Pid, Response} -> Response
 end.

The start() function spawns the converter process and returns its process identifier. The convert function uses the process identifier to call the converter process, sending the current identifier as the source, then blocks in a receive waiting for a response on the current's process mailbox, which is subsequently returned.

These are just the most basic ways to use actors in Erlang. Erlang also makes it easy to handle errors: instead of having a process manage its own errors, it's more common to create a new process (they're cheap, right?) to watch the original process and deal with an error. Many patterns, such as propagating the error or restarting the process, are possible. In fact, Erlang provides a whole library that deals with patterns of error handling, hot-swapping code, and other useful functionality.

Does it work?

Erlang wouldn't be receiving attention today without real-life success stories. At Ericsson, the AXD 301 switch is the flagship example of Erlang's scalability and reliability. This switch handles millions of calls per week and has a reported 99.9999999 percent uptime. Once Erlang was open-sourced, it was picked up by Ericsson's competitor Nortel and integrated into the Nortel Alteon SSL Accelerator, which does hundreds of transactions per second.

Because of Erlang's focus on messaging, it seems to be a good fit for these kinds of systems. The ejabberd daemon is a highly-regarded Jabber/XMPP implementation that has been used in some large implementations such as jabber.org. Similarly, RabbitMQ is a high-performance AMQP server written in Erlang that can reportedly handle 400,000 messages per second.

Several so-called Web 2.0 companies have also had success building parts of their systems in Erlang. Facebook Chat uses a combination of C++ and an Erlang Web server to handle 70,000 concurrent users. Delicious 2.0 relaunched in 2008 and is primarily based on C++ but uses Erlang in several subsystems such as data migrations, rolling migrations, and algorithmic analysis. CouchDB, which has gotten a lot of press lately as a document-centric Web database, is written entirely in Erlang. Reportedly the Amazon SimpleDB service also uses Erlang internally.

In short, Erlang can boast a number of high-profile successes, and these users consistently tout Erlang's strengths for writing distributed, concurrent, fault-tolerant software. It's clear that the actor model is a valid alternative for addressing concurrency without shared state and locks.

You may be thinking, "This sounds cool, but there's no way my manager will let me start deploying software in Erlang." Don't you wish you could use the actor model on the JVM? Well, stay tuned for Part 2.

Alex Miller is a tech lead at Terracotta Inc, the makers of the open-source Java clustering product Terracotta. Previously, Alex worked at BEA Systems on the AquaLogic product line and was Chief Architect at MetaMatrix. Alex blogs at Pure Danger Tech and speaks at user groups, conferences, and the No Fluff Just Stuff tour. He has an enduring love for his wife and three children, music, and nachos.

Learn more about this topic

More from JavaWorld

1 2 Page 2
Page 2 of 2