The recently released Akka 2.2.0-RC1 introduces the new
akka.io package in the
akka-actor module. According to the documentation, “the guiding design goal for this I/O implementation was to reach extreme scalability, make no compromises in providing an API correctly matching the underlying transport mechanism and to be fully event-driven, non-blocking and asynchronous.”
For some of you this completely actor-based I/O implementation might look familiar, because it has been developed as a joint effort by the spray and Akka teams, based on the “old”
In this blog post we will introduce the new Akka I/O by some very simple networking examples, namely a TCP and a HTTP server. In follow-up posts I will then show how Akka I/O and spray can be used to build a modern and reactive single-page web application.
Setting up the project
All right, to get stated we need an sbt project with the following dependencies:
- Scala 2.10.x
- akka-actor 2.2.0-RC2: provides Akka I/O
- spray-can 1.2-20130628: only needed for HTTP
For convenience we also add some logging support, hence we need the following sbt settings in
1 2 3 4 5 6
And this nice little class in
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
As we want to write a server, we need something we can run, i.e. an
1 2 3 4 5 6 7 8 9
We call it
EchoServiceApp, because all this very simple server will be able to do is echoing back whatever we tell. As you can see, we create an actor system and an endpoint on
localhost and port
Then we create the yet to be defined
EchoService actor. Please notice, that
passing constructor arguments to an actor has changed in Akka 2.2; while the old style is still supported, it is now deprecated in order to avoid closing over non-serializable state we are following a recommended implementation pattern and are using a
props factory method for
Props in the also to be defined companion object to avoid closing over non-serializable state: If you pass a closure to
Props from within an actor,
this gets included, which refers to an
Actor, which is not serializable.
Finally we make sure we can shutdown our server via the
I/O manager and listener
The new Akka I/O implementation abstracts over transport protocols via so called “drivers” and introduces the concept of an “I/O manager” as the API for a particular driver. Let’s create the
EchoService companion object defining the
Props factory as well as the
EchoService actor and create an I/O manager for TCP in its constructor:
1 2 3 4 5 6 7 8 9
We send a
Tcp.Bind command to the I/O manager for TCP in order to register
self – i.e. this very
EchoService actor instance – as so called “listener” for TCP connections. Of course we need to listen for TCP connections now:
1 2 3 4 5
Listening to TCP connections means handling messages of type
Tcp.Connected. All we do here is log a nice message at
DEBUG level and then register a new instance of the yet to be defined
EchoConnectionHandler actor as so called “handler” for the connection.
Hence we create a new handler actor for each connection. As actors are really cheap, this shouldn’t be an issue at all. But if you prefer, you can register the listener itself as handler.
As you can see, we pass the
sender, i.e. the connection, to the
EchoConnectionHandler. We’ll explain the reason soon …
Now let’s take a look at the final missing piece:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
As you can see, the connection handler receives messages of type
Tcp.Received which contain the payload as a
ByteString which – according to the documentation – is an “efficient, immutable alternative to the traditional byte containers used for I/O on the JVM, such as
Here we simply reply with a
Tcp.Write containing the same payload or – in case the payload equals “close” – stop the connection handler.
In case a
Tcp.ConnectionClosed message is received, we also stop the connection handler. And finally, we listen to
Terminated messages for the underlying connection and stop ourselves, too, in this case. Now you know why we had to pass along the connection from the listener.
TCP server in action
Now that we have all the necessary pieces in place, let’s run the TCP server and connect via
telnet. In one sbt session we run the
EchoServerApp and in another terminal session we enter the following:
1 2 3 4 5 6 7 8 9 10 11
As you can see, our TCP echo server works as expected. We can either close the connection via the “close command” or even shut down the server via the
Now that we know how to create a TCP server, let’s look at HTTP which is probably ways more interesting for most of us. Actually there is not so much to say, because Akka I/O is designed in a way which pretty much abstracts away the transport protocol, which is pretty awesome.
EchoServiceApp for HTTP looks exactly the same except for the constructor arguments of the HTTP listener. Hence let’s dive into the HTTP listener immediately:
1 2 3 4 5 6 7 8 9 10 11 12
As you can see, all we had to change here are the message types:
Http.Connected instead of the TCP likes.
And also the HTTP connection handler looks almost like the one for TCP:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
As you can see, the HTTP connection handler receives and
GET messages and replies with the path component of the URI. The other received messages are the same like for the TCP connection handler.
HTTP server in action
All right, let’s finally take a look at the HTTP server. We run it in sbt and in another terminal session we enter the following:
1 2 3
We have introduced the new Akka I/O by two very simple networking examples. Hopefully it has become obvious, that it is pretty easy to create an actor-based and hence completely asynchronous I/O server, most remarkably almost independent of the transport protocol.
The full source code is available on GitHub.