Edited at

サーバーレスサーバーサイドSwiftとHexaville

More than 1 year has passed since last update.


はじめに

こんにちは、tk1024です。

この前の金曜日にTokyo Server Side Swift Meetup #7が行われました。

その中でYuki Takei (noppoMan)さんがServer Less Server Side Swift with Hexavilleという物を発表していたので今回も関連するMediumの記事を翻訳してみました。

元記事: Serverless Server Side Swift with Hexaville

Google翻訳に毛が生えた程度なので誤字脱字・翻訳間違い等、コメントでも編集リクエストでも送っていただければ幸いです。

以下、翻訳



サーバーレスサーバーサイドSwiftとHexaville

Hello World.

自分で起こした会社でSwiftを使いサーバーサイド、クライアントサイドアプリケーションを書いています。この会社は自己資金を使い2人だけ(自分とco-founder/Engineer)で運営しています。充分な資金が無く潤沢なサーバーインスタンスも24時間サーバー立ち上げ続ける為に人を雇う余裕もありません。

ベンチャー企業をはじめるに当たり、このような状況でサーバーレスコンピューティングは1つの解決法だと期待しています。


サーバーレスコンピューティング


function as a service (FaaS)として知られているサーバーレスコンピューティングはクラウド事業者がplatform as a service (PaaS)コンテナ内でリクエストに応じてコードを実行するモデルです。

また仮想マシン毎ではなくリクエスト処理の実行時間で課金されるのでリソースにかかる支払額をより抽象的に測ることができます。


サーバーレスコンピューティングではコードが実行された場合のみ料金が発生します。(かなり安い)

これにより、サーバーインスタンスにかかる費用を気にする必要がなくなります。

そして多くの場合、クラウド事業者がサービスをフルマネージするので、スケーリングについて気にする必要もありません。

完璧に見えますが欠点もあります。

- クラウド事業者に縛られる

- クラウドサービスを使えなければならない

- クラウドサービスがダウンするとサービスもダウンする

- デプロイとルーティングを管理画面から操作する必要がある(Not programmatically)

- ミドルウェアとのコネクションを維持できない

- 同時並列実行にリミットがある(上限引き上げには申請が必要)

HexavilleはサーバーレスなSwift webアプリケーションを作るために作りました。同時に上に書いたいくつかの欠点も克服しています。


Hexaville

Github: noppoMan/Hexaville

Swiftの為のモダンなWebアプリケーションフレームワーク及びエンジン

Swiftで作られたwebアプリをlambdaとapi-gatewayで実行する事をコンセプトにしています。

これらは、Swiftのビルドとデプロイ、実際にlambdaのHexavilleフレームワーク上で実行するアプリケーション作る2つのレイヤーに分かれています。


Hexavilleを使いサーバーレスアプリケーションの作成とクラウド上へのデプロイをする

これからHexavilleを使ってサーバーレスアプリケーションを実際にビルドしていきます。

インストールはすごく簡単です。クローンしてビルドする、それだけです。

以下に書くコマンドは全てMacで実行したものです。(El Capitan, Xcode 8.3.2)


インストール

git clone https://github.com/noppoMan/Hexaville.git

cd Hexaville
swift build


Hexavilleプロジェクトを生成する

まず、オプションなしでHexavilleを実行します。

./.build/debug/Hexaville

出力はこのようになります。

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

実行可能なコマンド(Available commands)を見てください。

そして、generateコマンドを実行して最初のHexavilleプロジェクトを初期化してください。

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

generateコマンド実行後にはHelloディレクトリが作られていると思います。中を覗いてみましょう!

/Users/name/Desktop

├── Hexavillefile.yml
├── Package.swift
└── Sources
├── RandomNumberGenerateMiddleware.swift
└── main.swift

1 directory, 4 files

ディレクトリは一般的なSwift Package Managerプロジェクトの構成です。swift package generate-xcodeprojを実行する事で自動でxcodeprojを生成する事ができます。これはXcodeでHexavilleアプリケーションを開発できる事を意味します。


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

このようにしてXcodeで開く事ができます。


main.swift



main.swiftの中にはHexavilleフレームワークのサンプルコードが書かれています。ExpressやSinatraと似ています。

編集しないでデプロイしてみます。


Edit Hexavillefile.yml

Hexavillefile.ymlはHexavilleの設定ファイルです。

設定ファイルを開いて、credential, region, lambdaのroleを埋めてください。

(credential, region, passは環境変数として省略する事もできます)

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

では、deployコマンドでデプロイしましょう

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

時間がかかるのでしばらく待ちます...


ルーティング情報を取得する

次に、デプロイしたリソースを確認するためにルーティングを取得してみましょう。

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

このように出力されます

Endpoint: https://{id}.execute-api.{region}/staging

Routes:
GET /hello
GET /random_img
GET /
POST /hello/{id}
GET /hello/{id}


リソースにアクセス

curlでリソースのエンドポイントにアクセスします


curl https://{id}.execute-api.{region}/staging/

<html><head><title>Hexaville</title></head><body>Welcome to Hexaville!</body></html>

もしHTMLファイルをエンドポイントから取得できていれば、デプロイは成功です。

やったね!


デプロイフローの詳細

実際にlambda上での動作を確認しましたが、lambdaは現在Swiftのランタイムをサポートしていません。では、どのようにしてlambda上でSwiftを実行してのか説明していきます。

はじめにデプロイフローの図をご覧ください。この図に従って何をしているのか説明していきます。

Build Swift on Dockerを見てください。

もし、SwiftをMac上でビルドしてバイナリをアップロードするとAmazon Linux上で実行するlambdaでは動きません。

なので、Linux_x86と互換性のあるバイナリをビルドするためにDocker for Macを使う必要があります。

そして、ビルドされたバイナリと関連するオブジェクトは-vオプションでdockerとホストマシンの共有ディレクトリにデプロイされます。

また、Linux上でSwiftのバイナリを実行するには以下の.soファイルが必要です。

/${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

これらをディレクトリにまとめて、zipファイルにした後にAWS S3にアップロードします。

また、Hexavilleアプリケーションのルーティングがapi-gatewayにそのまま反映されている事を不思議だと思いましたか?

Hexavilleフレームワークで作られたアプリケーションはコマンドラインアプリケーションとして実行できます。

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

gen-routing-manifコマンドに注目してください。

このコマンドを一度、実行してみてください。

Hexavilleフレームワークアプリケーションからルーティング情報を抽出して.routing-manifest.jsonに出力します。


.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"
}
]
}

.routing-manifest.json はapi-gatewayのRestAPIのパラメータをマップしたものです。


Lambda上でどのようにしてSwiftを実行するのか

最後に、lambda上でどのようにしてSwiftのバイナリを実行するのか説明します。



この図が示すようにNode.jsをlambdaのランタイムとして、Swiftバイナリをchild_processモジュールでプロセスとして生成しています。

生成後、オリジンプロトコルで子プロセスから親プロセスにパイプでメッセージを送っています。


追伸

どうでしたか?

Hexavilleはまだ幾つかの機能しかなくできることは多くありませんが、実際に動かしながらフィードバックを提供し続けていきたいと思います。

次は以下の機能を実装しようと考えています。

- ログ出力(Cloud watch logs -> Amazon Athena)

- VPCサポート

- カスタムドメインサポート

- バイナリメディアサポート

これらの機能があれば、実用的なWebアプリケーションを作成する選択肢の1つになると私は信じています。


訳者あとがき

Github: noppoMan/Hexaville

Twitter: @noppoMan722

Connpass: Tokyo Server Side Swift Meetup