"Si un trabajador quiere hacer bien su trabajo, primero debe afilar sus herramientas." - Confucio, "Las Analectas de Confucio. Lu Linggong"
Página delantera > Programación > Cree API REST Go Serverless e impleméntelas en AWS utilizando el marco SAM (Amazon Linux untime)

Cree API REST Go Serverless e impleméntelas en AWS utilizando el marco SAM (Amazon Linux untime)

Publicado el 2024-09-18
Navegar:343

¿Por qué otro tutorial?

AWS ha estado desaprobando varios servicios y tiempos de ejecución recientemente. Como hemos visto con la discontinuación de nuestro querido CodeCommit y otros servicios cruciales, Go1.x ya no es compatible con las funciones de AWS Lambda.

Si intentas implementar la mayoría de los tutoriales obsoletos, es posible que encuentres errores como este:

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.

La conclusión clave es que la única constante en el software es el cambio. Sin embargo, existen algunos principios eternos que siempre debemos tener en cuenta:

Para abordar este problema, decidí crear un repositorio actualizado con toda la infraestructura necesaria para implementar una aplicación Go. Hay dos opciones disponibles:

  1. Implementación con Fargate usando contenedores Docker.
  2. Implementación utilizando el marco SAM en AWS.

Puedes encontrar el repositorio en GitHub aquí.

Principios atemporales en el desarrollo de software

  • La infraestructura como código es esencial.
  • Las buenas convenciones de nomenclatura en el software son cruciales.
  • Siempre prueba tu lógica.
  • Disponibilidad y escalabilidad
  • Deployment Pipeline como mecanismo para automatizar el proceso de entrega de software.
  • La observabilidad es obligatoria.
  • La seguridad es un ciudadano de primera clase en las aplicaciones nativas de la nube.
  • Go es una excelente opción para crear API.

La infraestructura como código es esencial

La infraestructura inmutable nos permite declarar lo que queremos en un nivel superior y garantiza que los entornos de desarrollo y producción permanezcan lo más cerca posible. Por ejemplo:

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

Las buenas convenciones de nomenclatura en el software son clave

No tengas miedo de refactorizar si tienes un buen conjunto de pruebas. La refactorización es una actividad esencial en el desarrollo de software. Los nombres son importantes ya que aparecen en todas partes en módulos, funciones, paquetes, variables, etc.

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)
}

Pon a prueba siempre tu lógica

En las aplicaciones sin servidor, las pruebas unitarias son importantes, pero no olvide incluir también pruebas de integración, ya que la mayoría de estas aplicaciones dependen de integraciones y políticas para resolver problemas comerciales.

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)
    }
}

Disponibilidad y escalabilidad

Las arquitecturas sin servidor tienen alta disponibilidad de forma predeterminada y están controladas por eventos, lo que elimina la mayoría de las tareas operativas. Sin embargo, si elige confiar en ECS y contenedores, es importante incluir un equilibrador de carga para distribuir el tráfico entre sus servidores, garantizando tanto la disponibilidad como la escalabilidad.

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

Canal de implementación

Un proceso de implementación automatiza el proceso de entrega de software. Creamos un Makefile para simplificar este proceso, facilitando la implementación y ejecución de tareas repetitivas con un solo comando. Este enfoque mejora la eficiencia y la coherencia en su flujo de trabajo de implementación.

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

La observabilidad es obligatoria

Asegúrese de contar con seguimiento, registro y métricas implementadas. Con las aplicaciones sin servidor, habilitar estas funciones es tan simple como agregar Tracing: Active. La capacidad de ver todos los registros en un lugar central como CloudWatch y monitorear las interacciones del servicio es invaluable.

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

La seguridad es un ciudadano de primera clase en las aplicaciones nativas de la nube

La seguridad es primordial en toda la aplicación. El uso de Amazon Cognito proporciona una autenticación de usuario sólida, mientras que las claves API agregan una capa adicional de control y autorización, lo que garantiza que solo los clientes autorizados puedan acceder a sus API.

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

Asigne los permisos mínimos necesarios a cada servicio, usuario y componente para reducir la superficie de ataque y evitar el acceso no autorizado. Principio de privilegio mínimo:

      Policies:
        - DynamoDBCrudPolicy:
            TableName: !Ref CompoundingTable

Referencias

  1. Terraform en acción: usos prácticos y estrategias para implementar Terraform, una herramienta para construir, cambiar y gestionar infraestructura.
  2. Tuberías de entrega continua

Conclusión

El software evoluciona constantemente y, si bien algunas herramientas y prácticas cambiarán, los principios fundamentales siguen siendo los mismos. Necesitamos una infraestructura inmutable, CI/CD, buenas convenciones de nomenclatura, una estrategia de prueba sólida, seguridad en nuestras API y eficiencia en nuestras aplicaciones. Por eso decidí recrear este proyecto sin servidor.

Nunca ha habido un mejor momento para ser ingeniero y crear valor en la sociedad a través del software.

  • LinkedIn
  • Gorjeo
  • GitHub

Si te gustaron los artículos, visita mi blog jorgetovar.dev

Declaración de liberación Este artículo se reproduce en: https://dev.to/aws-builders/build-go-serverless-rest-apis-and-deploy-to-aws-using-the-sam-framework-amazon-linux-2- runtime- 4n5p?1 Si hay alguna infracción, comuníquese con [email protected] para eliminarla.
Último tutorial Más>

Descargo de responsabilidad: Todos los recursos proporcionados provienen en parte de Internet. Si existe alguna infracción de sus derechos de autor u otros derechos e intereses, explique los motivos detallados y proporcione pruebas de los derechos de autor o derechos e intereses y luego envíelos al correo electrónico: [email protected]. Lo manejaremos por usted lo antes posible.

Copyright© 2022 湘ICP备2022001581号-3