Microservices Architecture Overview
Microservices Architecture Overview
Microservices are small, independent services that communicate over well-defined APIs.
Monolith vs Microservices
| Aspect | Monolith | Microservices |
|---|---|---|
| Deployment | Single unit | Independent |
| Scaling | Entire app | Individual services |
| Technology | Single stack | Polyglot |
| Failure | Entire app down | Isolated |
| Team | Large, shared | Small, autonomous |
Microservices on AWS
┌─────────────────────────────────────────────────────────────┐
│ Microservices Architecture │
├─────────────────────────────────────────────────────────────┤
│ │
│ API Gateway ──┬──▶ User Service (ECS/Lambda) │
│ │ └──▶ DynamoDB │
│ │ │
│ ├──▶ Order Service (ECS/Lambda) │
│ │ └──▶ RDS │
│ │ │
│ ├──▶ Payment Service (ECS/Lambda) │
│ │ └──▶ SQS ──▶ Processing │
│ │ │
│ └──▶ Notification Service (Lambda) │
│ └──▶ SNS ──▶ Email/SMS │
│ │
│ Communication: │
│ Synchronous: API Gateway, ALB │
│ Asynchronous: SQS, SNS, EventBridge │
└─────────────────────────────────────────────────────────────┘
AWS Services for Microservices
| Service | Purpose |
|---|---|
| ECS/EKS | Container orchestration |
| Lambda | Serverless compute |
| API Gateway | API management |
| SQS/SNS | Async messaging |
| Step Functions | Workflow orchestration |
| Service Discovery | Service registration |
Container Orchestration with ECS
Container Orchestration with ECS
ECS Cluster
# Create ECS cluster
aws ecs create-cluster --cluster-name my-cluster
# Create task definition
aws ecs register-task-definition \
--family my-app \
--network-mode awsvpc \
--requires-compatibilities FARGATE \
--cpu 256 \
--memory 512 \
--container-definitions '[{
"name": "my-app",
"image": "123456789012.dkr.ecr.us-east-1.amazonaws.com/my-app:latest",
"portMappings": [{"containerPort": 8080, "protocol": "tcp"}],
"environment": [{"name": "ENV", "value": "production"}],
"secrets": [{"name": "DB_PASSWORD", "valueFrom": "arn:aws:secretsmanager:us-east-1:xxx:secret:db-password"}]
}]'
# Create service
aws ecs create-service \
--cluster my-cluster \
--service-name my-service \
--task-definition my-app \
--desired-count 3 \
--launch-type FARGATE \
--network-configuration '{
"awsvpcConfiguration": {
"subnets": ["subnet-xxx", "subnet-yyy"],
"securityGroups": ["sg-xxx"],
"assignPublicIp": "DISABLED"
}
}' \
--load-balancers '[{
"targetGroupArn": "arn:aws:elasticloadbalancing:us-east-1:xxx:targetgroup/my-tg/xxx",
"containerName": "my-app",
"containerPort": 8080
}]' \
--health-check-grace-period-seconds 60
Auto Scaling
# Register scalable target
aws application-autoscaling register-scalable-target \
--service-namespace ecs \
--scalable-dimension ecs:service:DesiredCount \
--resource-id service/my-cluster/my-service \
--min-capacity 2 \
--max-capacity 20
# Target tracking policy
aws application-autoscaling put-scaling-policy \
--service-namespace ecs \
--scalable-dimension ecs:service:DesiredCount \
--resource-id service/my-cluster/my-service \
--policy-name cpu-tracking \
--policy-type TargetTrackingScaling \
--target-tracking-scaling-policy-configuration '{
"TargetValue": 70.0,
"PredefinedMetricSpecification": {
"PredefinedMetricType": "ECSServiceAverageCPUUtilization"
}
}'
Service Communication Patterns
Service Communication Patterns
Synchronous Communication
# API Gateway routing
aws apigateway create-resource --path-part users
aws apigateway create-resource --path-part orders
# ALB path-based routing
aws elbv2 create-rule \
--listener-arn arn:xxx \
--conditions Field=path-pattern,Values="/api/users/*" \
--actions Type=forward,TargetGroupArn=arn:xxx
Asynchronous Communication
# SQS for decoupled communication
aws sqs create-queue --queue-name order-processing-queue
# SNS for pub/sub
aws sns create-topic --name order-events
# Subscribe Lambda to SNS
aws sns subscribe \
--topic-arn arn:aws:sns:us-east-1:xxx:order-events \
--protocol lambda \
--notification-endpoint arn:aws:lambda:us-east-1:xxx:function:process-order
# EventBridge for event-driven
aws events put-rule \
--name order-created \
--event-pattern '{
"source": ["myapp.orders"],
"detail-type": ["OrderCreated"]
}'
Service Mesh (App Mesh)
# Create mesh
aws appmesh create-mesh --mesh-name my-mesh
# Create virtual node
aws appmesh create-virtual-node \
--mesh-name my-mesh \
--virtual-node-name user-service \
--spec '{
"listeners": [{"portMapping": {"port": 8080, "protocol": "http"}}],
"backends": [{"virtualService": {"virtualServiceName": "order-service.my-mesh"}}]
}'
Resilience Patterns
Resilience Patterns
Circuit Breaker
import boto3
import time
class CircuitBreaker:
def __init__(self, service_name):
self.state = 'CLOSED'
self.failure_count = 0
self.failure_threshold = 5
self.timeout = 30
self.last_failure_time = 0
def call(self, func, *args, **kwargs):
if self.state == 'OPEN':
if time.time() - self.last_failure_time > self.timeout:
self.state = 'HALF_OPEN'
else:
raise Exception('Circuit breaker is OPEN')
try:
result = func(*args, **kwargs)
if self.state == 'HALF_OPEN':
self.state = 'CLOSED'
self.failure_count = 0
return result
except Exception as e:
self.failure_count += 1
self.last_failure_time = time.time()
if self.failure_count >= self.failure_threshold:
self.state = 'OPEN'
raise
Retry with Backoff
import time
import random
def retry_with_backoff(func, max_retries=3, base_delay=1):
for attempt in range(max_retries):
try:
return func()
except Exception as e:
if attempt == max_retries - 1:
raise
delay = base_delay * (2 ** attempt) + random.uniform(0, 1)
time.sleep(delay)
Dead Letter Queue
# Create DLQ
aws sqs create-queue --queue-name order-processing-dlq
# Configure redrive policy
aws sqs set-queue-attributes \
--queue-url https://sqs.us-east-1.amazonaws.com/123456789012/order-processing-queue \
--attributes '{
"RedrivePolicy": "{\"deadLetterTargetArn\":\"arn:aws:sqs:us-east-1:123456789012:order-processing-dlq\",\"maxReceiveCount\":\"3\"}"
}'
Microservices Best Practices
Microservices Best Practices
Design Principles
- Single Responsibility: Each service does one thing well
- Loose Coupling: Services can be deployed independently
- High Cohesion: Related functionality in same service
- Database per Service: Each service owns its data
- API First: Design APIs before implementation
Deployment Strategies
# Blue/Green with ECS
aws ecs update-service \
--cluster my-cluster \
--service my-service \
--task-definition my-app:2
# Canary with CodeDeploy
aws codedeploy create-deployment \
--application-name my-app \
--deployment-group-name my-ecs-group \
--deployment-config-name CodeDeployDefault.ECSCanary10Percent5Minutes
Monitoring
# Distributed tracing with X-Ray
aws xray put-trace-summaries --start-time $(date -u -d '1 hour ago') --end-time $(date -u)
# Service metrics
aws cloudwatch get-metric-statistics \
--namespace AWS/ECS \
--metric-name CPUUtilization \
--dimensions Name=ClusterName,Value=my-cluster Name=ServiceName,Value=my-service
Security
# Service-to-service authentication with IAM
# Network isolation with VPC and security groups
# Secret management with Secrets Manager
# API authentication with Cognito or Lambda authorizers