MMMブログ

AWS LambdaでGolangのWebフレームワークGinを利用してみた

このエントリーをはてなブックマークに追加

最近は体調管理に一番困っているやっさんでございます。
頭痛や肩こり、そして腰痛。
年齢が上がると人には話しにくい悩みが増えていきますね。

さて、今回はAWS Lambdaで
GolangのWebフレームワークGinを利用してみました。

Ginとは

GinはGo(Golang)で記述されたWebフレームワークです。
パフォーマンスと優れた生産性が必要な場合は、Ginが気に入るはずです。

AWS Lambda × Ginのメリット

AWS LambdaでGinを利用することのメリットを考えてみます。

再利用性と可搬性の向上

Ginを利用することで、再利用性と可搬性が向上します。
GinはWebフレームワークですので、サーバーでも動かすことができます。
少しの修正でAWS Lamdaからコンテナアーキテクチャに変更することも可能になります。

フレームワークの恩恵を享受できる

GolangではAWS Lambdaに特化したフレームワークはありません。
他の言語であれば、以下のようなフレームワークが存在します。

  • Ruby:Ruby on Jets
  • Python:Chalice

「LambdaでSpring Bootを使えるか」という話を勉強会で耳にしました。
コミュニティから信頼されているフレームワークをLambdaで利用できれば、
生産性も上がり、コミュニティから多くの技術的知見も得られる …
このような話が出るのは当然です。
(LambdaでSpring Bootを使うのが本番ワークロードに適しているかは、別の話ですが。)

Ginも人気のあるWebフレームワークで、スター数は30,000を超えています。
LambdaでWebフレームワークに必要な機能をフルスクラッチで作るより、
Ginなどの有名なフレームワークを利用したほうが生産性は上がるでしょう。

このようなアプローチは他にもあります。

  • LambdaでExpress(Node.js)を利用する
  • LambdaでFlask(Python)を利用する

AWS LambdaでGinを利用してみる

以下の前提条件で構築しました。

  • Golang : 1.14.3
  • Serverless Framework : 1.67.1

ディレクトリ構成

今回はServerless Frameworkを利用します。

1
2
3
4
5
- src
- hanlder
- main.go
- Makefile
- serverless.yml

main.goの内容

awslabsが提供しているaws-lambda-go-api-proxyを利用して、
Lambdaのリクエスト情報をGinの機能に受け渡します。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package main

import (
"log"
"context"

"github.com/aws/aws-lambda-go/events"
"github.com/aws/aws-lambda-go/lambda"
"github.com/awslabs/aws-lambda-go-api-proxy/gin"
"github.com/gin-gonic/gin"
)

var ginLambda *ginadapter.GinLambda

func init() {
// stdout and stderr are sent to AWS CloudWatch Logs
log.Printf("Gin cold start")
r := gin.Default()
r.GET("/ping", func(c *gin.Context) {
c.JSON(200, gin.H{
"message": "pong",
})
})

ginLambda = ginadapter.New(r)
}

func Handler(ctx context.Context, req events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
// If no name is provided in the HTTP request body, throw an error
return ginLambda.ProxyWithContext(ctx, req)
}

func main() {
lambda.Start(Handler)
}

serverless.ymlの内容

記述内容にGin特有の変更はありません。
普段通り記述します。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
service: aws-lambda-go-api-proxy-gin

provider:
name: aws
runtime: go1.x
stage: ${opt:stage, self:custom.defaultStage}
region: ap-northeast-1
iamRoleStatements:
- Effect: "Allow"
Action:
- "logs:*"
Resource: "*"

package:
exclude:
- ./**
include:
- ./bin/**

custom:
defaultStage: dev

functions:
api:
handler: bin/main
timeout: 900
events:
- http:
path: ping
method: get

デプロイ

以下のコマンドをMakefileに用意しました。

1
2
3
4
5
6
build:
go mod download
env GOOS=linux go build -ldflags="-s -w" -o bin/main src/handler/main.go

deploy: build
sls deploy --verbose --aws-profile $(PROFILE)

実行してみる

実行できました!

パフォーマンスを測ってみる

Heyというツールを使って測ってみました。
コールドスタートで0.4秒ならよさそうです!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
Summary:
Total: 0.5447 secs
Slowest: 0.4115 secs
Fastest: 0.0246 secs
Average: 0.1200 secs
Requests/sec: 367.1871

Total data: 3600 bytes
Size/request: 18 bytes

Response time histogram:
0.025 [1] |
0.063 [145] |■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
0.102 [1] |
0.141 [2] |■
0.179 [2] |■
0.218 [0] |
0.257 [0] |
0.295 [1] |
0.334 [8] |■■
0.373 [32] |■■■■■■■■■
0.411 [8] |■■


Latency distribution:
10% in 0.0328 secs
25% in 0.0381 secs
50% in 0.0442 secs
75% in 0.1740 secs
90% in 0.3583 secs
95% in 0.3691 secs
99% in 0.3913 secs

Details (average, fastest, slowest):
DNS+dialup: 0.0151 secs, 0.0246 secs, 0.4115 secs
DNS-lookup: 0.0030 secs, 0.0000 secs, 0.0124 secs
req write: 0.0000 secs, 0.0000 secs, 0.0010 secs
resp wait: 0.1048 secs, 0.0245 secs, 0.3504 secs
resp read: 0.0000 secs, 0.0000 secs, 0.0002 secs

Status code distribution:
[200] 200 responses

いとも簡単にLambdaでGinを利用できました。
ここからにさらにデータソースをDynamoDBからRDBに変更しやすい設計とすれば
より再利用性と可搬性が向上しますね。

今回試したコードは以下にあります。
x-blood / aws-lambda-go-api-proxy-gin

よろしければご覧になってみてください。

以上です!

このエントリーをはてなブックマークに追加

お問い合わせ

見積もり依頼や詳しいご相談など、クラウド・AWSに関する困りごとをお気軽にご相談ください。
以下のお問い合わせ先から受け付けています。

お問合わせはこちら

※通常1営業日内にご回答いたします。