Funcatron on Mesos December 9, 2016
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!!