Kristian Kristensen’s Blog


Running Erlang Webmachine on Heroku

Posted in Code,Erlang,Ruby by Kristian Kristensen on the December 16th, 2011

When Heroku released their new stack Cedar they opened the door for a whole new set of components to run on their platform. To support running other components on Heroku you need a build pack that tells Heroku how to build and run your app. Heroku’s published a build pack for Erlang as well as a demo app. This demo app uses straight up Mochiweb as a web server.

MochiWeb is an Erlang library for building lightweight HTTP servers.

Mochiweb Github Repo

Webmachine runs on top of Mochiweb and is

A REST-based system for building web applications.

Webmachine Github Repo

In this blog post I’ll show how to get a Webmachine app running on Heroku.

Let’s get to it

So here are the steps to get a vanilla Webmachine app up and running on Heroku.

$ git clone git://github.com/basho/webmachine
$ cd webmachine
$ make
$ ./scripts/new_webmachine.sh my-erlang-app /tmp
$ cd /tmp/my-erlang-app
$ make

You can now run “./start.sh” and open your browser on http://localhost:8000 and see your new awesome Hello World Webmachine app. Now we want to deploy it to Heroku.
Make sure you have Ruby and the Heroku gem installed. If not run:

$ gem install heroku

Then setup our app:

$ git init
$ heroku create my-erlang-app -s cedar
$ heroku config:add BUILDPACK_URL=http://github.com/heroku/heroku-buildpack-erlang.git

This initializes a new Git repository in our app directory, creates the heroku app. The final line setups the build pack that cedar should use when deploying the app.

Let’s add the source files to the Git repo and start hammering out some code.

$ git add Makefile README rebar rebar.config start.sh src/* priv/dispatch.conf

Next we want to update our rebar.config:

%%-*- mode: erlang -*-
{sub_dirs, ["rel"]}.
{deps_dir, ["deps"]}.
{erl_opts, [debug_info]}.

{deps, [{webmachine, "1.9.*", {git, "git://github.com/basho/webmachine", "HEAD"}}]}.

Create the Procfile which Foreman will use to control our app:

web: erl -pa ebin deps/*/ebin -noshell -boot start_sasl -s reloader -s my-erlang-app

You know have the major components in place for Heroku deployment. If you want to test it out run:

$ ./rebar get-deps compile
$ foreman start

Of course this requires that you’ve Foreman in your path. If not install Ruby and run “gem install foreman”. If all goes well your app will start up and you’ll be able to point your browser to http://localhost:8000 and see the output.

Before we can push to Heroku we need to update the application start up code for the generated Webmachine app. When Cedar attempts to start your application it’ll define the port on which your app should listen/bind. Hence we need to read out this value and tell Webmachine to use it. Also we want to update the logging, basically turning it off (more about this later) and we want to just bind to the default catch all ip of 0.0.0.0.

Open up my_erlang_app_sup.erl in the src/ directory.
Change the init method so it looks like this:

init([]) ->
     {ok, Dispatch} = file:consult(filename:join(
                          [filename:dirname(code:which(?MODULE)),
                          "..", "priv", "dispatch.conf"])),

    Port = list_to_integer(os:getenv("PORT")),
    io:format("start web server on port ~p~n", [Port]),
    WebConfig = [
                 {ip, "0.0.0.0"},
                 {port, Port},
%                 {log_dir, "priv/log"},
                 {dispatch, Dispatch}],
    Web = {webmachine_mochiweb,
           {webmachine_mochiweb, start, [WebConfig]},
           permanent, 5000, worker, dynamic},
    Processes = [Web],
    {ok, { {one_for_one, 10, 10}, Processes} }.

This reads out the port number that Cedar has assigned to our app in line 6 and passes it to the Webmachine config. Also it binds to the right IP in line 9 and disables the log dir in line 11.

Make sure it compiles by running the rebar command again:

$ ./rebar get-deps compile

Before we push to Heroku you might want to change the output message of your app. Open “src/my_erlang_app_ressource.erl” and change the “to_html” function.

Now do the add and commit dance to git:

git add <input-changed-file-list-here>
git commit -m "initial commit before push to Heroku"

Next run

$ git push heroku master

Point your browser to http://my-erlang-app.heroku.com and you should see your output message as defined in “src/my_erlang_app_ressource.erl”.

To see what’s going on when Cedar boots up your app run “heroku logs”. This will spit out the same output you see when you run foreman locally. This is a great (and the) way to debug why your app isn’t starting up.

I’ve pushed my repository to Gibhub and deployed the app to Heroku. It’s called Erloku and you can check it out here

Next steps

Here are a couple of things that I’d like to continue to work on.

  • By default Webmachine comes with a logger that outputs to tiles. Since this doesn’t go well with Heroku which expects and redirects output from Standard Output and Standard Error to its logs. Therefore it would be nice to implement a logger for Webmachine that outputs to StdOut and StdErr. Doing this shouldn’t be too hard.
  • Get two dynos running an Erlang Node to talk with each other. Cedar probably has walls in place that won’t allow this, but if possible it would be mighty cool.
  • If you like my writing you should subscribe to my RSS feed.

    ErlChat – A Simple Chat Server Written In Chicago Boss, A Web Framework For Erlang

    Posted in Code,Erlang by Kristian Kristensen on the December 13th, 2011

    Recently I’ve been exploring Erlang and its web frameworks. As part of this exploration I found Chicago Boss. This blog post is a pointer into the simple chat server I built using Erlang and Chicago Boss.

    Jordan Orelli and Seth Murphy from Hacker School built Chatify as a demo application for Brubeck:

    Brubeck is a flexible Python web framework that aims to make the process of building scalable web services easy.

    Chatify is a simple chat application built with Brubeck as the backend and HTML and Javascript as the front end.
    I decided to reimplement the backend in Chicago Boss and reuse the front-end. The result is Erlchat.

    Here’s the main page of Erlchat, where you enter your nickname before logging into the chat:

    Click to View in Fullsize - ErlChat Main Page

    Bert and Ernie chat’s away:

    Click to View in Fullsize - ErlChat Chat Screen 1

    They’re loving it!

    Click to View in Fullsize - ErlChat Chat Screen 2

    The code is really simple. Mostly because the required parts for building a chat server is built into Chicago Boss in the form of a message queue abstraction. However, the reason it works is because of Erlangs ability to scale out. Each call to retrieve messages is a long polling HTTP call, and hence blocks a connection. Since Erlang scales to many thousands of processes and Chicago Boss takes advantage of that, it really isn’t a problem.

    The following function gets called by the client when he wishes to retrieve the messages that have occurred in Channel since his last retrieveal (LastTimestamp). It blocks on the call to boss_mq:pull.

    receive_chat('GET', [Channel, LastTimestamp]) ->
        {ok, Timestamp, Messages} = boss_mq:pull(Channel, list_to_integer(LastTimestamp)),
        {json, [{timestamp, Timestamp}, {messages, Messages}]}.
    

    Sending a message is a simple HTTP POST that creates a new message and pushes it on to the Channel message queue. It uses the utility method seen below.

    send_message('POST', [Channel]) ->
        create_and_push_message(Channel, list_to_binary(Req:post_param("message")), Req:post_param("nickname")),
        {output, "ok"}.
    
    create_and_push_message(Channel, Message, Username) ->
        NewMessage = message:new(id, Message, Username, erlang:localtime()),
        boss_mq:push(Channel, NewMessage).
    

    Check out the README as well as the source. It’s all up on Github.

  • If you like my writing you should subscribe to my RSS feed.