はじめに
こんにちは、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" : [
{
"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