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.swift1 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.