It's alive

I've been working on Funcatron for the last few months.

What's Funcatron?

Serverless for your cluster. If you're running Mesos or Kubernetes or Docker Swarm, you can get all the development simplification and autoscaling of Serverless, without getting locked into a particular cloud vendor.

In November, I showed how Funcatron works in developer mode:

Funcatron Developer Mode from bearfeeder on Vimeo.

Funcatron on Mesos

Based on feedback from testers, I've expanded Funcatron features to include database connections, improved logging, and more. And today, you can run Funcatron on your Mesos cluster.

Set up a Mesos cluster

First, set up a Mesos cluster. I used the dcos-vagrant tools to set up my cluster.

Start Funcatron on your cluster

You can use the handy script.

The script:

#!/bin/bash

curl -v -X PUT -H "Content-type: application/json" -d "@start.json" "http://m1.dcos:8080/v2/groups"

Which references a json description of what to deploy.

For those of you who don't parse Mesos JSON, there are 4 components deployed:

  • A RabbitMQ message broker so the rest of the system can talk
  • A 'Tron' manager that knows about the rest of the system
  • An Nginx/OpenResty front end that takes the http request
  • A 'Runner' that executes the functions. Note you can scale your system by creating more runner and in future version, the Tron will tell the substrate (Mesos) to create more runners on demand

And just like that, you've got a running Funcatron cluster.

Where are the system components?

The 'Tron' instance will print helpful messages at start-up telling you how to upload Func bundles and otherwise control the Funcatron cluster:

... INFO ... - Upload a Func Bundle: wget -q -O - --post-file=THE_UBERJAR http://192.168.65.131:31340/api/v1/add_func

... INFO ... - List known Func Bundles: curl -v http://192.168.65.131:31340/api/v1/known_funcs
... INFO ... - Enable a Func Bundle: curl -v -H "Content-Type: application/json" -d '{"sha":"THE-SHA-HERE", "props": {"key": "value"}}' -X POST http://192.168.65.131:31340/api/v1/enable
... INFO ... - Frontend at http://192.168.65.60:14009

Creating/Running an Application

Okay... so how do you create and run an app on Funcatron?

Funcatron apps are called "Func Bundles." A Func Bundle is a combination of a Swagger document describing the HTTP endpoints and code that services each of those endpoints.

There are some Java and Scala samples.

For example, Scala code to handle POST and DELETE endpoints might look like:

class PostOrDelete extends Func[Data] with DecoderOMatic[Data] {
  def apply(data: Data, context: Context) = {
    // we're guaranteed the 'cnt' path variable by the Swagger definition
    val cnt = context.getPathParams.get("cnt").asInstanceOf[Number]

    context.getMethod match {
      case "delete" =>
        new Data("Deleted " + cnt.longValue, cnt.intValue)

      case "post" =>
        (1 to cnt.intValue()).
          map(i => new Data(data.name + i, data.age + i)).
          toList

      case _ =>
        new MetaResponse() {
          def getResponseCode = 400

          override def getContentType = "text/plain"

          def getBody = ("Expecting a POST or DELETE, but got " + context.getMethod).getBytes("UTF-8")
        }
    }
  }

  protected def ct: Class[Data] = classOf[Data]
}

Once you've got your example code written, compile it.

If you're doing the Scala example: sbt clean assembly

And for the Java example: mvn clean package

Upload and enable the code

For the Scala code, you can upload it with:

wget -q -O - --post-file=target/scala-2.11/scala_sample-assembly-1.0.jar http://<SERVER>:<PORT>/api/v1/add_func

Note the sha that you get back from the server. To turn the code on:

curl -v -H "Content-Type: application/json" \
   -d '{"sha":"<SHA>", "props": {"key": "value"}}' \
   -X POST http://<SERVER>:<PORT>/api/v1/enable

Note the props field is a set of properties sent to the Runner and available to your function at runtime. The props field may also include descriptors such as JDBC information and access to other network resources. Because this is sent at deployment time, network resources (databases, caches, etc.) can be configured at enable-time.

Trying out the code

Based on the Frontend at message from the Tron, you can test your new function. for example:

http://<FRONTEND_SERVER>:<FE_PORT>/sample/scala/simple/42?cool=yes

Will return something like:

{"num-param":42,"bools":true,"numero":0.9112837757827404,"query-params":{"cool":"yes"},"time":"Fri Dec 09 20:31:31 UTC 2016"}

Logging for forensics

Take a look at the logs from the Runner:

16-12-09 20:31:31 /sample/scala INFO [funcatron.scala_sample.SimpleGet:GIT:b1d92b7430fcc6ed05c38c22d57d2163f6e8bb88&REQ:db9d00abf61d9c67f4f0e755e96b8d0e] - In Scala 'SimpleGet... yay!

See the GIT:b1d92b7430fcc6ed05c38c22d57d2163f6e8bb88 part? That's the git sha of the code that ran the function. This means for every log line, you can determine the exact version of the code that was running.

See the REQ:db9d00abf61d9c67f4f0e755e96b8d0e part? This is a unique id of the request. It is shared across the Funcatron network so that you'll be able to trace and time requests and fan-outs related to requests across your Funcatron cluster.

Yay!

So, that's Funcatron running on your Mesos cluster.

Have fun!

And please join the Funcatron community.

Thanks!!