今天我們來試試在雲端服務很熱門的一種架構:無伺服器架構 (Serverless)
我們會在 AWS 上建立一個無伺服器架構的 API,會使用到 AWS Lambda 跟 Amazon API Gateway 兩種服務。
首先要來建立 Lambda 函數。
AWS Lambda 是一種無伺服器架構的服務,只要把你寫好的程式放上去,接下來 Lambda 會依照使用量自動擴增資源。費用會依照使用量計算。
Lambda 支援很多程式語言,今天我們會使用 golang 來測試。
AWS 官方提供給 go 的開發者使用的函式庫放在 github 上: https://github.com/aws/aws-lambda-go
這次的 Hello world 範例會使用到兩種函式庫:
github.com/aws/aws-lambda-go/lambda
github.com/aws/aws-lambda-go/events
我們建立 main.go
檔案,當程式接到請求時,會回應一組字串,以下是完整內容:
package main
import (
"encoding/json"
"fmt"
"net/http"
"time"
"github.com/aws/aws-lambda-go/events"
"github.com/aws/aws-lambda-go/lambda"
)
// Response of API
type Response struct {
Message string `json:"message"`
At string `json:"at"`
}
func handleRequest(req events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
resp := Response{
Message: "Hello World!",
At: time.Now().Format(time.RFC3339),
}
name, ok := req.QueryStringParameters["name"]
if ok {
resp.Message = fmt.Sprintf("Hello, %s!\n", name)
}
body, _ := json.Marshal(resp)
res := events.APIGatewayProxyResponse{
StatusCode: http.StatusOK,
Headers: map[string]string{"Content-Type": "text/json; charset=utf-8"},
Body: string(body),
}
return res, nil
}
func main() {
lambda.Start(handleRequest)
}
建立 Makefile
放入 go build
指令
build:
GOOS=linux go build -ldflags="-s -w" -o bin/main main.go
執行指令 make build
編譯執行檔
建立檔案 lamda.tf
archive_file
打包編譯好的執行檔aws_iam_policy_document
跟 aws_iam_role
建立 IAM 角色aws_lambda_function
建立 Lambda 函數完整內容:
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
}
}
}
provider "aws" {
profile = "default"
region = "ap-northeast-1"
}
provider "archive" {}
data "archive_file" "zip" {
type = "zip"
source_file = "bin/main"
output_path = "hello_lambda.zip"
}
data "aws_iam_policy_document" "policy" {
statement {
sid = ""
effect = "Allow"
principals {
identifiers = ["lambda.amazonaws.com"]
type = "Service"
}
actions = ["sts:AssumeRole"]
}
}
resource "aws_iam_role" "lambda_exec" {
name = "lambda_exec"
assume_role_policy = data.aws_iam_policy_document.policy.json
}
resource "aws_lambda_function" "hello" {
function_name = "hello_lambda"
filename = data.archive_file.zip.output_path
source_code_hash = data.archive_file.zip.output_base64sha256
role = aws_iam_role.lambda_exec.arn
handler = "main"
runtime = "go1.x"
}
執行 terraform init
初始化 Terraform,下載供應商外掛
$ terraform init
Initializing the backend...
...
* hashicorp/archive: version = "~> 1.3.0"
* hashicorp/aws: version = "~> 3.8.0"
Terraform has been successfully initialized!
執行 terraform apply
建立 Lambda 函數
$ terraform apply
...
Apply complete! Resources: 2 added, 0 changed, 0 destroyed.
我們成功建立一個 Lambda 函數了,接著要來做一點測試
使用 AWS 指令測試函數:
$ aws lambda invoke --region=ap-northeast-1 --function-name=hello_lambda output.json
{
"StatusCode": 200,
"ExecutedVersion": "$LATEST"
}
檢查輸出的資料:
cat output.json
{"statusCode":200,"headers":{"Content-Type":"text/json; charset=utf-8"},"multiValueHeaders":null,"body":"{\"message\":\"Hello World!\",\"at\":\"2020-09-26T09:35:12Z\"}"}%
現在我們有了 Lamda 函數,下一步要跟 API Gateway 組合,讓這個函數可以介由 HTTP 在網路上使用。