首页 >后端开发 >Golang >使用 SAM 框架构建 Go Serverless REST API 并部署到 AWS (Amazon Linux untime)

使用 SAM 框架构建 Go Serverless REST API 并部署到 AWS (Amazon Linux untime)

WBOY
WBOY原创
2024-08-23 06:42:11860浏览

为什么还要另一个 Go 教程

AWS 最近已弃用多项服务和运行时。正如我们所看到的,随着我们喜爱的 CodeCommit 和其他关键服务的终止,AWS Lambda 函数不再支持 Go1.x。

如果您尝试部署大部分过时的教程,您可能会遇到如下错误:

Resource creation Initiated    
CREATE_FAILED                    AWS::Lambda::Function            DemoFunction                     
                                   Resource handler returned message: 
                                   "The runtime parameter of go1.x is no longer supported for 
                                   creating or updating AWS Lambda functions. We recommend you 
                                   use a supported runtime while creating or updating functions. 
                                   (Service: Lambda, Status Code: 400, Request ID:  
                                   81f1f708-0a7a-40d0-8442-b9c16510d01f)" 
ROLLBACK_IN_PROGRESS             AWS::CloudFormation::Stack       lambda-go-gorilla                
                                   The following resource(s) failed to create: 
                                   [DemoFunction]. Rollback requested by user.

关键要点是软件中唯一不变的就是变化。然而,有一些永恒的原则我们应该永远牢记

为了解决这个问题,我决定创建一个最新的存储库,其中包含部署 Go 应用程序所需的所有基础设施。有两种选择:

  1. 使用 Docker 容器通过 Fargate 进行部署。
  2. 在 AWS 上使用 SAM 框架进行部署。

您可以在 GitHub 上找到存储库。

软件开发中永恒的原则

  • 基础设施即代码至关重要。
  • 软件中良好的命名约定至关重要。
  • 永远测试你的逻辑。
  • 可用性和可扩展性
  • 部署管道作为自动化软件交付过程的机制。
  • 可观察性是强制性的。
  • 安全性是云原生应用程序中的一等公民。
  • Go 是构建 API 的绝佳选择。

基础设施即代码至关重要

不可变的基础设施使我们能够在更高的层面上声明我们想要什么,并确保开发和生产环境保持尽可能接近。例如:

CompoundingFunction:
  Type: AWS::Serverless::Function
  Metadata:
    BuildMethod: makefile
  Properties:
    FunctionName: CompoundingFunction
    Architectures: ["arm64"]
    Handler: bootstrap
    Runtime: provided.al2
    CodeUri: ./functions/CompoundingFunction/
    MemorySize: 512
    Timeout: 10
    Environment:
      Variables:
        COMPOUNDING_TABLE_NAME: !Ref CompoundingTable
    Policies:
      - DynamoDBCrudPolicy:
          TableName: !Ref CompoundingTable
    Events:
      ApiGatewayPost:
        Type: Api
        Properties:
          RestApiId: !Ref ApiGateway
          Path: /compounding
          Method: POST

软件中良好的命名约定是关键

如果您有一套好的测试,请不要害怕重构。重构是软件开发中的一项重要活动。名称很重要,因为它们出现在模块、函数、包、变量等中的任何地方。

package main

import (
    "context"
    "encoding/json"
    "fmt"
    "github.com/aws/aws-lambda-go/events"
    "github.com/aws/aws-lambda-go/lambda"
)

// Response is the structure for the response JSON
type Response struct {
    Message      string    `json:"message"`
    GainsPerYear []float64 `json:"gainsPerYear"`
}

type Request struct {
    Principal  float64 `json:"principal"`
    AnnualRate float64 `json:"annualRate"`
    Years      int     `json:"years"`
}

func HelloHandler(ctx context.Context, event events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
    var req Request
    err := json.Unmarshal([]byte(event.Body), &req)
    if err != nil {
        return createResponse(400, "Invalid request body")
    }
    fmt.Println("Request", req)
    gainsPerYear := CalculateCompoundInterest(req.Principal, req.AnnualRate, req.Years)
    fmt.Println(gainsPerYear)
    response := Response{
        Message:      "Calculation successful",
        GainsPerYear: gainsPerYear,
    }

    body, err := json.Marshal(response)
    if err != nil {
        return createResponse(500, "Error marshalling response")
    }

    return createResponse(200, string(body))
}

func createResponse(statusCode int, body string) (events.APIGatewayProxyResponse, error) {
    return events.APIGatewayProxyResponse{
        StatusCode: statusCode,
        Body:       body,
        Headers:    map[string]string{"Content-Type": "application/json"},
    }, nil
}

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

永远测试你的逻辑

在无服务器应用程序中,单元测试很重要,但不要忘记还包括集成测试,因为大多数这些应用程序都依赖集成和策略来解决业务问题。

func TestCalculateCompoundInterest(t *testing.T) {
    principal := 100000000.0
    annualRate := 10.0
    years := 10

    result := CalculateCompoundInterest(principal, annualRate, years)
    lastElement := round(result[len(result)-1], 2)

    expected := round(259374246.01, 2)
    if !reflect.DeepEqual(lastElement, expected) {
        t.Errorf("Expected %v, but got %v", expected, lastElement)
    }
}

可用性和可扩展性

无服务器架构默认情况下高度可用,并且是事件驱动的,消除了大多数操作任务。但是,如果您选择依赖 ECS 和容器,那么包含负载均衡器来在服务器之间分配流量以确保可用性和可扩展性非常重要。

  CompoundingLoadBalancer:
    Type: AWS::ElasticLoadBalancingV2::LoadBalancer
    Properties:
      Name: compounding-nlb
      Scheme: internet-facing
      Type: network
      Subnets:
        - !Ref PublicSubnetOne
        - !Ref PublicSubnetTwo

部署管道

部署管道使软件交付过程自动化。我们创建了一个 Makefile 来简化此过程,从而可以使用单个命令轻松部署和执行重复任务。这种方法提高了部署工作流程的效率和一致性。

Build Go Serverless REST APIs and Deploy to AWS using the SAM framework (Amazon Linux untime)

可观察性是强制性的

确保您有跟踪、日志记录和指标。对于无服务器应用程序,启用这些功能就像添加 Tracing: Active 一样简单。在 CloudWatch 等中心位置查看所有日志并监控服务交互的能力是非常宝贵的。

Build Go Serverless REST APIs and Deploy to AWS using the SAM framework (Amazon Linux untime)

安全性是云原生应用程序中的一等公民

安全性在所有应用程序中都是最重要的。使用 Amazon Cognito 提供强大的用户身份验证,而 API 密钥添加了额外的控制和授权层,确保只有授权的客户端才能访问您的 API。

Auth:
  DefaultAuthorizer: CompoundingAuthorizer
  Authorizers:
    CompoundingAuthorizer:
      UserPoolArn:  XXXX
    LambdaTokenAuthorizer:
      FunctionArn: !GetAtt LambdaTokenAuthorizerFunction.Arn
      FunctionPayloadType: REQUEST
      Identity:
        Headers:
          - Authorization
        ReauthorizeEvery: 100
  AddDefaultAuthorizerToCorsPreflight: false

为每个服务、用户和组件分配最少的必要权限,以减少攻击面并防止未经授权的访问。 最小特权原则

      Policies:
        - DynamoDBCrudPolicy:
            TableName: !Ref CompoundingTable

参考

  1. Terraform in Action - 实施 Terraform 的实际用途和策略,Terraform 是一种用于构建、更改和管理基础设施的工具。
  2. 持续交付管道

结论

软件在不断发展,虽然一些工具和实践会发生变化,但基本原则保持不变。我们需要不可变的基础设施、CI/CD、良好的命名约定、强大的测试策略、API 的安全性以及应用程序的效率。这就是为什么我决定以无服务器方式重新创建这个项目。

现在是成为工程师并通过软件为社会创造价值的最佳时机。

  • 领英
  • 推特
  • GitHub

如果您喜欢这些文章,请访问我的博客 jorgetovar.dev

以上是使用 SAM 框架构建 Go Serverless REST API 并部署到 AWS (Amazon Linux untime)的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn