Introducción a serverless y desacoplamiento

Clase 60 de 72Curso de AWS Certified Solutions Architect Associate

Introducción a Serverless y Desacoplamiento

En 2018, Nexiabank enfrentaba problemas de escalabilidad durante su evento anual de ventas. Su arquitectura monolítica colapsaba bajo la carga, causando pérdidas significativas. Al migrar a una arquitectura serverless basada en microservicios desacoplados mediante SQS y Lambda, lograron manejar un aumento de tráfico del 500% en su siguiente evento, mientras reducían sus costos operativos en un 40%. Esta transformación ilustra el poder real de los patrones serverless y el desacoplamiento.

Microservicios y Mensajería Asíncrona

Evolución de Arquitecturas

Las arquitecturas de aplicaciones han evolucionado significativamente:

  1. Monolíticas: Aplicaciones como bloques únicos donde todos los componentes están interconectados
  2. Orientadas a servicios (SOA): División en servicios con responsabilidades específicas
  3. Microservicios: Descomposición en componentes pequeños e independientes

Los microservicios ofrecen numerosas ventajas:

  • Desarrollo independiente y paralelo
  • Despliegue aislado
  • Escalabilidad granular
  • Resiliencia mejorada
  • Selección de tecnología por caso de uso

Sin embargo, la comunicación entre microservicios presenta desafíos. Es aquí donde la mensajería asíncrona juega un papel crucial.

Amazon SQS (Simple Queue Service)

Amazon SQS es un servicio de colas de mensajes gestionado que permite desacoplar y escalar microservicios, sistemas distribuidos y aplicaciones serverless.

Características principales:

  • Colas estándar: alto rendimiento, entrega al menos una vez
  • Colas FIFO: garantiza orden y entrega exactamente una vez
  • Retención de mensajes configurable (hasta 14 días)
  • Visibilidad de mensajes configurable
  • Cifrado en reposo y en tránsito
  • Políticas de acceso basadas en recursos

Screenshot (44).png

// Ejemplo de envío de mensaje a SQS usando AWS SDK para Node.js const AWS = require('aws-sdk'); const sqs = new AWS.SQS({region: 'us-east-1'}); exports.handler = async (event) => { const params = { QueueUrl: '<https://sqs.us-east-1.amazonaws.com/123456789012/mi-cola>', MessageBody: JSON.stringify({ orderId: 'ORD-12345', customer: 'Cliente A', items: 3, total: 150.75 }), MessageAttributes: { 'OrderType': { DataType: 'String', StringValue: 'Prioritario' } } }; try { const result = await sqs.sendMessage(params).promise(); return { statusCode: 200, body: `Mensaje enviado: ${result.MessageId}` }; } catch (error) { return { statusCode: 500, body: `Error: ${error.message}` }; } };

Amazon SNS (Simple Notification Service)

Amazon SNS es un servicio de mensajería pub/sub gestionado para la comunicación de aplicaciones a aplicaciones (A2A) y aplicaciones a personas (A2P).

Características principales:

  • Modelo publicador/suscriptor
  • Entrega a múltiples suscriptores simultáneamente
  • Soporta múltiples protocolos (HTTP/S, Email, SMS, SQS, Lambda, etc.)
  • Filtrado de mensajes basado en atributos
  • Entrega fiable con reintentos
  • Temas FIFO para mensajería ordenada

Screenshot (45).png

# Ejemplo de configuración de SNS en CloudFormation Resources: NotificationTopic: Type: AWS::SNS::Topic Properties: TopicName: sistema-notificaciones DisplayName: Notificaciones Tags: - Key: Environment Value: Production EmailSubscription: Type: AWS::SNS::Subscription Properties: TopicArn: !Ref NotificationTopic Protocol: email Endpoint: alertas@ejemplo.com LambdaSubscription: Type: AWS::SNS::Subscription Properties: TopicArn: !Ref NotificationTopic Protocol: lambda Endpoint: !GetAtt ProcesadorNotificaciones.Arn FilterPolicy: prioridad: ["alta", "crítica"]

Patrones de Integración SQS y SNS

Un patrón común es la combinación de SNS con SQS para crear un sistema de fanout con procesamiento desacoplado:

[Productor][SNS Topic][SQS Queue 1][Consumidor 1] [SQS Queue 2][Consumidor 2] [SQS Queue 3][Consumidor 3]

Este patrón permite:

  • Distribución de mensajes a múltiples servicios
  • Procesamiento a diferentes velocidades
  • Aislamiento de fallos
  • Capacidad de retención si un servicio está caído

Serverless: Fundamentos y Ventajas

¿Qué es Serverless?

Serverless no significa "sin servidores", sino "sin gestión de servidores". Es un modelo de ejecución donde:

  1. El proveedor cloud gestiona completamente la infraestructura
  2. La asignación de recursos es automática y elástica
  3. El cobro se basa en el consumo real, no en capacidad aprovisionada
  4. La arquitectura está orientada a eventos y funciones

Ventajas del Enfoque Serverless

  • Costo optimizado: Pago solo por lo que se usa, sin recursos ociosos
  • Escalabilidad automática: Desde cero a miles de instancias sin intervención
  • Reducción de operaciones: Sin parches, actualizaciones o mantenimiento de servidores
  • Agilidad: Ciclos de desarrollo más rápidos
  • Resiliencia: Distribución automática entre zonas de disponibilidad

AWS Lambda: Núcleo de Serverless

AWS Lambda es un servicio de computación que ejecuta código en respuesta a eventos sin necesidad de aprovisionar servidores.

Características clave:

  • Soporte para múltiples lenguajes (Node.js, Python, Java, Go, .NET, Ruby)
  • Escalado automático basado en carga
  • Integración nativa con servicios AWS
  • Modelo de seguridad basado en IAM
  • Entorno de ejecución aislado
  • Configuración de memoria (128MB a 10GB)
  • Tiempo de ejecución máximo (15 minutos) Screenshot (46).png
# Ejemplo de función Lambda en Python import json import boto3 import os dynamodb = boto3.resource('dynamodb') table = dynamodb.Table(os.environ['TABLE_NAME']) def lambda_handler(event, context): # Procesar evento de SQS for record in event['Records']: payload = json.loads(record['body']) # Guardar en DynamoDB response = table.put_item( Item={ 'id': payload['orderId'], 'customer': payload['customer'], 'amount': payload['total'], 'timestamp': payload['timestamp'] } ) return { 'statusCode': 200, 'body': json.dumps('Procesados ' + str(len(event['Records'])) + ' mensajes') }

Arquitecturas Event-Driven

Las arquitecturas event-driven se basan en la producción, detección, consumo y reacción a eventos. Un evento es cualquier cambio de estado significativo en el sistema.

Componentes Principales

  1. Productores de eventos: Generan eventos (ej: aplicaciones, servicios AWS, sensores)
  2. Bus de eventos: Enruta eventos a los consumidores (ej: EventBridge, SNS)
  3. Consumidores de eventos: Procesan eventos y ejecutan lógica de negocio (ej: Lambda)
  4. Almacenes de eventos: Registran eventos para análisis o reproducción (ej: Kinesis, S3)

Integraciones con Lambda

AWS Lambda puede integrarse con numerosos servicios como fuentes de eventos:

  • Amazon S3: Ejecución en respuesta a operaciones de objetos
  • DynamoDB Streams: Procesamiento de cambios en tablas
  • Kinesis: Análisis de flujos de datos en tiempo real
  • SQS/SNS: Procesamiento de mensajes
  • EventBridge: Reacción a eventos del sistema o personalizados
  • API Gateway: Creación de APIs serverless
# Ejemplo de integración Lambda con S3 en CloudFormation Resources: ProcessorFunction: Type: AWS::Lambda::Function Properties: Handler: index.handler Runtime: nodejs14.x Code: S3Bucket: mi-bucket-codigo S3Key: funciones/procesador-imagenes.zip Role: !GetAtt LambdaExecutionRole.Arn Environment: Variables: OUTPUT_BUCKET: !Ref OutputBucket LambdaPermission: Type: AWS::Lambda::Permission Properties: Action: lambda:InvokeFunction FunctionName: !Ref ProcessorFunction Principal: s3.amazonaws.com SourceArn: !GetAtt InputBucket.Arn InputBucket: Type: AWS::S3::Bucket Properties: NotificationConfiguration: LambdaConfigurations: - Event: s3:ObjectCreated:* Filter: S3Key: Rules: - Name: suffix Value: .jpg Function: !GetAtt ProcessorFunction.Arn

Diseño Desacoplado con Colas y Eventos

El desacoplamiento es una técnica de diseño que separa los componentes para que puedan funcionar de manera independiente.

Beneficios del Desacoplamiento

  • Resiliencia: Los fallos se aíslan y no se propagan
  • Escalabilidad: Los componentes escalan independientemente
  • Evolución: Los servicios pueden cambiar sin afectar a otros
  • Rendimiento: Procesamiento asíncrono para operaciones lentas

Patrones de Desacoplamiento

1. Cola de Tareas

[Servicio A][SQS Queue][Servicio B]

Ideal para:

  • Distribuir carga de trabajo
  • Manejar picos de tráfico
  • Procesar tareas en segundo plano

2. Fanout (Distribución)

[Servicio A][SNS Topic][Múltiples Suscriptores]

Ideal para:

  • Notificar a múltiples sistemas
  • Implementar patrones de observabilidad
  • Crear flujos de trabajo paralelos

3. Pipes and Filters

[Origen][SQS][Procesador 1][SQS][Procesador 2][Destino]

Ideal para:

  • Procesamiento secuencial
  • Transformaciones de datos en etapas
  • Flujos de trabajo complejos

4. Event Sourcing

[Servicios][Eventos][Event Store][Proyecciones]

Ideal para:

  • Auditoría completa
  • Reconstrucción de estado
  • Sistemas con requisitos de trazabilidad

Integración con Otros Servicios AWS

API Gateway

Amazon API Gateway permite crear, publicar y gestionar APIs RESTful y WebSocket que actúan como "puerta de entrada" a servicios backend, incluidas funciones Lambda.

# Ejemplo de API Gateway con integración Lambda Resources: ApiGateway: Type: AWS::ApiGateway::RestApi Properties: Name: MiAPI Description: API Serverless de ejemplo ApiResource: Type: AWS::ApiGateway::Resource Properties: RestApiId: !Ref ApiGateway ParentId: !GetAtt ApiGateway.RootResourceId PathPart: items ApiMethod: Type: AWS::ApiGateway::Method Properties: RestApiId: !Ref ApiGateway ResourceId: !Ref ApiResource HttpMethod: POST AuthorizationType: NONE Integration: Type: AWS_PROXY IntegrationHttpMethod: POST Uri: !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${LambdaFunction.Arn}/invocations

Step Functions

AWS Step Functions permite coordinar múltiples servicios AWS en flujos de trabajo visuales estructurados.

Screenshot (49).png

// Ejemplo de definición de máquina de estado en Step Functions { "Comment": "Proceso de aprobación de pedidos", "StartAt": "ValidarPedido", "States": { "ValidarPedido": { "Type": "Task", "Resource": "arn:aws:lambda:us-east-1:123456789012:function:ValidarPedido", "Next": "VerificarInventario" }, "VerificarInventario": { "Type": "Task", "Resource": "arn:aws:lambda:us-east-1:123456789012:function:VerificarInventario", "Next": "EvaluarDisponibilidad" }, "EvaluarDisponibilidad": { "Type": "Choice", "Choices": [ { "Variable": "$.disponible", "BooleanEquals": true, "Next": "ProcesarPago" } ], "Default": "NotificarNoDisponible" }, "ProcesarPago": { "Type": "Task", "Resource": "arn:aws:lambda:us-east-1:123456789012:function:ProcesarPago", "Next": "EnviarConfirmacion" }, "NotificarNoDisponible": { "Type": "Task", "Resource": "arn:aws:lambda:us-east-1:123456789012:function:NotificarNoDisponible", "End": true }, "EnviarConfirmacion": { "Type": "Task", "Resource": "arn:aws:lambda:us-east-1:123456789012:function:EnviarConfirmacion", "End": true } } }

EventBridge

Amazon EventBridge es un bus de eventos serverless que facilita la conexión de aplicaciones con datos de diversas fuentes.

Screenshot (48).png

# Ejemplo de regla de EventBridge Resources: EventRule: Type: AWS::Events::Rule Properties: Name: DetectarCambiosUsuario Description: Detecta cambios en usuarios y envía notificaciones EventPattern: source: - com.empresa.usuarios detail-type: - UsuarioActualizado detail: tipoUsuario: - premium State: ENABLED Targets: - Arn: !GetAtt NotificacionFunction.Arn Id: NotificarCambioUsuario

Arquitectura de Referencia: Sistema de Procesamiento de Pedidos

┌───────────┐ ┌───────────┐ ┌───────────┐ ┌───────────┐ │ │ │ │ │ │ │ │ API │────►│ Lambda │────►│ SNS │────►│ SQSGateway │ │ Validador │ │ Topic │ │ Queue│ │ │ │ │ │ │ │ └───────────┘ └───────────┘ └───────────┘ └───────────┘ │ │ ▼ ▼ ┌───────────┐ ┌───────────┐ │ │ │ │ Lambda │ │ LambdaNotificar │ │ Procesar │ │ │ │ └───────────┘ └───────────┘ ┌───────────┐ │ │ DynamoDB │ │ └───────────┘

En este ejemplo:

  1. API Gateway recibe solicitudes de pedidos
  2. Lambda valida los datos del pedido
  3. SNS distribuye el evento a múltiples suscriptores
  4. Una función Lambda envía notificaciones al cliente
  5. SQS almacena los pedidos para procesamiento asíncrono
  6. Otra función Lambda procesa los pedidos y los almacena en DynamoDB

Consideraciones y Buenas Prácticas

Gestión de Errores

  • Implementar reintentos con backoff exponencial
  • Utilizar colas de mensajes fallidos (DLQ)
  • Monitorear y alertar sobre fallos
  • Diseñar para idempotencia
# Ejemplo de configuración de DLQ para Lambda Resources: DeadLetterQueue: Type: AWS::SQS::Queue Properties: QueueName: MiFuncionDLQ MessageRetentionPeriod: 1209600 # 14 días MiFuncion: Type: AWS::Lambda::Function Properties: Handler: index.handler Runtime: nodejs14.x Code: S3Bucket: mi-bucket S3Key: codigo/funcion.zip DeadLetterConfig: TargetArn: !GetAtt DeadLetterQueue.Arn

Observabilidad

  • Utilizar AWS X-Ray para trazabilidad distribuida
  • Implementar logging estructurado
  • Configurar métricas personalizadas en CloudWatch
  • Crear dashboards para visualizar el estado del sistema

Seguridad

  • Aplicar el principio de mínimo privilegio en IAM
  • Cifrar datos en tránsito y en reposo
  • Validar y sanitizar entradas
  • Implementar autenticación y autorización en API Gateway

Costos

  • Monitorear y establecer presupuestos
  • Optimizar la duración y memoria de funciones Lambda
  • Utilizar reservas para cargas de trabajo predecibles
  • Implementar mecanismos de limitación (throttling)

Las arquitecturas serverless y los patrones de desacoplamiento representan un cambio fundamental en la forma de diseñar y operar aplicaciones en la nube. Al eliminar la necesidad de gestionar infraestructura y adoptar un enfoque orientado a eventos, los desarrolladores pueden centrarse en crear valor de negocio mientras AWS se encarga de la escalabilidad, disponibilidad y mantenimiento. La combinación de servicios como Lambda, SQS, SNS, API Gateway y Step Functions permite construir sistemas robustos, escalables y rentables que pueden adaptarse rápidamente a las cambiantes necesidades del negocio.

El verdadero poder de serverless no está solo en la reducción de costos operativos, sino en la agilidad que proporciona. La capacidad de experimentar, iterar y escalar rápidamente permite a las organizaciones innovar a un ritmo que sería imposible con arquitecturas tradicionales. Al adoptar estos patrones, estamos construyendo sistemas que no solo son técnicamente superiores, sino que también están mejor alineados con los objetivos comerciales de velocidad, flexibilidad y eficiencia.