」工欲善其事,必先利其器。「—孔子《論語.錄靈公》
首頁 > 程式設計 > 使用 SAM 框架建置 Go Serverless REST API 並部署到 AWS (Amazon Linux untime)

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

發佈於2024-09-18
瀏覽:311

为什么还要另一个 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

版本聲明 本文轉載於:https://dev.to/aws-builders/build-go-serverless-rest-apis-and-deploy-to-aws-using-the-sam-framework-amazon-linux-2-runtime- 4n5p?1如有侵犯,請聯絡[email protected]刪除
最新教學 更多>
  • 如何在react中使用PKCE實現oAuth以進行第三方集成
    如何在react中使用PKCE實現oAuth以進行第三方集成
    在為第三方整合實作oAuth時,我偶然發現了一些很長一段時間沒有更新的資訊。在這裡,我試著記錄我的經驗及其運作方式 注意:本文不會詳細討論oAuth及其運作方式。主要關注如何在 React 應用程式中配置和實現它們。如果您想了解 oAuth,請閱讀此處。提供清晰的資訊。 流程: 大...
    程式設計 發佈於2024-11-07
  • 為什麼我在 POST Jersey 請求中收到不支援的媒體類型錯誤?
    為什麼我在 POST Jersey 請求中收到不支援的媒體類型錯誤?
    POST Jersey 請求中不支援的媒體類型錯誤遇到HTTP 狀態代碼415 - 對Jersey 的POST 請求中不支持的媒體類型REST 服務,問題通常在於Jersey 發行版中缺少JSON/POJO 支援。要解決此錯誤,需要在專案中新增必要的 JAR 依賴項。 具體來說,需要以下依賴:jer...
    程式設計 發佈於2024-11-07
  • 針對 XSS 的常見防禦措施有哪些?
    針對 XSS 的常見防禦措施有哪些?
    針對 XSS 的常見防禦輸入和輸出清理是防止跨站腳本 (XSS) 攻擊的關鍵技術。本文探討了產業和個人網站廣泛採用的減輕這種威脅的方法。 1。 HTML 轉義:在將所有使用者輸入顯示為 HTML 程式碼之前徹底轉義它們。這涉及將“”、“&”和“等字元替換為其相應的HTML 實體(例如,“”、“&”、...
    程式設計 發佈於2024-11-07
  • Python垃圾收集器如何自動管理記憶體?
    Python垃圾收集器如何自動管理記憶體?
    Python 垃圾收集器文件Python 垃圾收集器是一個記憶體管理系統,可以自動釋放程式不再使用的記憶體。這有助於透過防止記憶體洩漏並確保程式不會耗盡記憶體來提高效能。 垃圾收集器的工作過程分為兩步:引用計數: 解釋器追蹤每個物件的引用數量。當引用計數達到零時,該物件被認為不可達,並添加到要刪除的...
    程式設計 發佈於2024-11-07
  • PHP 如何有效率地處理大整數?
    PHP 如何有效率地處理大整數?
    PHP 可以處理大整數嗎? PHP 可能沒有明確的「BigInteger」類,但它提供了幾種處理大整數的方法整數。 使用 BC 數學函數PHP 提供BC 數學函數,如用於整數算術的 bcadd() 和 bcsub()。然而,這種方法對於大量計算來說可能會很慢。 使用 GMP 擴展GMP(GNU 多精...
    程式設計 發佈於2024-11-07
  • 如何使用 Python 字串匹配驗證 IP 位址輸入?
    如何使用 Python 字串匹配驗證 IP 位址輸入?
    使用 Python 驗證 IP 位址輸入驗證使用者輸入的 IP 位址在各種應用中至關重要。本文將探討驗證以字串形式提供的 IP 位址合法性的最有效方法。 首選方法偏離解析,而是利用 Python 標準函式庫的套接字模組。透過利用 inet_aton(),我們可以確定輸入字串是否代表有效的 IP 位址...
    程式設計 發佈於2024-11-07
  • 那麼 Pull 請求如何再次發揮作用呢?螢幕顯示#3
    那麼 Pull 請求如何再次發揮作用呢?螢幕顯示#3
    在我之前的文章中,我談到了啟動一個基於開源 GenAI 的終端應用程式。本週的任務是為另一個用戶的專案貢獻一個新功能。由於我們必須與新人合作,所以我與 Lily 合作,她開發了一個應用程序,其代碼改進功能與我的類似,只是她的角色是老鼠! 有時間的話可以去看看她的專案老鼠助手。 她的程式碼是用 T...
    程式設計 發佈於2024-11-07
  • 為什麼 Go 中不能直接將 []string 轉換為 []interface{}?
    為什麼 Go 中不能直接將 []string 轉換為 []interface{}?
    為什麼將[]string 轉換為[]interface{} 會在Go 中引發編譯錯誤轉換字串切片([] string)考慮到它們共享切片特徵以及[]string 的每個元素都可以被視為一個接口,Go 中的接口切片([]interface{}) 似乎很簡單。然而,嘗試這種轉換時會出現編譯錯誤,讓程式設...
    程式設計 發佈於2024-11-07
  • 理解 Shadow DOM:封裝 Web 元件的關鍵
    理解 Shadow DOM:封裝 Web 元件的關鍵
    在現代 Web 開發中,創建可重複使用和可維護的元件至關重要。 Shadow DOM 是 Web 元件標準的一部分,在實現這一目標方面發揮著至關重要的作用。本文深入探討了 Shadow DOM 的概念、它的優點以及如何在您的專案中有效地使用它。 什麼是 Shadow DOM? Sh...
    程式設計 發佈於2024-11-07
  • 如何使用 Java 運行時解決輸出重定向問題?
    如何使用 Java 運行時解決輸出重定向問題?
    使用Runtime 的exec() 方法解決輸出重定向問題在Java 中,利用Runtime.getRuntime().exec() 運行指令可以擷取進程的輸出和錯誤流。但是,在需要輸出重定向的情況下,單獨使用此方法可能會無效。 問題:輸出未重定向當使用Runtime.getRuntime().ex...
    程式設計 發佈於2024-11-07
  • 如何使用 CSS 懸停效果從左到右填滿背景顏色?
    如何使用 CSS 懸停效果從左到右填滿背景顏色?
    使用CSS 從左到右填充背景顏色在CSS 中,您可以透過利用線性漸層和動畫背景定位來創造迷人的懸停效果。這種方法使您能夠在懸停時從左到右用新顏色填充元素的背景。 線性漸變和背景大小關鍵是使用由兩種顏色組成的線性漸變背景,並將背景大小設定為元素寬度的兩倍。這允許您在兩種顏色之間創建無縫過渡。 背景定位...
    程式設計 發佈於2024-11-07
  • GraalVM 本機映像中的記憶體管理
    GraalVM 本機映像中的記憶體管理
    内存管理是计算机软件开发的重要组成部分,负责应用程序中内存的有效分配、利用和释放。其重要性在于增强软件性能,保证系统稳定性。 垃圾收集 垃圾收集 (GC) 在 Java 和 Go 等当代编程语言中至关重要。它自动检测并回收未使用的内存,从而减轻开发人员手动管理内存的需要。 GC 的概...
    程式設計 發佈於2024-11-07
  • ## 在 C++ 中什麼時候應該使用參考作為函數參數?
    ## 在 C++ 中什麼時候應該使用參考作為函數參數?
    在 C 中傳遞參數:瞭解引用在 C 中,函數參數的行為由其型別決定。一個重要的區別是「按值傳遞」和「按引用傳遞」。 為什麼在函數參數中使用引用? 引用在函數參數中用於兩種情況主要原因:修改參數:引用允許函數修改值論證通過了。這意味著該函數可以進行呼叫者可見的更改。 避免物件複製: 透過引用傳遞大物件...
    程式設計 發佈於2024-11-07
  • 為什麼會出現“getaddrinfo 失敗”以及如何修復?
    為什麼會出現“getaddrinfo 失敗”以及如何修復?
    探索“getaddrinfo failed”錯誤名稱解析過程中發生錯誤“getaddrinfo failed”,其中主機名稱被翻譯轉換為IP 位址。它顯示所提供的主機名的解析有問題。 深入研究錯誤情境從提供的錯誤追蹤中,我們可以將原因追溯到套接字。 getaddrinfo(主機,連接埠)方法。當無法...
    程式設計 發佈於2024-11-07
  • 如何在單一命令列中運行多行命令?
    如何在單一命令列中運行多行命令?
    如何在一行命令列中執行多行語句使用Python的-c選項執行單行循環時,在循環之前導入模組會導致語法錯誤。這是因為Python解釋器將程式碼區塊視為單一語句。 要解決此問題,可以採用以下幾種方法:使用管道要克服語法錯誤,請使用echo 命令將程式碼區塊作為一系列輸入行重定向到Python:echo ...
    程式設計 發佈於2024-11-07

免責聲明: 提供的所有資源部分來自互聯網,如果有侵犯您的版權或其他權益,請說明詳細緣由並提供版權或權益證明然後發到郵箱:[email protected] 我們會在第一時間內為您處理。

Copyright© 2022 湘ICP备2022001581号-3