AWS企業帳號代理 AWS 無伺服器資料處理架構:結合 S3、Lambda 與 DynamoDB
# AWS 無伺服器資料處理架構:結合 S3、Lambda 與 DynamoDB
## 寫作前分析:你真正想解決的問題是什麼?
當你搜尋這個主題時,通常不是想看架構概念,而是要完成一條**能真正跑起來的資料處理流程**。最常見的目標包括:
AWS企業帳號代理 1. 使用者把檔案上傳到 S3 後,自動觸發 Lambda。
2. Lambda 解析檔案內容,做格式轉換、欄位清洗或基本校驗。
3. 處理後的結果寫入 DynamoDB,供網站、API 或後續分析系統查詢。
4. 當流程失敗時,能快速定位是權限、事件、程式碼還是資料格式問題。
換句話說,這篇文章要幫你解決的不是「什麼是 AWS 無伺服器」,而是:
- S3 該怎麼建?
- Lambda 要怎麼接收 S3 事件?
- DynamoDB 表怎麼設計才不會後面查詢很痛苦?
- IAM 權限怎麼配才不會出現 AccessDenied?
- 為什麼檔案上傳了,Lambda 卻沒有觸發?
- 為什麼 Lambda 執行成功,但 DynamoDB 沒資料?
下面直接進入實作。
---
## 一、實作目標與架構流程
這裡用一個典型場景來做教程:
**場景:**
你有一個上傳到 S3 的 JSON 檔案,每筆資料代表一條訂單或事件記錄。當檔案進入指定 Bucket 後,Lambda 自動觸發,讀取 JSON,逐筆寫入 DynamoDB。
**流程如下:**
1. 建立 S3 Bucket 作為資料入口。
2. 建立 DynamoDB 資料表保存處理結果。
3. 建立 Lambda 函數負責讀檔、解析、寫入資料。
4. 配置 IAM Role,讓 Lambda 有權限讀取 S3、寫入 DynamoDB、輸出日誌到 CloudWatch。
5. 在 S3 配置事件通知,當檔案上傳時觸發 Lambda。
6. 上傳測試檔案並排查可能報錯。
---
## 二、部署前的配置規劃
先把幾個容易選錯的參數定下來。
### 1. Region 選擇
建議把 S3、Lambda、DynamoDB 放在**同一個 Region**,例如:
- ap-northeast-1(東京)
- ap-southeast-1(新加坡)
- us-east-1(維吉尼亞北部)
**實務建議:**
- 如果你的使用者主要在亞洲,優先選東京或新加坡。
- Lambda 與 S3 事件通知需要在同區域內整合,跨區域會增加管理複雜度。
- DynamoDB 雖然本身是區域級服務,但若你把應用資源拆到不同區域,後續排查延遲和權限問題會更麻煩。
### 2. 命名規劃
建議提前統一命名,避免控制台裡資源過多後找不到。
示例:
- S3 Bucket:`demo-data-ingest-2026`
- Lambda:`s3-json-to-dynamodb`
- DynamoDB Table:`orders_raw`
- IAM Role:`lambda-s3-ddb-role`
### 3. 測試資料格式
先準備一份 JSON 檔,內容如下:
```json
[
{
"order_id": "A1001",
"user_id": "U9001",
"amount": 399,
"status": "paid",
"created_at": "2026-10-21T10:00:00Z"
},
{
"order_id": "A1002",
"user_id": "U9002",
"amount": 599,
"status": "pending",
"created_at": "2026-10-21T10:05:00Z"
}
]
```
檔案命名為:`orders/orders-001.json`
這樣後面可以順便示範 S3 Prefix 過濾。
---
## 三、建立 S3 Bucket
### 步驟 1:進入 S3 控制台
登入 AWS Console 後:
AWS企業帳號代理 - 搜尋 `S3`
- 點擊 **Create bucket**
### 步驟 2:填寫 Bucket 參數
關鍵參數建議如下:
- **Bucket name**:輸入全域唯一名稱,例如 `demo-data-ingest-2026`
- **AWS Region**:選定你的目標區域,例如 `ap-northeast-1`
- **Block Public Access**:保持預設開啟
- **Bucket Versioning**:建議開啟,方便誤覆蓋或回滾
- **Default encryption**:建議開啟 SSE-S3
### 為什麼這樣設?
- 這個 Bucket 是資料入口,不需要公開讀寫。
- 開啟版本控制後,若 Lambda 處理前檔案被覆蓋,仍可追溯。
- 加密是基本要求,避免後續合規或內部審計出問題。
### 常見問題
#### 1. Bucket name already exists
S3 Bucket 名稱是全域唯一,不是你的帳號內唯一。改一個新名稱,例如加入公司縮寫、日期或隨機碼。
#### 2. 上傳成功但 Lambda 沒觸發
這通常不是 Bucket 問題,而是後面的事件通知或 Lambda 權限沒設好。
AWS企業帳號代理 ---
## 四、建立 DynamoDB 資料表
### 步驟 1:進入 DynamoDB 控制台
- 搜尋 `DynamoDB`
- 點擊 **Create table**
### 步驟 2:設計資料表主鍵
如果資料以 `order_id` 唯一識別,建議如下:
- **Table name**:`orders_raw`
- **Partition key**:`order_id`,型別選 `String`
如果後續你會按使用者查詢訂單,可以額外規劃 GSI,但教程先以基本入庫為主。
### 步驟 3:容量模式
建議開發或初期測試選:
- **On-demand**
原因:
- 不用先估讀寫容量
- 適合事件驅動、流量不穩定場景
- 配置簡單,降低一開始踩坑機率
### 實務上的表設計提醒
很多人一開始只想著「能不能寫入」,忽略「之後怎麼查」。如果你的查詢方式包括:
- 按 `user_id` 查詢最近訂單
- 按 `status` 篩選待處理資料
- 按時間區間查詢
那麼你應該在建表前就考慮:
- 是否增加 GSI
- 是否用複合主鍵
- 是否需要把 `created_at` 當 sort key
本篇為了聚焦 S3 → Lambda → DynamoDB 主流程,先用單主鍵示範。若你的資料查詢維度很多,不要等上線後再補索引,代價較高。
---
## 五、建立 Lambda 執行角色(IAM Role)
AWS企業帳號代理 這一步是最容易出錯的地方之一。
Lambda 要完成這條鏈路,至少需要三類權限:
1. 讀取 S3 物件
2. 寫入 DynamoDB
3. 輸出日誌到 CloudWatch Logs
### 步驟 1:進入 IAM
- 搜尋 `IAM`
- 點擊 **Roles**
- 選擇 **Create role**
### 步驟 2:選擇信任實體
AWS企業帳號代理 - 選擇 **AWS service**
- Use case 選 **Lambda**
### 步驟 3:附加權限政策
至少附加以下政策:
- `AWSLambdaBasicExecutionRole`
這個只提供 CloudWatch Logs 權限,不包含 S3 和 DynamoDB 操作。
建議再建立一個自訂 Policy,例如:
```json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetObject"
],
"Resource": "arn:aws:s3:::demo-data-ingest-2026/*"
},
{
"Effect": "Allow",
"Action": [
"dynamodb:PutItem",
"dynamodb:BatchWriteItem"
],
"Resource": "arn:aws:dynamodb:ap-northeast-1:123456789012:table/orders_raw"
}
]
}
```
請把下面內容替換成你的實際值:
- Bucket 名稱
- Region
- AWS Account ID
- DynamoDB 表名
### 常見錯誤
#### 1. AccessDenied for S3 GetObject
表示 Lambda 角色沒有讀取 Bucket 內物件的權限,或 Resource ARN 寫錯。
#### 2. DynamoDB PutItem AccessDenied
通常是表 ARN 寫錯、Region 寫錯,或 Lambda 使用了其他 Role。
#### 3. CloudWatch 沒日誌
大多數情況是沒掛 `AWSLambdaBasicExecutionRole`,導致函數有執行但你看不到記錄。
---
## 六、建立 Lambda 函數
### 步驟 1:進入 Lambda 控制台
- 搜尋 `Lambda`
- 點擊 **Create function**
- 選擇 **Author from scratch**
### 步驟 2:填寫基本資訊
- **Function name**:`s3-json-to-dynamodb`
- **Runtime**:建議 `Python 3.12` 或你團隊慣用版本
- **Execution role**:選擇剛才建立的 `lambda-s3-ddb-role`
### 步驟 3:設定環境變數
進入 Lambda 後,在 **Configuration** → **Environment variables** 增加:
- `TABLE_NAME=orders_raw`
如果你還需要區分不同前綴、業務線,也可以增加:
- `S3_PREFIX=orders/`
### 步驟 4:部署程式碼
以下是可直接測試的 Python 範例:
```python
import json
import os
import urllib.parse
import boto3
s3 = boto3.client('s3')
dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table(os.environ['TABLE_NAME'])
def lambda_handler(event, context):
print("Received event:", json.dumps(event))
for record in event.get('Records', []):
bucket = record['s3']['bucket']['name']
key = urllib.parse.unquote_plus(record['s3']['object']['key'])
print(f"Processing file s3://{bucket}/{key}")
AWS企業帳號代理 response = s3.get_object(Bucket=bucket, Key=key)
content = response['Body'].read().decode('utf-8')
data = json.loads(content)
if not isinstance(data, list):
raise ValueError('JSON file must contain a list of objects')
with table.batch_writer() as batch:
for item in data:
if 'order_id' not in item:
print(f"Skip invalid item: {item}")
continue
batch.put_item(Item=item)
return {
'statusCode': 200,
'body': json.dumps('Processing completed')
}
```
### 這段程式做了什麼?
- 從 S3 事件中取出 Bucket 與 Key
- 下載上傳的 JSON 檔案
- 解析成 Python list
- 檢查每一筆資料是否有 `order_id`
- 使用 `batch_writer()` 批量寫入 DynamoDB
### 為什麼用 batch_writer?
相較逐筆 `put_item()`:
- 寫入效率更好
- SDK 會幫你處理部分重試
- 更適合批次資料導入
---
## 七、配置 S3 事件通知觸發 Lambda
這一步做完後,S3 才會在上傳檔案時觸發 Lambda。
### 步驟 1:打開 S3 Bucket
- 進入 `demo-data-ingest-2026`
- 點擊 **Properties**
- 找到 **Event notifications**
- 點擊 **Create event notification**
### 步驟 2:設定事件條件
可使用以下配置:
- **Event name**:`trigger-lambda-on-orders-upload`
- **Prefix**:`orders/`
- **Suffix**:`.json`
- **Event types**:選 `PUT`
- **Destination**:選 `Lambda function`
- **Lambda function**:選 `s3-json-to-dynamodb`
### 為什麼要設 Prefix/Suffix?
避免所有上傳都觸發 Lambda,尤其當 Bucket 不只存一種資料時,這個過濾非常重要。
例如:
- 只有 `orders/` 目錄下的 JSON 觸發
- 圖片、備份檔、不相關檔案不會觸發
### 常見錯誤
#### 1. 無法選取 Lambda 作為目的地
通常是 Lambda 權限授權沒自動建立成功。你可以重新在 Lambda 觸發器中手動添加,或檢查是否已有對應資源政策。
#### 2. 檔案上傳後沒反應
請依序檢查:
- 檔案路徑是否符合 Prefix,例如是不是傳到 `upload/` 而不是 `orders/`
- 副檔名是否真的是 `.json`
- Bucket 與 Lambda 是否在同一 Region
- Lambda 是否有被觸發記錄
---
## 八、上傳檔案測試整條鏈路
### 方法 1:控制台手動上傳
進入 S3 Bucket:
- 點擊 **Upload**
- 上傳 `orders-001.json`
- 放到 `orders/` 路徑下
完整 Key 應該是:
`orders/orders-001.json`
AWS企業帳號代理 ### 方法 2:AWS CLI 上傳
```bash
aws s3 cp orders-001.json s3://demo-data-ingest-2026/orders/orders-001.json
```
### 驗證結果
#### 1. 看 Lambda 執行記錄
進入 Lambda:
- 點擊 **Monitor**
- 查看 **CloudWatch Logs**
你應該能看到類似:
```text
Processing file s3://demo-data-ingest-2026/orders/orders-001.json
```
#### 2. 看 DynamoDB 是否入庫
進入 `orders_raw`:
- 點擊 **Explore table items**
- 確認是否出現 `A1001`、`A1002`
---
AWS企業帳號代理 ## 九、常見問題排查指南
下面這部分是實際操作時最常遇到的問題。
### 問題 1:S3 上傳成功,但 Lambda 沒有觸發
### 排查順序
1. 檢查 S3 Event Notification 是否已建立。
2. 檢查 Prefix/Suffix 是否匹配。
3. 檢查 Lambda 與 S3 是否同 Region。
4. 檢查 Lambda 資源政策是否允許 S3 觸發。
5. 查看 Lambda Monitor 是否完全沒有調用記錄。
### 典型原因
- 路徑不符合 `orders/`
- 檔案不是 `.json`
- 通知配置設錯事件類型
- 之前刪過 Lambda,S3 通知指向舊 ARN
---
### 問題 2:Lambda 有觸發,但報 AccessDenied
### 典型日誌
```text
An error occurred (AccessDenied) when calling the GetObject operation
```
### 排查方法
- 檢查 Lambda 執行角色是否有 `s3:GetObject`
- 檢查 Resource 是否包含 `bucket/*`
- 確認實際讀取的 Bucket 是否就是授權的那個
- 若 Bucket 使用 KMS 加密,還需要額外的 KMS 解密權限
---
### 問題 3:Lambda 執行成功,但 DynamoDB 沒資料
### 排查方法
1. 查看程式是否真的進入 `batch.put_item()`。
2. 檢查 JSON 是否為 list。
3. 檢查每一筆資料是否包含 `order_id`。
4. 查看 `TABLE_NAME` 環境變數是否正確。
5. 確認 Lambda Role 是否有 `dynamodb:PutItem` 或 `BatchWriteItem`。
### 補充提醒
如果你開啟了 skip invalid item 的邏輯,函數成功不代表所有資料都寫入了。要看 CloudWatch 日誌裡是否出現跳過記錄。
---
### 問題 4:報 JSONDecodeError
AWS企業帳號代理 ### 原因
上傳檔案不是合法 JSON,常見情況:
- 多了一個逗號
- 編碼不是 UTF-8
- 實際內容不是 list,而是單一物件或 CSV
### 解法
- 本地先用工具驗證 JSON
- 如果來源檔案格式不固定,Lambda 內加入更嚴格的異常處理
例如:
```python
try:
data = json.loads(content)
except json.JSONDecodeError as e:
print(f"Invalid JSON file: {e}")
raise
```
---
### 問題 5:資料量大時 Lambda 超時
### 表現
- 檔案上傳後 Lambda 執行一段時間失敗
- CloudWatch 顯示 Task timed out
### 解法
- 提高 Lambda timeout,例如從 3 秒調到 30 秒或 60 秒
- 增加記憶體配置,CPU 也會同步提高
- 將大檔拆分成多個小檔
- 如果是超大批次資料,不要直接用單次 S3 事件處理全部內容,可改為 SQS 緩衝或 Step Functions 分段處理
---
AWS企業帳號代理 ## 十、配置優化建議
這部分是把教程從「能跑」提升到「較穩定可維護」。
### 1. Lambda Timeout 與 Memory
預設值通常太保守。建議起步:
- **Memory**:512 MB 或 1024 MB
- **Timeout**:30 秒
如果你的 JSON 檔案接近數 MB,256 MB 常常不夠用。
### 2. 增加失敗保護
可以在 Lambda 中把異常檔案寫入另一個 S3 路徑,例如:
AWS企業帳號代理 - `failed/`
- `quarantine/`
這樣不是只有 CloudWatch 報錯,還能保留原始失敗資料供排查。
### 3. 控制觸發範圍
不要讓整個 Bucket 的所有物件都觸發處理流程。建議至少用:
- Prefix:`orders/`
- Suffix:`.json`
### 4. DynamoDB 寫入模式
若資料量逐漸增大:
- 優先使用 `batch_writer`
- 避免在單次 Lambda 中做過多同步查詢
- 如果要去重,可在資料模型中加條件寫入或版本欄位
### 5. CloudWatch 日誌格式化
建議每次打印關鍵資訊:
- Bucket 名稱
- Object Key
- 記錄數量
- 成功筆數
- 失敗筆數
- Request ID
這樣故障時不用反覆加 log 再重跑。
---
## 十一、進階配置:避免重複處理
在實際環境中,S3 事件可能因重試或重複上傳導致相同資料被重複寫入。
### 可行做法 1:用 order_id 做覆蓋寫入
如果 `order_id` 唯一,相同主鍵再次寫入只會覆蓋舊值。適合可接受冪等覆蓋的場景。
### 可行做法 2:在 DynamoDB 增加檔案資訊
例如在每筆資料加上:
- `source_file`
- `ingested_at`
方便後續追蹤是哪個檔案寫入的。
### 可行做法 3:記錄已處理檔案清單
可建立另一張表記錄:
- `file_key`
- `etag`
- `processed_at`
Lambda 開始處理前先查這張表,避免重複消費。
---
AWS企業帳號代理 ## 十二、安全與權限實踐
雖然這是無伺服器架構,但權限控制不能省。
### 1. IAM 權限最小化
AWS企業帳號代理 不要直接給 Lambda:
- `AmazonS3FullAccess`
- `AmazonDynamoDBFullAccess`
只授權需要的 Bucket 與 Table。
### 2. S3 Bucket 不公開
保持 Block Public Access 開啟,除非你的業務明確需要公開下載。
### 3. 環境變數保護
如果 Lambda 內有敏感配置,不要直接明文硬編碼,可配合:
- AWS Systems Manager Parameter Store
- AWS Secrets Manager
本篇示例只有表名,不涉及敏感資訊,但正式環境應維持分離。
---
## 十三、性能與成本控制建議
這部分很實用,尤其當資料量增加後。
### S3
- 儲存原始資料成本通常不高
- 但如果你大量重複上傳測試檔案,版本控制可能累積很多舊版本,要定期清理
### Lambda
成本主要跟以下有關:
AWS企業帳號代理 - 執行次數
- 執行時間
- 記憶體大小
**優化思路:**
- 過濾不必要觸發
- 減少函數內無效處理
- 用 batch_writer 降低單筆操作耗時
### DynamoDB
如果你選 On-demand:
- 初期方便
- 流量穩定後可以評估 Provisioned 模式做成本優化
但在大多數中小型事件處理場景,先把穩定性做出來,比過早壓榨每分成本更重要。
---
## 十四、適合直接複製的完整操作清單
如果你只想快速照著做,按下面執行即可。
### 部署清單
1. 在同一 Region 建立 S3 Bucket。
2. 建立 DynamoDB 表 `orders_raw`,主鍵 `order_id`。
3. 建立 IAM Role:
- 掛 `AWSLambdaBasicExecutionRole`
- 加入 S3 `GetObject` 與 DynamoDB `PutItem/BatchWriteItem` 權限
4. 建立 Lambda 函數 `s3-json-to-dynamodb`。
5. 配置環境變數:`TABLE_NAME=orders_raw`。
6. 上傳 Python 程式碼並 Deploy。
7. 在 S3 建立 Event Notification:
- Prefix:`orders/`
- Suffix:`.json`
- Event:PUT
- Target:Lambda
8. 上傳 `orders/orders-001.json`。
9. 到 CloudWatch 看 Lambda 日誌。
10. 到 DynamoDB 驗證資料是否已寫入。
---
AWS企業帳號代理 ## 十五、總結
AWS企業帳號代理 如果你的目標是用 AWS 快速搭建一條無伺服器資料處理鏈路,**S3 + Lambda + DynamoDB** 是最容易落地、也最適合事件驅動場景的組合之一。
在實際操作中,真正影響成敗的往往不是程式碼本身,而是以下幾個配置點:
- S3 事件是否正確綁定 Lambda
- Lambda IAM 權限是否完整且精準
- DynamoDB 表主鍵是否符合後續查詢需求
- CloudWatch 日誌是否足夠支持故障排查
- 大檔與異常資料是否有超時和錯誤保護
如果你照著本文配置,通常可以在很短時間內完成一條可測試、可驗證的資料入庫流程。
若要進一步擴展到生產實踐,下一步建議優先加入:
- 失敗重試與死信機制
- 檔案去重處理
- DynamoDB 索引優化
- SQS 或 Step Functions 做解耦與分段處理
先把主鏈路跑通,再逐步補上可靠性與擴展性,這樣最符合實際工程落地節奏。


