在 Day 17 我們建立了微服務部署架構,今天我們要聚焦在 AWS 雲端效能優化。從 CloudFront CDN 配置、Auto Scaling 智能擴展、到 RDS 效能調校,我們將實現企業級的雲端效能最佳化方案,確保 SaaS 系統在雲端環境中達到最佳效能表現。
# infrastructure/cloudfront-optimization.yml
Resources:
OptimizedCloudFrontDistribution:
Type: AWS::CloudFront::Distribution
Properties:
DistributionConfig:
# 基礎配置
Enabled: true
HttpVersion: http2
PriceClass: PriceClass_All
IPV6Enabled: true
# 來源配置
Origins:
- Id: S3-StaticAssets
DomainName: !GetAtt S3Bucket.DomainName
S3OriginConfig:
OriginAccessIdentity: !Sub "origin-access-identity/cloudfront/${CloudFrontOAI}"
OriginCustomHeaders:
- HeaderName: X-Forwarded-Proto
HeaderValue: https
- Id: ALB-API
DomainName: !GetAtt ApplicationLoadBalancer.DNSName
CustomOriginConfig:
HTTPPort: 80
HTTPSPort: 443
OriginProtocolPolicy: https-only
OriginSSLProtocols: [TLSv1.2]
OriginReadTimeout: 30
OriginKeepaliveTimeout: 5
# 快取行為配置
DefaultCacheBehavior:
TargetOriginId: S3-StaticAssets
ViewerProtocolPolicy: redirect-to-https
CachePolicyId: !Ref OptimizedCachePolicy
OriginRequestPolicyId: !Ref CORSRequestPolicy
ResponseHeadersPolicyId: !Ref SecurityHeadersPolicy
Compress: true
# Lambda@Edge 功能
LambdaFunctionAssociations:
- EventType: viewer-request
LambdaFunctionARN: !GetAtt EdgeOptimizationFunction.FunctionArn
- EventType: origin-response
LambdaFunctionARN: !GetAtt CompressionOptimizationFunction.FunctionArn
CacheBehaviors:
# API 快取行為
- PathPattern: "/api/*"
TargetOriginId: ALB-API
ViewerProtocolPolicy: https-only
CachePolicyId: !Ref APICachePolicy
OriginRequestPolicyId: !Ref APIRequestPolicy
AllowedMethods: [GET, HEAD, OPTIONS, PUT, POST, PATCH, DELETE]
CachedMethods: [GET, HEAD, OPTIONS]
Compress: true
# 靜態資源快取行為
- PathPattern: "/static/*"
TargetOriginId: S3-StaticAssets
ViewerProtocolPolicy: redirect-to-https
CachePolicyId: !Ref StaticAssetsCachePolicy
Compress: true
# 動態內容快取行為
- PathPattern: "/app/*"
TargetOriginId: S3-StaticAssets
ViewerProtocolPolicy: redirect-to-https
CachePolicyId: !Ref DynamicContentCachePolicy
OriginRequestPolicyId: !Ref CORSRequestPolicy
Compress: true
# 自訂錯誤頁面
CustomErrorResponses:
- ErrorCode: 404
ResponseCode: 200
ResponsePagePath: /index.html
ErrorCachingMinTTL: 300
- ErrorCode: 403
ResponseCode: 200
ResponsePagePath: /index.html
ErrorCachingMinTTL: 300
# 優化的快取策略
OptimizedCachePolicy:
Type: AWS::CloudFront::CachePolicy
Properties:
CachePolicyConfig:
Name: OptimizedCachePolicy
DefaultTTL: 86400 # 1 天
MaxTTL: 31536000 # 1 年
MinTTL: 0
ParametersInCacheKeyAndForwardedToOrigin:
EnableAcceptEncodingGzip: true
EnableAcceptEncodingBrotli: true
QueryStringsConfig:
QueryStringBehavior: whitelist
QueryStrings: [version, locale, theme]
HeadersConfig:
HeaderBehavior: whitelist
Headers:
- Accept-Language
- Accept-Encoding
- User-Agent
CookiesConfig:
CookieBehavior: whitelist
Cookies: [session-id, user-preferences]
# API 專用快取策略
APICachePolicy:
Type: AWS::CloudFront::CachePolicy
Properties:
CachePolicyConfig:
Name: APICachePolicy
DefaultTTL: 300 # 5 分鐘
MaxTTL: 3600 # 1 小時
MinTTL: 0
ParametersInCacheKeyAndForwardedToOrigin:
EnableAcceptEncodingGzip: true
EnableAcceptEncodingBrotli: true
QueryStringsConfig:
QueryStringBehavior: all
HeadersConfig:
HeaderBehavior: whitelist
Headers:
- Authorization
- Content-Type
- X-API-Key
- Accept
CookiesConfig:
CookieBehavior: none
# 靜態資源快取策略
StaticAssetsCachePolicy:
Type: AWS::CloudFront::CachePolicy
Properties:
CachePolicyConfig:
Name: StaticAssetsCachePolicy
DefaultTTL: 604800 # 7 天
MaxTTL: 31536000 # 1 年
MinTTL: 604800 # 7 天
ParametersInCacheKeyAndForwardedToOrigin:
EnableAcceptEncodingGzip: true
EnableAcceptEncodingBrotli: true
QueryStringsConfig:
QueryStringBehavior: whitelist
QueryStrings: [v, version]
HeadersConfig:
HeaderBehavior: none
CookiesConfig:
CookieBehavior: none
// lambda-edge/edge-optimization.js
'use strict';
// 檢視器請求優化
exports.viewerRequest = (event, context, callback) => {
const request = event.Records[0].cf.request;
const headers = request.headers;
// 1. 裝置類型檢測與優化
const userAgent = headers['user-agent'] ? headers['user-agent'][0].value : '';
const isMobile = /Mobile|Android|iPhone|iPad/i.test(userAgent);
if (isMobile) {
// 行動裝置路由到優化版本
if (request.uri.startsWith('/static/')) {
request.uri = request.uri.replace('/static/', '/static/mobile/');
}
}
// 2. 地理位置路由
const countryCode = headers['cloudfront-viewer-country'] ?
headers['cloudfront-viewer-country'][0].value : 'US';
// 為特定地區提供本地化內容
if (['CN', 'JP', 'KR'].includes(countryCode)) {
headers['x-region'] = [{ key: 'X-Region', value: 'asia' }];
}
// 3. 壓縮算法協商
const acceptEncoding = headers['accept-encoding'] ?
headers['accept-encoding'][0].value : '';
if (acceptEncoding.includes('br')) {
headers['x-preferred-encoding'] = [{ key: 'X-Preferred-Encoding', value: 'br' }];
} else if (acceptEncoding.includes('gzip')) {
headers['x-preferred-encoding'] = [{ key: 'X-Preferred-Encoding', value: 'gzip' }];
}
// 4. 快取優化 Headers
if (request.uri.match(/\.(css|js|png|jpg|jpeg|gif|ico|svg|woff|woff2)$/)) {
headers['cache-control'] = [{
key: 'Cache-Control',
value: 'public, max-age=31536000, immutable'
}];
}
// 5. 安全性 Headers
headers['strict-transport-security'] = [{
key: 'Strict-Transport-Security',
value: 'max-age=31536000; includeSubDomains; preload'
}];
headers['x-content-type-options'] = [{
key: 'X-Content-Type-Options',
value: 'nosniff'
}];
headers['x-frame-options'] = [{
key: 'X-Frame-Options',
value: 'SAMEORIGIN'
}];
callback(null, request);
};
// 來源響應優化
exports.originResponse = (event, context, callback) => {
const request = event.Records[0].cf.request;
const response = event.Records[0].cf.response;
// 1. 自動 WebP 轉換
const uri = request.uri;
const acceptHeader = request.headers.accept ? request.headers.accept[0].value : '';
if (uri.match(/\.(jpg|jpeg|png)$/) && acceptHeader.includes('image/webp')) {
// 檢查是否有 WebP 版本
const webpUri = uri.replace(/\.(jpg|jpeg|png)$/, '.webp');
// 如果來源回應 404,嘗試獲取 WebP 版本
if (response.status === '404') {
const modifiedRequest = {
...request,
uri: webpUri
};
// 重新導向到 WebP 版本
response.status = '302';
response.headers.location = [{ key: 'Location', value: webpUri }];
}
}
// 2. 動態壓縮優化
const preferredEncoding = request.headers['x-preferred-encoding'] ?
request.headers['x-preferred-encoding'][0].value : '';
if (preferredEncoding && !response.headers['content-encoding']) {
// 為未壓縮的內容添加壓縮指示
response.headers['vary'] = [{ key: 'Vary', value: 'Accept-Encoding' }];
}
// 3. 快取優化
const contentType = response.headers['content-type'] ?
response.headers['content-type'][0].value : '';
if (contentType.startsWith('text/') ||
contentType.includes('application/json') ||
contentType.includes('application/javascript')) {
// 文字內容快取配置
response.headers['cache-control'] = [{
key: 'Cache-Control',
value: 'public, max-age=300, s-maxage=3600'
}];
} else if (contentType.startsWith('image/')) {
// 圖片內容長期快取
response.headers['cache-control'] = [{
key: 'Cache-Control',
value: 'public, max-age=31536000, immutable'
}];
}
// 4. 效能 Headers
response.headers['x-cache'] = [{
key: 'X-Cache',
value: `HIT-${context.logStreamName}`
}];
callback(null, response);
};
// 壓縮優化函數
exports.compressionOptimization = (event, context, callback) => {
const response = event.Records[0].cf.response;
const request = event.Records[0].cf.request;
// 檢查內容大小和類型
const contentLength = response.headers['content-length'] ?
parseInt(response.headers['content-length'][0].value) : 0;
const contentType = response.headers['content-type'] ?
response.headers['content-type'][0].value : '';
// 只對大於 1KB 的可壓縮內容進行處理
if (contentLength > 1024 && isCompressible(contentType)) {
const acceptEncoding = request.headers['accept-encoding'] ?
request.headers['accept-encoding'][0].value : '';
// 設定最適合的壓縮算法
if (acceptEncoding.includes('br') && contentType.includes('javascript')) {
response.headers['content-encoding'] = [{ key: 'Content-Encoding', value: 'br' }];
response.headers['vary'] = [{ key: 'Vary', value: 'Accept-Encoding' }];
} else if (acceptEncoding.includes('gzip')) {
response.headers['content-encoding'] = [{ key: 'Content-Encoding', value: 'gzip' }];
response.headers['vary'] = [{ key: 'Vary', value: 'Accept-Encoding' }];
}
}
callback(null, response);
};
function isCompressible(contentType) {
const compressibleTypes = [
'text/',
'application/javascript',
'application/json',
'application/xml',
'image/svg+xml'
];
return compressibleTypes.some(type => contentType.includes(type));
}
# infrastructure/auto-scaling-config.yml
Resources:
# ECS 服務自動擴展
ECSAutoScalingTarget:
Type: AWS::ApplicationAutoScaling::ScalableTarget
Properties:
ServiceNamespace: ecs
ResourceId: !Sub service/${ECSCluster}/${ECSService}
ScalableDimension: ecs:service:DesiredCount
MinCapacity: 2
MaxCapacity: 20
RoleARN: !GetAtt ECSAutoScalingRole.Arn
# CPU 使用率擴展策略
CPUScalingPolicy:
Type: AWS::ApplicationAutoScaling::ScalingPolicy
Properties:
PolicyName: CPUTargetTrackingScaling
PolicyType: TargetTrackingScaling
ScalingTargetId: !Ref ECSAutoScalingTarget
TargetTrackingScalingPolicyConfiguration:
TargetValue: 70.0
PredefinedMetricSpecification:
PredefinedMetricType: ECSServiceAverageCPUUtilization
ScaleOutCooldown: 300 # 5 分鐘
ScaleInCooldown: 300 # 5 分鐘
DisableScaleIn: false
# 記憶體使用率擴展策略
MemoryScalingPolicy:
Type: AWS::ApplicationAutoScaling::ScalingPolicy
Properties:
PolicyName: MemoryTargetTrackingScaling
PolicyType: TargetTrackingScaling
ScalingTargetId: !Ref ECSAutoScalingTarget
TargetTrackingScalingPolicyConfiguration:
TargetValue: 80.0
PredefinedMetricSpecification:
PredefinedMetricType: ECSServiceAverageMemoryUtilization
ScaleOutCooldown: 300
ScaleInCooldown: 600 # 更長的縮容冷卻時間
# 自訂指標擴展策略 - 請求數量
RequestCountScalingPolicy:
Type: AWS::ApplicationAutoScaling::ScalingPolicy
Properties:
PolicyName: RequestCountTargetTracking
PolicyType: TargetTrackingScaling
ScalingTargetId: !Ref ECSAutoScalingTarget
TargetTrackingScalingPolicyConfiguration:
TargetValue: 1000.0
CustomizedMetricSpecification:
MetricName: RequestCountPerTarget
Namespace: AWS/ApplicationELB
Dimensions:
- Name: TargetGroup
Value: !GetAtt ALBTargetGroup.TargetGroupFullName
Statistic: Sum
ScaleOutCooldown: 180 # 3 分鐘 - 快速擴展
ScaleInCooldown: 900 # 15 分鐘 - 保守縮容
# 預測性擴展策略
PredictiveScalingPolicy:
Type: AWS::ApplicationAutoScaling::ScalingPolicy
Properties:
PolicyName: PredictiveScaling
PolicyType: PredictiveScaling
ScalingTargetId: !Ref ECSAutoScalingTarget
PredictiveScalingPolicyConfiguration:
MetricSpecifications:
- TargetValue: 70.0
PredefinedMetricSpecification:
PredefinedMetricType: ECSServiceAverageCPUUtilization
Mode: ForecastAndScale # 預測並自動擴展
SchedulingBufferTime: 300 # 5 分鐘緩衝時間
MaxCapacityBreachBehavior: HonorMaxCapacity
MaxCapacityBuffer: 20 # 20% 容量緩衝
# 時間排程擴展
ScheduledScalingAction:
Type: AWS::ApplicationAutoScaling::ScheduledAction
Properties:
ServiceNamespace: ecs
ResourceId: !Sub service/${ECSCluster}/${ECSService}
ScalableDimension: ecs:service:DesiredCount
Schedule: cron(0 8 * * MON-FRI) # 週一到週五早上 8 點
ScalableTargetAction:
MinCapacity: 5
MaxCapacity: 25
Timezone: Asia/Taipei
# 週末縮容排程
WeekendScaleDownAction:
Type: AWS::ApplicationAutoScaling::ScheduledAction
Properties:
ServiceNamespace: ecs
ResourceId: !Sub service/${ECSCluster}/${ECSService}
ScalableDimension: ecs:service:DesiredCount
Schedule: cron(0 20 * * FRI) # 週五晚上 8 點
ScalableTargetAction:
MinCapacity: 1
MaxCapacity: 10
Timezone: Asia/Taipei
# ALB 目標群組自動擴展配置
Resources:
# ALB 目標群組
OptimizedTargetGroup:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
Properties:
Name: kyo-optimized-targets
Port: 3000
Protocol: HTTP
VpcId: !Ref VPC
TargetType: ip
# 健康檢查優化
HealthCheckEnabled: true
HealthCheckPath: /health
HealthCheckProtocol: HTTP
HealthCheckIntervalSeconds: 15 # 更頻繁的健康檢查
HealthCheckTimeoutSeconds: 5
HealthyThresholdCount: 2 # 更快標記為健康
UnhealthyThresholdCount: 3
Matcher:
HttpCode: 200
# 目標群組屬性優化
TargetGroupAttributes:
- Key: deregistration_delay.timeout_seconds
Value: 30 # 快速離線
- Key: slow_start.duration_seconds
Value: 60 # 新目標暖身時間
- Key: load_balancing.algorithm.type
Value: least_outstanding_requests # 最少未完成請求
- Key: stickiness.enabled
Value: false # 禁用黏性以改善負載分散
- Key: target_group_health.dns_failover.minimum_healthy_targets.count
Value: 1
- Key: target_group_health.unhealthy_state_routing.minimum_healthy_targets.count
Value: 1
# ALB 監聽器規則優化
OptimizedListenerRule:
Type: AWS::ElasticLoadBalancingV2::ListenerRule
Properties:
ListenerArn: !Ref ALBListener
Priority: 100
Conditions:
- Field: path-pattern
Values: ["/api/*"]
Actions:
- Type: forward
ForwardConfig:
TargetGroups:
- TargetGroupArn: !Ref OptimizedTargetGroup
Weight: 100
TargetGroupStickinessConfig:
Enabled: false
# CloudWatch 警報 - 高延遲
HighLatencyAlarm:
Type: AWS::CloudWatch::Alarm
Properties:
AlarmName: ALB-HighLatency
AlarmDescription: ALB target response time is too high
MetricName: TargetResponseTime
Namespace: AWS/ApplicationELB
Statistic: Average
Period: 300
EvaluationPeriods: 2
Threshold: 1.0 # 1 秒
ComparisonOperator: GreaterThanThreshold
Dimensions:
- Name: LoadBalancer
Value: !GetAtt ApplicationLoadBalancer.LoadBalancerFullName
- Name: TargetGroup
Value: !GetAtt OptimizedTargetGroup.TargetGroupFullName
AlarmActions:
- !Ref SNSAlarmTopic
# CloudWatch 警報 - 錯誤率
HighErrorRateAlarm:
Type: AWS::CloudWatch::Alarm
Properties:
AlarmName: ALB-HighErrorRate
AlarmDescription: ALB error rate is too high
MetricName: HTTPCode_Target_5XX_Count
Namespace: AWS/ApplicationELB
Statistic: Sum
Period: 300
EvaluationPeriods: 2
Threshold: 10
ComparisonOperator: GreaterThanThreshold
Dimensions:
- Name: LoadBalancer
Value: !GetAtt ApplicationLoadBalancer.LoadBalancerFullName
- Name: TargetGroup
Value: !GetAtt OptimizedTargetGroup.TargetGroupFullName
AlarmActions:
- !Ref SNSAlarmTopic
# infrastructure/rds-optimization.yml
Resources:
# 優化的 RDS 實例
OptimizedRDSInstance:
Type: AWS::RDS::DBInstance
Properties:
DBInstanceIdentifier: kyo-postgres-optimized
DBInstanceClass: db.r6g.xlarge # 記憶體最佳化實例
Engine: postgres
EngineVersion: 15.4
AllocatedStorage: 100
MaxAllocatedStorage: 1000 # 自動擴展儲存
StorageType: gp3 # 最新一代 SSD
StorageEncrypted: true
Iops: 3000 # 高 IOPS 配置
# 多可用區部署
MultiAZ: true
DBSubnetGroupName: !Ref DBSubnetGroup
VPCSecurityGroups:
- !Ref DatabaseSecurityGroup
# 備份配置
BackupRetentionPeriod: 7
PreferredBackupWindow: "03:00-04:00"
PreferredMaintenanceWindow: "sun:04:00-sun:05:00"
DeleteAutomatedBackups: false
# 效能洞察
EnablePerformanceInsights: true
PerformanceInsightsRetentionPeriod: 7
# 監控配置
MonitoringInterval: 60
MonitoringRoleArn: !GetAtt RDSMonitoringRole.Arn
EnableCloudwatchLogsExports:
- postgresql
# 參數群組
DBParameterGroupName: !Ref OptimizedDBParameterGroup
# 最佳化參數群組
OptimizedDBParameterGroup:
Type: AWS::RDS::DBParameterGroup
Properties:
Description: Optimized PostgreSQL parameters for SaaS workload
Family: postgres15
Parameters:
# 記憶體配置
shared_buffers: "{DBInstanceClassMemory/4}" # 25% 記憶體
effective_cache_size: "{DBInstanceClassMemory*3/4}" # 75% 記憶體
work_mem: "16MB" # 每個操作工作記憶體
maintenance_work_mem: "256MB" # 維護操作記憶體
# 連線配置
max_connections: "200" # 最大連線數
shared_preload_libraries: "pg_stat_statements" # 預載入擴展
# 檢查點配置
checkpoint_completion_target: "0.9" # 檢查點完成目標
checkpoint_timeout: "10min" # 檢查點間隔
max_wal_size: "2GB" # WAL 檔案大小
# 查詢優化
random_page_cost: "1.1" # SSD 隨機讀取成本
seq_page_cost: "1.0" # 順序讀取成本
effective_io_concurrency: "200" # I/O 併發數
# 統計資訊
default_statistics_target: "500" # 統計樣本數
# 日誌配置
log_min_duration_statement: "1000" # 記錄超過 1 秒的查詢
log_checkpoints: "on" # 記錄檢查點
log_lock_waits: "on" # 記錄鎖等待
log_temp_files: "0" # 記錄暫存檔案
# 自動清理配置
autovacuum: "on"
autovacuum_max_workers: "4"
autovacuum_naptime: "30s"
autovacuum_vacuum_threshold: "50"
autovacuum_analyze_threshold: "50"
# 讀取副本
ReadReplica:
Type: AWS::RDS::DBInstance
Properties:
DBInstanceIdentifier: kyo-postgres-read-replica
DBInstanceClass: db.r6g.large # 較小的讀取副本
SourceDBInstanceIdentifier: !Ref OptimizedRDSInstance
PubliclyAccessible: false
MultiAZ: false # 讀取副本不需要多 AZ
# 效能洞察
EnablePerformanceInsights: true
PerformanceInsightsRetentionPeriod: 7
# 監控
MonitoringInterval: 60
MonitoringRoleArn: !GetAtt RDSMonitoringRole.Arn
Tags:
- Key: Purpose
Value: ReadReplica
# RDS Proxy 配置
RDSProxy:
Type: AWS::RDS::DBProxy
Properties:
DBProxyName: kyo-postgres-proxy
EngineFamily: POSTGRESQL
Auth:
- AuthScheme: SECRETS
SecretArn: !Ref DatabaseCredentials
RoleArn: !GetAtt RDSProxyRole.Arn
VpcSubnetIds:
- !Ref PrivateSubnet1
- !Ref PrivateSubnet2
VpcSecurityGroupIds:
- !Ref ProxySecurityGroup
# 連線池配置
MaxConnectionsPercent: 100
MaxIdleConnectionsPercent: 50
RequireTLS: true
IdleClientTimeout: 1800 # 30 分鐘閒置超時
# 目標群組
TargetGroups:
- DBInstanceIdentifiers:
- !Ref OptimizedRDSInstance
DBClusterIdentifiers: []
ConnectionPoolConfig:
MaxConnectionsPercent: 80
MaxIdleConnectionsPercent: 20
ConnectionBorrowTimeout: 120
SessionPinningFilters:
- EXCLUDE_VARIABLE_SETS
Tags:
- Key: Name
Value: KyoPostgresProxy
# CloudWatch 警報配置
Resources:
# CPU 使用率警報
DatabaseCPUAlarm:
Type: AWS::CloudWatch::Alarm
Properties:
AlarmName: RDS-HighCPU
AlarmDescription: RDS CPU utilization is too high
MetricName: CPUUtilization
Namespace: AWS/RDS
Statistic: Average
Period: 300
EvaluationPeriods: 2
Threshold: 80
ComparisonOperator: GreaterThanThreshold
Dimensions:
- Name: DBInstanceIdentifier
Value: !Ref OptimizedRDSInstance
AlarmActions:
- !Ref SNSAlarmTopic
# 連線數警報
DatabaseConnectionsAlarm:
Type: AWS::CloudWatch::Alarm
Properties:
AlarmName: RDS-HighConnections
AlarmDescription: RDS connection count is too high
MetricName: DatabaseConnections
Namespace: AWS/RDS
Statistic: Average
Period: 300
EvaluationPeriods: 2
Threshold: 160 # 80% of max_connections
ComparisonOperator: GreaterThanThreshold
Dimensions:
- Name: DBInstanceIdentifier
Value: !Ref OptimizedRDSInstance
AlarmActions:
- !Ref SNSAlarmTopic
# 讀取延遲警報
DatabaseReadLatencyAlarm:
Type: AWS::CloudWatch::Alarm
Properties:
AlarmName: RDS-HighReadLatency
AlarmDescription: RDS read latency is too high
MetricName: ReadLatency
Namespace: AWS/RDS
Statistic: Average
Period: 300
EvaluationPeriods: 2
Threshold: 0.02 # 20ms
ComparisonOperator: GreaterThanThreshold
Dimensions:
- Name: DBInstanceIdentifier
Value: !Ref OptimizedRDSInstance
AlarmActions:
- !Ref SNSAlarmTopic
# 寫入延遲警報
DatabaseWriteLatencyAlarm:
Type: AWS::CloudWatch::Alarm
Properties:
AlarmName: RDS-HighWriteLatency
AlarmDescription: RDS write latency is too high
MetricName: WriteLatency
Namespace: AWS/RDS
Statistic: Average
Period: 300
EvaluationPeriods: 2
Threshold: 0.05 # 50ms
ComparisonOperator: GreaterThanThreshold
Dimensions:
- Name: DBInstanceIdentifier
Value: !Ref OptimizedRDSInstance
AlarmActions:
- !Ref SNSAlarmTopic
# 磁碟佇列深度警報
DatabaseQueueDepthAlarm:
Type: AWS::CloudWatch::Alarm
Properties:
AlarmName: RDS-HighQueueDepth
AlarmDescription: RDS disk queue depth is too high
MetricName: DiskQueueDepth
Namespace: AWS/RDS
Statistic: Average
Period: 300
EvaluationPeriods: 2
Threshold: 64
ComparisonOperator: GreaterThanThreshold
Dimensions:
- Name: DBInstanceIdentifier
Value: !Ref OptimizedRDSInstance
AlarmActions:
- !Ref SNSAlarmTopic
# infrastructure/elasticache-optimization.yml
Resources:
# 優化的 Redis 叢集
OptimizedRedisCluster:
Type: AWS::ElastiCache::ReplicationGroup
Properties:
ReplicationGroupId: kyo-redis-optimized
Description: Optimized Redis cluster for high performance caching
# 節點配置
NodeType: cache.r7g.large # 記憶體最佳化實例
NumCacheClusters: 6 # 3 主節點 + 3 副本節點
NumNodeGroups: 3 # 3 個分片
ReplicasPerNodeGroup: 1 # 每個分片 1 個副本
# 引擎配置
Engine: redis
EngineVersion: 7.0
Port: 6379
# 網路配置
CacheSubnetGroupName: !Ref CacheSubnetGroup
SecurityGroupIds:
- !Ref CacheSecurityGroup
PreferredCacheClusterAZs:
- !Sub "${AWS::Region}a"
- !Sub "${AWS::Region}b"
- !Sub "${AWS::Region}c"
# 參數群組
CacheParameterGroupName: !Ref OptimizedRedisParameterGroup
# 備份配置
SnapshotRetentionLimit: 7
SnapshotWindow: "03:00-05:00"
PreferredMaintenanceWindow: "sun:05:00-sun:07:00"
# 安全性
AtRestEncryptionEnabled: true
TransitEncryptionEnabled: true
AuthToken: !Sub "{{resolve:secretsmanager:${RedisAuthSecret}:SecretString:token}}"
# 自動故障切換
AutomaticFailoverEnabled: true
MultiAZEnabled: true
# 通知
NotificationTopicArn: !Ref SNSAlarmTopic
# 日誌配置
LogDeliveryConfigurations:
- DestinationType: cloudwatch-logs
DestinationDetails:
LogGroup: !Ref RedisLogGroup
LogFormat: json
LogType: slow-log
# Redis 參數群組優化
OptimizedRedisParameterGroup:
Type: AWS::ElastiCache::ParameterGroup
Properties:
CacheParameterGroupFamily: redis7.x
Description: Optimized Redis parameters for high performance
Properties:
# 記憶體配置
maxmemory-policy: allkeys-lru # LRU 淘汰策略
maxmemory-samples: 10 # 樣本數量
# 持久化配置
save: "900 1 300 10 60 10000" # RDB 快照策略
rdbcompression: "yes" # 啟用 RDB 壓縮
rdbchecksum: "yes" # 啟用 RDB 校驗
# 網路配置
tcp-keepalive: "300" # TCP keepalive
timeout: "0" # 客戶端超時時間
tcp-backlog: "511" # TCP 積壓佇列
# 效能優化
hash-max-ziplist-entries: "512" # 雜湊表壓縮閾值
hash-max-ziplist-value: "64" # 雜湊值壓縮閾值
list-max-ziplist-size: "-2" # 列表壓縮大小
set-max-intset-entries: "512" # 整數集合閾值
zset-max-ziplist-entries: "128" # 有序集合壓縮閾值
zset-max-ziplist-value: "64" # 有序集合值壓縮閾值
# 監控配置
slowlog-log-slower-than: "10000" # 慢查詢閾值 (微秒)
slowlog-max-len: "128" # 慢查詢日誌長度
# Redis 連線監控
RedisConnectionsAlarm:
Type: AWS::CloudWatch::Alarm
Properties:
AlarmName: Redis-HighConnections
AlarmDescription: Redis connection count is too high
MetricName: CurrConnections
Namespace: AWS/ElastiCache
Statistic: Average
Period: 300
EvaluationPeriods: 2
Threshold: 300
ComparisonOperator: GreaterThanThreshold
Dimensions:
- Name: CacheClusterId
Value: !Sub "${OptimizedRedisCluster}-001"
AlarmActions:
- !Ref SNSAlarmTopic
# Redis 記憶體使用率監控
RedisMemoryAlarm:
Type: AWS::CloudWatch::Alarm
Properties:
AlarmName: Redis-HighMemoryUsage
AlarmDescription: Redis memory usage is too high
MetricName: DatabaseMemoryUsagePercentage
Namespace: AWS/ElastiCache
Statistic: Average
Period: 300
EvaluationPeriods: 2
Threshold: 85
ComparisonOperator: GreaterThanThreshold
Dimensions:
- Name: CacheClusterId
Value: !Sub "${OptimizedRedisCluster}-001"
AlarmActions:
- !Ref SNSAlarmTopic
# Redis CPU 使用率監控
RedisCPUAlarm:
Type: AWS::CloudWatch::Alarm
Properties:
AlarmName: Redis-HighCPUUsage
AlarmDescription: Redis CPU usage is too high
MetricName: CPUUtilization
Namespace: AWS/ElastiCache
Statistic: Average
Period: 300
EvaluationPeriods: 2
Threshold: 80
ComparisonOperator: GreaterThanThreshold
Dimensions:
- Name: CacheClusterId
Value: !Sub "${OptimizedRedisCluster}-001"
AlarmActions:
- !Ref SNSAlarmTopic
# infrastructure/cost-optimization.yml
Resources:
# Savings Plans 建議
ComputeSavingsPlan:
Type: AWS::SavingsPlans::SavingsPlansTemplate
Properties:
SavingsPlansType: Compute
TermInYears: 1
PaymentOption: Partial Upfront
Commitment: 100 # 每小時承諾金額 (USD)
# 預留實例建議
RDSReservedInstance:
Type: AWS::RDS::DBInstance
Properties:
# 使用預留實例可節省 30-60% 成本
DBInstanceClass: db.r6g.xlarge
ReservedDBInstancesOfferingId: "reserved-offering-id"
# Spot 執行個體配置 (適用於非關鍵工作負載)
SpotFleetConfig:
Type: AWS::EC2::SpotFleet
Properties:
SpotFleetRequestConfig:
IamFleetRole: !GetAtt SpotFleetRole.Arn
AllocationStrategy: diversified
TargetCapacity: 2
SpotPrice: "0.05" # 最高出價
LaunchSpecifications:
- ImageId: ami-12345678
InstanceType: t3.medium
KeyName: !Ref KeyPair
SecurityGroups:
- GroupId: !Ref ApplicationSecurityGroup
SubnetId: !Ref PrivateSubnet1
UserData:
Fn::Base64: !Sub |
#!/bin/bash
# 安裝應用程式
# 自動化成本優化
CostOptimizationLambda:
Type: AWS::Lambda::Function
Properties:
FunctionName: cost-optimization-automation
Runtime: python3.9
Handler: index.lambda_handler
Role: !GetAtt CostOptimizationRole.Arn
Timeout: 300
Code:
ZipFile: |
import boto3
import json
from datetime import datetime, timedelta
def lambda_handler(event, context):
ec2 = boto3.client('ec2')
rds = boto3.client('rds')
# 1. 識別未使用的 EBS 卷
volumes = ec2.describe_volumes(
Filters=[{'Name': 'state', 'Values': ['available']}]
)
unused_volumes = []
for volume in volumes['Volumes']:
create_time = volume['CreateTime']
if (datetime.now(create_time.tzinfo) - create_time).days > 7:
unused_volumes.append(volume['VolumeId'])
# 2. 識別空閒的 RDS 實例
db_instances = rds.describe_db_instances()
idle_instances = []
for db in db_instances['DBInstances']:
# 檢查 CloudWatch 指標判斷是否空閒
# 這裡應該加入實際的 CloudWatch 指標檢查
pass
# 3. 建議調整實例大小
instances = ec2.describe_instances()
recommendations = []
for reservation in instances['Reservations']:
for instance in reservation['Instances']:
if instance['State']['Name'] == 'running':
# 分析 CloudWatch 指標建議新的實例類型
recommendations.append({
'InstanceId': instance['InstanceId'],
'CurrentType': instance['InstanceType'],
'RecommendedType': 'calculated-recommendation'
})
return {
'statusCode': 200,
'body': json.dumps({
'unused_volumes': unused_volumes,
'idle_db_instances': idle_instances,
'resize_recommendations': recommendations
})
}
# 成本優化排程
CostOptimizationSchedule:
Type: AWS::Events::Rule
Properties:
Description: Weekly cost optimization analysis
ScheduleExpression: cron(0 10 * * SUN) # 每週日上午 10 點
State: ENABLED
Targets:
- Arn: !GetAtt CostOptimizationLambda.Arn
Id: CostOptimizationTarget
# 成本警報
BillingAlarm:
Type: AWS::CloudWatch::Alarm
Properties:
AlarmName: HighBillingAlarm
AlarmDescription: Alert when estimated charges exceed threshold
MetricName: EstimatedCharges
Namespace: AWS/Billing
Statistic: Maximum
Period: 86400 # 24 小時
EvaluationPeriods: 1
Threshold: 1000 # USD 1000
ComparisonOperator: GreaterThanThreshold
Dimensions:
- Name: Currency
Value: USD
AlarmActions:
- !Ref CostAlarmTopic
今天我們完成了全面的 AWS 雲端效能優化實作: