概要
タイトル通り、GolangアプリケーションをLambdaプロキシ統合で動かします
Lambdaプロキシ統合ってなに
ここに書いてある
これを使うとLambda関数を小分けにしなくても、アプリケーション側でルーティングを振り分ける従来の開発方法でサーバーレスなアプリケーションが作れる
必要なもの
・AWSアカウント
・ServerlessCLI
インストール、認証情報の設定が必要です
公式ドキュメント
実装
sls create --template aws-go-mod --path go-test
テンプレートから雛形を作ってもらいます
go-test
の部分はお好きなプロジェクト名を入れてください
この時点でのファイル構成はこんな感じ
├── Makefile
├── gomod.sh
├── hello
│ └── main.go
├── serverless.yml
└── world
└── main.go
ここからプロキシ統合で動かすためにMakefileやらserverless.ymlやら色々手を加えていきます
プロキシ統合では単一のlambda関数にAPIGatewayからリクエストを渡し関数側でルーティング等の処理をします。
現在はhello関数とworld関数が存在するのでこれを削除して一つにしましょう。
├── Makefile
├── gomod.sh
├── serverless.yml
└── src
└── main.go
~~~
provider:
name: aws
runtime: go1.x
#リージョンの設定をしないとデフォルトのus-east-1に飛ばされます
region: ap-northeast-1
~~~
functions:
#lambda関数名
main:
#ビルド後のバイナリファイルパス
handler: bin/main
#lambdaプロキシ統合の設定
events:
- http: ANY /
- http: 'ANY {proxy+}'
~~~
次にmain.goにAPIGatewayから送られてきたリクエストをどうにかする処理を書いてくのですが、AWS様がライブラリを用意してくれているので簡単に実装できます。
net/httpは勿論、gorilla/mux, Gin, Echo fiber等がサポートされているみたいですが今回はgorilla/muxを使用します。
Go歴2日なのでクソコードなのは許してください。。。
package main
import (
"context"
"encoding/json"
"fmt"
"log"
"net/http"
"github.com/aws/aws-lambda-go/events"
"github.com/aws/aws-lambda-go/lambda"
"github.com/awslabs/aws-lambda-go-api-proxy/gorillamux"
"github.com/gorilla/mux"
)
var gorillaMuxLambda *gorillamux.GorillaMuxAdapter
func handleHello(w http.ResponseWriter, r *http.Request) {
type response struct {
Message string `json:"message"`
}
result, err := json.Marshal(response{Message: "hello"})
if err != nil {
log.Println(err.Error())
fmt.Fprint(w, "sorry server error...")
return
}
fmt.Fprintf(w, "%s", result)
}
//コールドスタート時にのみ実行される
func init() {
log.Printf("cold start")
router := mux.NewRouter()
router.HandleFunc("/", handleHello)
gorillaMuxLambda = gorillamux.New(router)
}
func Handler(ctx context.Context, req events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
return gorillaMuxLambda.ProxyWithContext(ctx, req)
}
func main() {
lambda.Start(Handler)
}
関数の構成を変更したのでMakefileにも変更を加えます
またデフォルトのbuildコマンドだと何故かファイルのパスが解決できないとかなんとかでlambdaが動いてくれないためこちらにも変更を加えます
何故動かないのかはよくわからないので誰か教えて下さい。。。
とりあえずおまじないとして-ldflags='-d -s -w' -a -tags netgo -installsuffix netgo
を追加します
#Makefile
.PHONY: build clean deploy gomodgen
build: gomodgen
export GO111MODULE=on
#ここを変更
env GOARCH=amd64 GOOS=linux go build -ldflags='-d -s -w' -a -tags netgo -installsuffix netgo -o bin/main src/main.go
clean:
rm -rf ./bin ./vendor go.sum
deploy: clean build
sls deploy --verbose
gomodgen:
chmod u+x gomod.sh
./gomod.sh
これで設定が終わったのでファイルをビルドしてデプロイしていきます
go.modの作成
make gomodgen
モジュールのダウンロード
go mod tidy
ビルド
make build
デプロイ
sls deploy
この時点でのファイル構成
├── Makefile
├── bin
│ └── main
├── go.mod
├── go.sum
├── gomod.sh
├── serverless.yml
└── src
└── main.go
無事にデプロイ出来たらsls invoke -f main
でAPIを叩いてみましょう
{
"statusCode": 200,
"headers": null,
"multiValueHeaders": {
"Content-Type": [
"text/plain; charset=utf-8"
]
},
"body": "{\"message\":\"hello\"}"
}
ここまで出来たらあとは普通のGolangアプリケーションと同じ感覚で開発していけます
最後に
Lambdaは安いし楽だし個人開発において最強