Serverless Server Side Swift with Hexaville

Hello World.

I’m writing client and server applications with Swift at my company. 
Our company has only two people(me and co-founder/Engineer) and running by our own money.
So we don’t have abundant money to launch a lot of server instances usually and difficult to hire other people to operate/observe our clusters in 24 hours a day.

I hope Serverless computing is one of the solution for this situation in the beginning of such a venture well.

Serverless computing

Serverless computing, also known as function as a service (FaaS), is a cloud computing code execution model in which the cloud provider fully manages starting and stopping of a function’s container platform as a service (PaaS) as necessary to serve requests, and requests are billed by an abstract measure of the resources required to satisfy the request, rather than per virtual machine, per hour

In the Serveless comuputing, The charging is occured when the function is executed(it’s incredibly cheap) so we don’t need to pay fixed cost for Server Instances.
And most of the case, Cloud provider provide it as fully managed service, therefore We don’t have to worry about server scaling in/out and downing.

It seems perfectly nice, but there are disadvantages as well.

  • Locked into the cloud service
  • Required proficient in the cloud service
  • Your Service goes down when the cloud service is down
  • Deploying and routing from the control panel(Not programmatically)
  • Have to use the programming languages that serverless service provides
  • Can’t keep connection between middlewares
  • Limited parallelism(Needs upper limit relaxation application)

Hexaville made it wanting to build Swift’s web application in a serverless environment while overcoming some of these drawbacks to some extent.

Hexaville

The modern serverless web application engine and framework for Swift

The concept is execute `web apps made by Swift` as it on lambda+api-gateway.

Hexaville is an engine that can build a serverless environment for Swift and its web application framework. entire codes written in Swift. (Think of it as the Swift version of the serverless)

Currently supports only AWS lambda+api-gateway.

It’s devided two layers, one is for creating environment, building swift and deploying, the other one is framework for creating application that is actually executed in the lambda that called HexavilleFramework.

Using Hexaville for creating serverless application and deploying to the cloud

let’s try building a serveless application with Hexaville from now on. Installation is super easy. just clone and build.

The every commands that I wrote following are executed on my Mac(El Capitan, Xcode 8.3.2)

Installation

git clone https://github.com/noppoMan/Hexaville.git
cd Hexaville
swift build

Generate a Hexaville Project

First, try to execute Hexaville without any options.

./.build/debug/Hexaville

The output should be…

Available commands:
- generate            Generate initial project
- deploy              Deploy your application to the specified cloud provider
- routes              Show routes and endpoint for the API
- help                Prints this help information
- version             Prints the current version of this app

You would see the available commands so far, and then execute generate command to initialize the first Hexaville project.

./.build/debug/Hexaville generate --dest /Users/name/Desktop/Hello

After finishing generate, Hello directory should be created on the Desktop. Let’s look inside of the directory!

/Users/name/Desktop
├── Hexavillefile.yml
├── Package.swift
└── Sources
├── RandomNumberGenerateMiddleware.swift
└── main.swift
1 directory, 4 files

In the directory structure is basic structure for the Swift Package Manager Project. So you can automatically generate xcodeproj file with swift package generate-xcodeproj . It means You can develop Hexaville application with Xcode.

cd ~/Desktop/Hello
swift package generate-xcodeproj
open *.xcodeproj

And then, open it with Xcode

main.swift

In the main.swift, the example code of HexavilleFramework application is written. It’s similar with web application made by express or sinatra.

At this time, deploying it without editing.

Edit Hexavillefile.yml

Hexavillefile.yml is a configuration file for Hexaville.

Open it and fill credential, region and role for lambda in. (You can omit credential and region and pass them as environment variables)

name: test-app
service: aws
aws:
credential:
access_key_id: xxxxxxxxxxxxx
secret_access_key: xxxxxxxxxxxxx
region: us-east-1
lambda:
role: arn:aws:iam::xxxxx:role/xxxxxxxxxxxxx
timout: 10
build:
nocache: false

Deploy

If you did so far, Let’s Deploy it with deploy command!

/path/to/your/Hexaville/.build/debug/Hexaville deploy Hello

This work will take a while….

Get the routing informations

Next let’s get the routing information to confirm available resources on the deployment stage.

/path/to/your/Hexaville/.build/debug/Hexaville routes

Output should be…

Endpoint: https://{id}.execute-api.{region}/staging
Routes:
GET /hello
GET /random_img
GET /
POST /hello/{id}
GET /hello/{id}

Access the resources

Let’s try to access the endpoint with curl

curl https://{id}.execute-api.{region}/staging/
<html><head><title>Hexaville</title></head><body>Welcome to Hexaville!</body></html>

If you can get html response from endpoint, deploying is successfully completed.

We got power!!!

Anatomy of Deployment flow

Well, We could confirm that it actually works, but currently lambda does not support swift runtime. I’ll explain how to execute Swift on lambda.

First, describe the deployment flow. following figure describes what happening in the deploying phase.

Attention to the `Build Swift on Docker` section.

If you build swift on the Mac and upload its binary to lambda, it won’t be able to executed cause lambda is executed on the Amazon Linux.

So, we need to use `Docker for Mac` to build and get binary that have compatibility with Linux_x86. And the built binary and related shared objects(*.so) will be deployed into the shared directory between host machine and docker with `-v` option.

Besides, to run Swift’s binary on Linux, the following .so files are required.

/${SWIFTFILE}/usr/lib/swift/linux/*.so
/usr/lib/x86_64-linux-gnu/libicudata.so
/usr/lib/x86_64-linux-gnu/libicui18n.so
/usr/lib/x86_64-linux-gnu/libicuuc.so
/usr/lib/x86_64-linux-gnu/libbsd.so

They are grouped in a directory, zipped and uploaded to AWS S3.

Also, it’s mysterious that the routing of the Hexaville application is reflected on the api-gateway as it is. aren’t you?

An application created with HexavilleFramewok is executable as command line application.

Available commands:
- gen-routing-manif Generate routing manifest file
- execute Execute the specified resource. ex. execute GET /
- serve Start Hexaville Builtin Server
- help Prints this help information
- version Prints the current version of this app

Attention to the gen-routing-manif command

Once execute this command, extract routing information from HexavilleFramework app and print it as .routing-manifest.json.

{
"routing" : [
{
"method" : "get",
"path" : "\/"
},
{
"method" : "get",
"path" : "\/hello"
},
{
"method" : "get",
"path" : "\/hello\/{id}"
},
{
"method" : "post",
"path" : "\/hello\/{id}"
},
{
"method" : "get",
"path" : "\/random_img"
}
]
}

This .routing-manifest.json is mapped to the parameters of RestAPI of api-gateway.

How is Swift executed on Lambda

At the last, I’ll explain you how Swift’s binary is executed in the lambda.

As shown in this figure, we use the node.js as runtime of lambda, and spawn Swift’s binary as a process from child_process module.

After spawning, connecting the parent and child with pipe and sending message from child with original protocol.

PS

How was it?

Although Hexaville still has few functions, and not many things that can do, but I’d like to take advantage of actual operation and constantly provide feedback from it.

I plan to implement following features for the next.

  • logging pipeline(Cloud watch logs -> Amazon Athena)
  • VPC Supports
  • Custom Domain Supports
  • Binary Media type Supports

If it got these features, I believe it will become one of the choice to create practical web application tool.