LoginSignup
1

More than 1 year has passed since last update.

posted at

Golang + gorilla/mux + LambdaProxyIntegration + ServerlessFrameworkを動かすまで

概要

タイトル通り、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
serverless.yml
~~~
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日なのでクソコードなのは許してください。。。

main.go
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は安いし楽だし個人開発において最強

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
1