亚麻云之静态资源管家——S3存储服务实战

发布于:2025-08-12 ⋅ 阅读:(16) ⋅ 点赞:(0)

本文作者: 封磊

Eclicktech SA | AWS Community Builder DevTool | AWS UGL | 亚马逊云科技云博主

阿里云&InfoQ&CSDN签约作者

在这里插入图片描述

前言

经过前三篇文章的学习,我们已经从Lightsail入门,掌握了EC2的灵活部署,并将数据库迁移到了RDS。现在我们的WordPress网站运行在EC2上,数据安全地存储在RDS中。但是,随着网站内容的增加,你可能会发现一个新的问题:服务器存储空间不够用了!

图片、视频、CSS、JavaScript文件越来越多,不仅占用服务器空间,还影响网站加载速度。今天,让我们为这些静态资源找一个更好的"家"——Amazon S3(Simple Storage Service)。

传统存储方式的局限

还记得我们在EC2上存储WordPress文件的方式吗?所有内容都堆在一个服务器上:

# 查看WordPress目录结构
ls -la /var/www/html/
drwxr-xr-x  5 apache apache  4096 Dec  1 10:00 wp-content
drwxr-xr-x  2 apache apache  4096 Dec  1 10:00 wp-includes
drwxr-xr-x  2 apache apache  4096 Dec  1 10:00 wp-admin

# wp-content目录越来越大
du -sh /var/www/html/wp-content/
2.5G    /var/www/html/wp-content/

存在的问题

1. 存储空间限制

  • EBS卷容量有限,扩展需要停机
  • 大量媒体文件占用宝贵的服务器空间
  • 备份整个服务器变得缓慢且昂贵

2. 性能影响

  • 静态文件请求占用服务器带宽
  • 影响动态内容的响应速度
  • 单点访问,无法分布式加速

3. 可靠性风险

  • 服务器故障可能导致所有文件丢失
  • 备份恢复复杂,容易出错
  • 无法实现异地容灾

4. 成本问题

  • 需要为不常访问的文件支付高性能存储费用
  • 带宽成本随文件访问量线性增长
  • 无法根据访问频率优化存储成本

什么是Amazon S3?

Amazon S3是AWS提供的对象存储服务,可以理解为云端的"超级硬盘",但它比传统硬盘强大得多。

S3的核心概念

对象存储 vs 文件系统

# 传统文件系统(层级结构)
/var/www/html/
├── wp-content/
│   ├── uploads/
│   │   ├── 2023/
│   │   │   ├── 12/
│   │   │   │   └── image.jpg
│   │   └── themes/
│   └── plugins/

# S3对象存储(扁平结构,用键值对)
Bucket: my-wordpress-assets
Key: wp-content/uploads/2023/12/image.jpg
Key: wp-content/themes/mytheme/style.css
Key: wp-content/plugins/myplugin/script.js

桶(Bucket)

  • 存储对象的容器,类似于顶级文件夹
  • 全球唯一命名
  • 可以设置访问权限和策略

对象(Object)

  • 存储的文件和元数据
  • 每个对象有唯一的键(Key)
  • 大小可达5TB

S3的强大优势

1. 无限扩展

  • 存储容量无限制
  • 自动扩展,无需人工干预
  • 按实际使用量付费

2. 高可用性

  • 99.999999999%(11个9)的数据持久性
  • 自动跨多个设施复制
  • 区域性故障自动恢复

3. 多种存储类别

  • 根据访问频率选择不同存储类别
  • 自动生命周期管理
  • 显著降低存储成本

4. 全球访问

  • 通过HTTP/HTTPS访问
  • 支持CDN加速
  • 全球边缘节点分发

S3存储类别选择指南

S3提供多种存储类别,就像酒店的不同房型,价格和服务不同:

Standard(标准存储)

# 特点:
# • 高频访问
# • 毫秒级访问延迟
# • 99.99%可用性
# • 适合:网站资源、移动应用、游戏应用

# 定价示例(美国东部):
# 存储:$0.023/GB/月
# 请求:$0.0004/1000次GET请求

Standard-IA(标准不频繁访问)

# 特点:
# • 低频访问但需要快速访问
# • 毫秒级访问延迟
# • 99.9%可用性
# • 适合:备份、灾难恢复、长期存储

# 定价示例:
# 存储:$0.0125/GB/月
# 请求:$0.001/1000次GET请求
# 检索:$0.01/GB

Glacier(冰川存储)

# 特点:
# • 归档存储
# • 检索时间:1分钟-12小时
# • 99.999999999%持久性
# • 适合:长期归档、合规备份

# 定价示例:
# 存储:$0.004/GB/月
# 检索:$0.03/GB(标准检索)

Intelligent-Tiering(智能分层)

# 特点:
# • 自动在存储类别间移动对象
# • 基于访问模式优化成本
# • 无检索费用
# • 适合:访问模式不确定的数据

# 定价示例:
# 监控费用:$0.0025/1000个对象/月
# 自动分层,无额外费用

实战案例:WordPress静态资源迁移到S3

让我们将WordPress的静态资源迁移到S3,实现存储和访问的优化。

步骤1:创建S3桶

使用控制台创建
  1. 桶名称:选择全球唯一的名称,如 my-wordpress-assets-20231201
  2. 区域:选择离用户最近的区域
  3. 公共访问设置:暂时阻止所有公共访问(稍后配置)
  4. 版本控制:启用(便于文件管理)
  5. 加密:启用服务器端加密
使用命令行创建
# 创建S3桶
aws s3 mb s3://my-wordpress-assets-20231201 --region us-east-1

# 启用版本控制
aws s3api put-bucket-versioning \
    --bucket my-wordpress-assets-20231201 \
    --versioning-configuration Status=Enabled

# 启用服务器端加密
aws s3api put-bucket-encryption \
    --bucket my-wordpress-assets-20231201 \
    --server-side-encryption-configuration '{
        "Rules": [
            {
                "ApplyServerSideEncryptionByDefault": {
                    "SSEAlgorithm": "AES256"
                }
            }
        ]
    }'

步骤2:配置桶权限

# 创建桶策略,允许公开读取
cat > bucket-policy.json << EOF
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PublicReadGetObject",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::my-wordpress-assets-20231201/*"
        }
    ]
}
EOF

# 应用桶策略
aws s3api put-bucket-policy \
    --bucket my-wordpress-assets-20231201 \
    --policy file://bucket-policy.json

# 禁用阻止公共访问(仅针对GetObject)
aws s3api put-public-access-block \
    --bucket my-wordpress-assets-20231201 \
    --public-access-block-configuration \
    "BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=false,RestrictPublicBuckets=false"

步骤3:上传现有静态资源

# 连接到EC2实例
ssh -i my-key.pem ec2-user@your-ec2-ip

# 同步wp-content/uploads到S3
aws s3 sync /var/www/html/wp-content/uploads/ \
    s3://my-wordpress-assets-20231201/wp-content/uploads/ \
    --delete

# 同步主题文件
aws s3 sync /var/www/html/wp-content/themes/ \
    s3://my-wordpress-assets-20231201/wp-content/themes/ \
    --exclude "*.php" \
    --include "*.css" \
    --include "*.js" \
    --include "*.png" \
    --include "*.jpg" \
    --include "*.gif"

# 查看上传结果
aws s3 ls s3://my-wordpress-assets-20231201/wp-content/uploads/ --recursive

步骤4:配置WordPress使用S3

方法1:使用插件(推荐初学者)
# 安装WP CLI(如果还没有)
curl -O https://raw.githubusercontent.com/wp-cli/wp-cli/v2.8.1/wp-cli.phar
chmod +x wp-cli.phar
sudo mv wp-cli.phar /usr/local/bin/wp

# 安装S3插件
cd /var/www/html
wp plugin install amazon-s3-and-cloudfront --activate --allow-root

在WordPress管理后台配置插件:

  1. 进入 “AWS” → “S3 and CloudFront”
  2. 输入S3桶名称:my-wordpress-assets-20231201
  3. 选择区域:us-east-1
  4. 启用 “Copy files to S3”
  5. 启用 “Serve files from S3”
方法2:修改WordPress配置(高级用户)
// 在wp-config.php中添加S3配置
define('S3_UPLOADS_BUCKET', 'my-wordpress-assets-20231201');
define('S3_UPLOADS_REGION', 'us-east-1');
define('S3_UPLOADS_BASE_URL', 'https://my-wordpress-assets-20231201.s3.amazonaws.com');

// 修改上传目录
add_filter('upload_dir', function($uploads) {
    $uploads['url'] = 'https://my-wordpress-assets-20231201.s3.amazonaws.com/wp-content/uploads';
    $uploads['baseurl'] = 'https://my-wordpress-assets-20231201.s3.amazonaws.com/wp-content/uploads';
    return $uploads;
});

步骤5:测试S3访问

# 测试直接访问S3文件
curl -I https://my-wordpress-assets-20231201.s3.amazonaws.com/wp-content/uploads/2023/12/test-image.jpg

# 检查WordPress网站图片显示
curl -s http://your-ec2-ip | grep -o 'https://my-wordpress-assets-20231201.s3.amazonaws.com[^"]*'

S3高级功能配置

生命周期管理

自动管理文件的存储类别,优化成本:

# 创建生命周期配置
cat > lifecycle-policy.json << EOF
{
    "Rules": [
        {
            "ID": "WordPressAssetsLifecycle",
            "Status": "Enabled",
            "Filter": {
                "Prefix": "wp-content/uploads/"
            },
            "Transitions": [
                {
                    "Days": 30,
                    "StorageClass": "STANDARD_IA"
                },
                {
                    "Days": 90,
                    "StorageClass": "GLACIER"
                },
                {
                    "Days": 365,
                    "StorageClass": "DEEP_ARCHIVE"
                }
            ]
        },
        {
            "ID": "DeleteIncompleteMultipartUploads",
            "Status": "Enabled",
            "Filter": {},
            "AbortIncompleteMultipartUpload": {
                "DaysAfterInitiation": 7
            }
        }
    ]
}
EOF

# 应用生命周期策略
aws s3api put-bucket-lifecycle-configuration \
    --bucket my-wordpress-assets-20231201 \
    --lifecycle-configuration file://lifecycle-policy.json

版本控制和删除保护

# 启用MFA删除保护(需要root用户)
aws s3api put-bucket-versioning \
    --bucket my-wordpress-assets-20231201 \
    --versioning-configuration Status=Enabled,MFADelete=Enabled \
    --mfa "arn:aws:iam::123456789012:mfa/root-account-mfa-device 123456"

# 查看对象版本
aws s3api list-object-versions \
    --bucket my-wordpress-assets-20231201 \
    --prefix wp-content/uploads/2023/12/

# 恢复删除的对象
aws s3api delete-object \
    --bucket my-wordpress-assets-20231201 \
    --key wp-content/uploads/2023/12/deleted-image.jpg \
    --version-id null

跨区域复制

为重要资源设置跨区域备份:

# 创建目标桶(不同区域)
aws s3 mb s3://my-wordpress-backup-20231201 --region us-west-2

# 创建复制角色
cat > replication-role-trust-policy.json << EOF
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "s3.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}
EOF

aws iam create-role \
    --role-name S3ReplicationRole \
    --assume-role-policy-document file://replication-role-trust-policy.json

# 附加复制权限
aws iam attach-role-policy \
    --role-name S3ReplicationRole \
    --policy-arn arn:aws:iam::aws:policy/service-role/AWSS3ReplicationServiceRolePolicy

# 配置复制规则
cat > replication-config.json << EOF
{
    "Role": "arn:aws:iam::123456789012:role/S3ReplicationRole",
    "Rules": [
        {
            "ID": "ReplicateUploads",
            "Status": "Enabled",
            "Priority": 1,
            "Filter": {
                "Prefix": "wp-content/uploads/"
            },
            "Destination": {
                "Bucket": "arn:aws:s3:::my-wordpress-backup-20231201",
                "StorageClass": "STANDARD_IA"
            }
        }
    ]
}
EOF

aws s3api put-bucket-replication \
    --bucket my-wordpress-assets-20231201 \
    --replication-configuration file://replication-config.json

静态网站托管

S3不仅可以存储文件,还可以直接托管静态网站:

配置静态网站托管

# 启用静态网站托管
aws s3api put-bucket-website \
    --bucket my-wordpress-assets-20231201 \
    --website-configuration '{
        "IndexDocument": {
            "Suffix": "index.html"
        },
        "ErrorDocument": {
            "Key": "error.html"
        }
    }'

# 创建简单的index.html
cat > index.html << EOF
<!DOCTYPE html>
<html>
<head>
    <title>My WordPress Assets</title>

    <style>
        body { font-family: Arial, sans-serif; margin: 40px; }
        .container { max-width: 800px; margin: 0 auto; }
        .asset-list { list-style: none; padding: 0; }
        .asset-list li { padding: 10px; border-bottom: 1px solid #eee; }
    </style>

</head>

<body>
    <div class="container">
        <h1>WordPress Static Assets</h1>

        <p>This bucket contains static assets for our WordPress site.</p>

        <ul class="asset-list">
            <li><a href="wp-content/uploads/">Uploads Directory</a></li>

            <li><a href="wp-content/themes/">Themes Directory</a></li>

        </ul>

    </div>

</body>

</html>

EOF

# 上传index.html
aws s3 cp index.html s3://my-wordpress-assets-20231201/ \
    --content-type "text/html"

# 访问静态网站
echo "Website URL: http://my-wordpress-assets-20231201.s3-website-us-east-1.amazonaws.com"

自定义域名绑定

# 创建CNAME记录(在你的DNS提供商)
# assets.yourdomain.com -> my-wordpress-assets-20231201.s3-website-us-east-1.amazonaws.com

# 或使用Route 53
aws route53 change-resource-record-sets \
    --hosted-zone-id Z123456789 \
    --change-batch '{
        "Changes": [
            {
                "Action": "CREATE",
                "ResourceRecordSet": {
                    "Name": "assets.yourdomain.com",
                    "Type": "CNAME",
                    "TTL": 300,
                    "ResourceRecords": [
                        {
                            "Value": "my-wordpress-assets-20231201.s3-website-us-east-1.amazonaws.com"
                        }
                    ]
                }
            }
        ]
    }'

文件上传和管理

批量上传工具

# 使用AWS CLI同步
aws s3 sync /local/path/ s3://my-wordpress-assets-20231201/path/ \
    --exclude "*.tmp" \
    --include "*.jpg" \
    --include "*.png" \
    --include "*.css" \
    --include "*.js" \
    --delete \
    --dryrun  # 先预览,确认无误后去掉此参数

# 设置文件元数据
aws s3 cp image.jpg s3://my-wordpress-assets-20231201/wp-content/uploads/2023/12/ \
    --metadata "title=My Image,description=A beautiful image" \
    --content-type "image/jpeg" \
    --cache-control "max-age=31536000"

# 批量设置缓存策略
aws s3 cp s3://my-wordpress-assets-20231201/wp-content/uploads/ \
    s3://my-wordpress-assets-20231201/wp-content/uploads/ \
    --recursive \
    --metadata-directive REPLACE \
    --cache-control "max-age=31536000" \
    --content-type "image/jpeg" \
    --exclude "*" \
    --include "*.jpg"

预签名URL

为私有文件生成临时访问链接:

# 生成1小时有效的下载链接
aws s3 presign s3://my-wordpress-assets-20231201/private/document.pdf \
    --expires-in 3600

# 生成上传链接
aws s3 presign s3://my-wordpress-assets-20231201/uploads/new-file.jpg \
    --expires-in 3600 \
    --http-method PUT

多部分上传

对于大文件,使用多部分上传提高效率:

# 启动多部分上传
UPLOAD_ID=$(aws s3api create-multipart-upload \
    --bucket my-wordpress-assets-20231201 \
    --key large-video.mp4 \
    --query 'UploadId' \
    --output text)

# 分块上传(示例:分成3个部分)
aws s3api upload-part \
    --bucket my-wordpress-assets-20231201 \
    --key large-video.mp4 \
    --part-number 1 \
    --upload-id $UPLOAD_ID \
    --body part1.mp4

aws s3api upload-part \
    --bucket my-wordpress-assets-20231201 \
    --key large-video.mp4 \
    --part-number 2 \
    --upload-id $UPLOAD_ID \
    --body part2.mp4

aws s3api upload-part \
    --bucket my-wordpress-assets-20231201 \
    --key large-video.mp4 \
    --part-number 3 \
    --upload-id $UPLOAD_ID \
    --body part3.mp4

# 完成上传
aws s3api complete-multipart-upload \
    --bucket my-wordpress-assets-20231201 \
    --key large-video.mp4 \
    --upload-id $UPLOAD_ID \
    --multipart-upload file://parts.json

性能优化

请求优化

# 使用Transfer Acceleration
aws s3api put-bucket-accelerate-configuration \
    --bucket my-wordpress-assets-20231201 \
    --accelerate-configuration Status=Enabled

# 使用加速端点上传
aws s3 cp large-file.zip \
    s3://my-wordpress-assets-20231201/ \
    --endpoint-url https://s3-accelerate.amazonaws.com

缓存策略

# 为不同文件类型设置不同的缓存策略
# 图片文件 - 长期缓存
aws s3 cp s3://my-wordpress-assets-20231201/wp-content/uploads/ \
    s3://my-wordpress-assets-20231201/wp-content/uploads/ \
    --recursive \
    --metadata-directive REPLACE \
    --cache-control "max-age=31536000, public" \
    --exclude "*" \
    --include "*.jpg" \
    --include "*.png" \
    --include "*.gif"

# CSS/JS文件 - 中期缓存
aws s3 cp s3://my-wordpress-assets-20231201/wp-content/themes/ \
    s3://my-wordpress-assets-20231201/wp-content/themes/ \
    --recursive \
    --metadata-directive REPLACE \
    --cache-control "max-age=86400, public" \
    --exclude "*" \
    --include "*.css" \
## 监控和故障排除

### CloudWatch监控

```bash
# 查看存储使用量
aws cloudwatch get-metric-statistics \
    --namespace AWS/S3 \
    --metric-name BucketSizeBytes \
    --dimensions Name=BucketName,Value=my-wordpress-assets-20231201 Name=StorageType,Value=StandardStorage \
    --start-time 2023-12-01T00:00:00Z \
    --end-time 2023-12-01T23:59:59Z \
    --period 86400 \
    --statistics Maximum

# 查看请求数量
aws cloudwatch get-metric-statistics \
    --namespace AWS/S3 \
    --metric-name AllRequests \
    --dimensions Name=BucketName,Value=my-wordpress-assets-20231201 \
    --start-time 2023-12-01T00:00:00Z \
    --end-time 2023-12-01T23:59:59Z \
    --period 3600 \
    --statistics Sum

# 设置告警
aws cloudwatch put-metric-alarm \
    --alarm-name "S3-High-Request-Count" \
    --alarm-description "Alert when S3 requests are high" \
    --metric-name AllRequests \
    --namespace AWS/S3 \
    --statistic Sum \
    --period 3600 \
    --threshold 10000 \
    --comparison-operator GreaterThanThreshold \
    --evaluation-periods 2 \
    --dimensions Name=BucketName,Value=my-wordpress-assets-20231201

常见问题解决

问题1:403 Forbidden错误

# 检查桶策略
aws s3api get-bucket-policy --bucket my-wordpress-assets-20231201

# 检查公共访问阻止设置
aws s3api get-public-access-block --bucket my-wordpress-assets-20231201

# 检查对象ACL
aws s3api get-object-acl \
    --bucket my-wordpress-assets-20231201 \
    --key wp-content/uploads/2023/12/image.jpg

问题2:上传失败

# 检查IAM权限
aws iam get-user-policy --user-name your-username --policy-name S3Access

# 检查文件大小限制
ls -lh large-file.zip

# 使用多部分上传
aws configure set default.s3.multipart_threshold 64MB
aws configure set default.s3.multipart_chunksize 16MB

问题3:访问速度慢

# 检查区域选择
aws s3api get-bucket-location --bucket my-wordpress-assets-20231201

# 启用Transfer Acceleration
aws s3api put-bucket-accelerate-configuration \
    --bucket my-wordpress-assets-20231201 \
    --accelerate-configuration Status=Enabled

# 测试加速效果
aws s3 cp test-file.jpg s3://my-wordpress-assets-20231201/ \
    --endpoint-url https://s3-accelerate.amazonaws.com

自动化管理

Lambda函数自动处理

创建Lambda函数自动优化上传的图片:

import json
import boto3
from PIL import Image
import io

def lambda_handler(event, context):
    s3 = boto3.client('s3')
    
    # 获取触发事件的桶和对象信息
    bucket = event['Records'][0]['s3']['bucket']['name']
    key = event['Records'][0]['s3']['object']['key']
    
    # 只处理图片文件
    if not key.lower().endswith(('.jpg', '.jpeg', '.png')):
        return {'statusCode': 200, 'body': 'Not an image file'}
    
    try:
        # 下载原始图片
        response = s3.get_object(Bucket=bucket, Key=key)
        image_data = response['Body'].read()
        
        # 使用PIL处理图片
        image = Image.open(io.BytesIO(image_data))
        
        # 创建缩略图
        thumbnail = image.copy()
        thumbnail.thumbnail((300, 300), Image.Resampling.LANCZOS)
        
        # 保存缩略图
        thumb_buffer = io.BytesIO()
        thumbnail.save(thumb_buffer, format=image.format, optimize=True, quality=85)
        thumb_buffer.seek(0)
        
        # 上传缩略图到S3
        thumb_key = key.replace('/uploads/', '/uploads/thumbs/')
        s3.put_object(
            Bucket=bucket,
            Key=thumb_key,
            Body=thumb_buffer.getvalue(),
            ContentType=response['ContentType'],
            CacheControl='max-age=31536000'
        )
        
        return {
            'statusCode': 200,
            'body': json.dumps(f'Thumbnail created: {thumb_key}')
        }
        
    except Exception as e:
        print(f'Error processing {key}: {str(e)}')
        return {
            'statusCode': 500,
            'body': json.dumps(f'Error: {str(e)}')
        }

事件通知配置

# 配置S3事件通知
cat > notification-config.json << EOF
{
    "LambdaConfigurations": [
        {
            "Id": "ImageProcessing",
            "LambdaFunctionArn": "arn:aws:lambda:us-east-1:123456789012:function:ProcessS3Images",
            "Events": ["s3:ObjectCreated:*"],
            "Filter": {
                "Key": {
                    "FilterRules": [
                        {
                            "Name": "prefix",
                            "Value": "wp-content/uploads/"
                        },
                        {
                            "Name": "suffix",
                            "Value": ".jpg"
                        }
                    ]
                }
            }
        }
    ]
}
EOF

aws s3api put-bucket-notification-configuration \
    --bucket my-wordpress-assets-20231201 \
    --notification-configuration file://notification-config.json

备份和灾难恢复

跨账户备份

# 创建跨账户复制策略
cat > cross-account-policy.json << EOF
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowCrossAccountReplication",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::BACKUP-ACCOUNT-ID:root"
            },
            "Action": [
                "s3:GetBucketVersioning",
                "s3:PutBucketVersioning",
                "s3:ReplicateObject",
                "s3:ReplicateDelete"
            ],
            "Resource": [
                "arn:aws:s3:::my-wordpress-backup-account",
                "arn:aws:s3:::my-wordpress-backup-account/*"
            ]
        }
    ]
}
EOF

数据恢复流程

# 恢复删除的对象
aws s3api list-object-versions \
    --bucket my-wordpress-assets-20231201 \
    --prefix wp-content/uploads/2023/12/deleted-image.jpg

# 恢复特定版本
aws s3api copy-object \
    --copy-source "my-wordpress-assets-20231201/wp-content/uploads/2023/12/deleted-image.jpg?versionId=VERSION_ID" \
    --bucket my-wordpress-assets-20231201 \
    --key wp-content/uploads/2023/12/deleted-image.jpg

# 批量恢复
aws s3 sync s3://my-wordpress-backup-20231201/ s3://my-wordpress-assets-20231201/ \
    --delete \
    --dryrun  # 先预览

迁移验证清单

功能验证

  • WordPress网站图片正常显示
  • 媒体库文件可以正常上传
  • 主题CSS和JS文件正常加载
  • 文件下载功能正常
  • 搜索引擎可以正常索引图片

性能验证

# 测试文件访问速度
time curl -o /dev/null -s https://my-wordpress-assets-20231201.s3.amazonaws.com/wp-content/uploads/2023/12/large-image.jpg

# 测试网站加载速度
curl -w "@curl-format.txt" -o /dev/null -s http://your-ec2-ip

# 检查缓存头
curl -I https://my-wordpress-assets-20231201.s3.amazonaws.com/wp-content/uploads/2023/12/image.jpg

成本验证

# 查看S3使用量
aws s3 ls s3://my-wordpress-assets-20231201 --recursive --summarize

# 检查存储类别分布
aws s3api list-objects-v2 \
    --bucket my-wordpress-assets-20231201 \
    --query 'Contents[].{Key:Key,StorageClass:StorageClass,Size:Size}'

WordPress插件推荐

WP Offload Media

  • 自动上传媒体文件到S3
  • 支持CDN集成
  • 提供图片优化功能

S3 Uploads

  • 轻量级S3集成
  • 开源免费
  • 适合开发者使用

WP-Stateless

  • Google Cloud Storage和S3双支持
  • 图片处理功能
  • 性能优化

最佳实践总结

命名规范

# 桶命名
company-project-environment-date
# 例如:mycompany-wordpress-prod-20231201

# 对象键命名
service/type/date/filename
# 例如:wp-content/uploads/2023/12/image-001.jpg

权限管理

  • 使用最小权限原则
  • 定期审查桶策略
  • 启用访问日志记录
  • 使用IAM角色而非用户密钥

成本控制

  • 合理选择存储类别
  • 设置生命周期策略
  • 监控请求数量
  • 使用CloudFront减少直接请求

安全配置

  • 启用版本控制
  • 配置跨区域复制
  • 使用服务器端加密
  • 限制公共访问权限

下一步学习方向

掌握了S3基础后,你可以继续探索:

  1. CloudFront CDN:为S3内容提供全球加速(下一篇文章重点)
  2. Lambda@Edge:在边缘节点处理请求
  3. S3 Select:直接查询S3中的数据
  4. AWS DataSync:大规模数据迁移
  5. S3 Batch Operations:批量处理S3对象

结语

通过将静态资源迁移到S3,我们不仅解决了存储空间的问题,还获得了更好的性能、可靠性和成本效益。S3就像一个无限容量的"云端仓库",不仅安全可靠,还能根据我们的需求提供不同级别的服务。

从本地存储到云端存储,这不仅是技术架构的升级,更是存储思维的转变。我们学会了:

  • 根据访问频率选择合适的存储类别
  • 使用生命周期策略自动优化成本
  • 通过版本控制和跨区域复制保障数据安全
  • 利用事件通知实现自动化处理

现在我们的架构已经包含了:

  • 计算层:EC2(动态内容)
  • 数据层:RDS(数据库)
  • 存储层:S3(静态资源)

在下一篇文章中,我们将学习CloudFront CDN服务,为我们的S3内容和EC2应用提供全球加速,让世界各地的用户都能快速访问我们的网站。


静态资源有了新家,网站性能更上一层楼!S3让存储变得如此简单而强大!

压缩优化

# 启用Gzip压缩
aws s3 cp style.css s3://my-wordpress-assets-20231201/wp-content/themes/mytheme/ \
    --content-encoding gzip \
    --content-type "text/css"

# 批量压缩CSS和JS文件
find /var/www/html/wp-content/themes -name "*.css" -o -name "*.js" | while read file; do
    gzip -c "$file" > "${file}.gz"
    aws s3 cp "${file}.gz" "s3://my-wordpress-assets-20231201${file#/var/www/html}" \
        --content-encoding gzip \
        --content-type "$(file -b --mime-type "$file")"
    rm "${file}.gz"
done

安全配置

访问控制

# 创建更精细的桶策略
cat > secure-bucket-policy.json << EOF
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PublicReadGetObject",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::my-wordpress-assets-20231201/wp-content/uploads/*",
            "Condition": {
                "StringLike": {
                    "aws:Referer": [
                        "http://yourdomain.com/*",
                        "https://yourdomain.com/*"
                    ]
                }
            }
        },
        {
            "Sid": "DenyDirectAccess",
            "Effect": "Deny",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::my-wordpress-assets-20231201/private/*"
        }
    ]
}
EOF

aws s3api put-bucket-policy \
    --bucket my-wordpress-assets-20231201 \
    --policy file://secure-bucket-policy.json

访问日志

# 创建日志桶
aws s3 mb s3://my-wordpress-access-logs-20231201

# 启用访问日志
aws s3api put-bucket-logging \
    --bucket my-wordpress-assets-20231201 \
    --bucket-logging-status '{
        "LoggingEnabled": {
            "TargetBucket": "my-wordpress-access-logs-20231201",
            "TargetPrefix": "access-logs/"
        }
    }'

数据加密

# 启用默认加密
aws s3api put-bucket-encryption \
    --bucket my-wordpress-assets-20231201 \
    --server-side-encryption-configuration '{
        "Rules": [
            {
                "ApplyServerSideEncryptionByDefault": {
                    "SSEAlgorithm": "aws:kms",
                    "KMSMasterKeyID": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012"
                },
                "BucketKeyEnabled": true
            }
        ]
    }'

# 上传加密文件
aws s3 cp sensitive-document.pdf \
    s3://my-wordpress-assets-20231201/private/ \
    --server-side-encryption aws:kms \
    --ssekms-key-id arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012

成本优化策略

存储类别优化

# 分析存储使用情况
aws s3api get-bucket-analytics-configuration \
    --bucket my-wordpress-assets-20231201 \
    --id EntireBucket

# 启用智能分层
aws s3 cp s3://my-wordpress-assets-20231201/ \
    s3://my-wordpress-assets-20231201/ \
    --recursive \
    --storage-class INTELLIGENT_TIERING

成本监控

# 设置S3成本预算
aws budgets create-budget \
    --account-id 123456789012 \
    --budget '{
        "BudgetName": "S3-Monthly-Budget",
        "BudgetLimit": {
            "Amount": "20",
            "Unit": "USD"
        },
        "TimeUnit": "MONTHLY",
        "BudgetType": "COST",
        "CostFilters": {
            "Service": ["Amazon Simple Storage Service"]
        }
    }'

# 查看存储使用量
aws cloudwatch get-metric-statistics \
    --namespace AWS/S3 \
    --metric-name BucketSizeBytes \
    --dimensions Name=BucketName,Value=my-wordpress-assets-20231201 Name=StorageType,Value=StandardStorage \
    --start-time 2023-11-01T00:00:00Z \
    --end-time 2023-12-01T00:00:00Z \
    --period 86400 \
    --statistics Average

请求成本优化

# 使用CloudFront减少S3请求
# (这将在下一篇文章详细介绍)

# 批量删除过期文件
aws s3api list-objects-v2 \
    --bucket my-wordpress-assets-20231201 \
    --query 'Contents[?LastModified<`2023-01-01`].Key' \
    --output text | \
    xargs -I {} aws s3 rm s3://my-wordpress-assets-20231201/{}