

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 現代化
<a name="modernization-pattern-list"></a>

**Topics**
+ [使用 DynamoDB TTL 自動將項目封存至 Amazon S3](automatically-archive-items-to-amazon-s3-using-dynamodb-ttl.md)
+ [在 Amazon OpenSearch Service 中建置多租戶無伺服器架構](build-a-multi-tenant-serverless-architecture-in-amazon-opensearch-service.md)
+ [使用 AWS CDK 搭配 TypeScript 部署多堆疊應用程式](deploy-multiple-stack-applications-using-aws-cdk-with-typescript.md)
+ [使用 AWS SAM 自動化巢狀應用程式的部署](automate-deployment-of-nested-applications-using-aws-sam.md)
+ [使用 AWS Lambda 字符販賣機實作 Amazon S3 的 SaaS 租用戶隔離](implement-saas-tenant-isolation-for-amazon-s3-by-using-an-aws-lambda-token-vending-machine.md)
+ [使用 AWS Step Functions 實作無伺服器 saga 模式](implement-the-serverless-saga-pattern-by-using-aws-step-functions.md)
+ [使用 AWS CDK 設定 Amazon ECS Anywhere 來管理內部部署容器應用程式](manage-on-premises-container-applications-by-setting-up-amazon-ecs-anywhere-with-the-aws-cdk.md)
+ [在 AWS 上現代化 ASP.NET Web Forms 應用程式](modernize-asp-net-web-forms-applications-on-aws.md)
+ [使用 C\$1 和 AWS CDK 在孤立模型的 SaaS 架構中加入租用戶](tenant-onboarding-in-saas-architecture-for-the-silo-model-using-c-and-aws-cdk.md)
+ [使用 CQRS 和事件來源將整體分解為微服務](decompose-monoliths-into-microservices-by-using-cqrs-and-event-sourcing.md)
+ [更多模式](modernization-more-patterns-pattern-list.md)

# 使用 DynamoDB TTL 自動將項目封存至 Amazon S3
<a name="automatically-archive-items-to-amazon-s3-using-dynamodb-ttl"></a>

*Tabby Ward，Amazon Web Services*

## 總結
<a name="automatically-archive-items-to-amazon-s3-using-dynamodb-ttl-summary"></a>

此模式提供從 Amazon DynamoDB 資料表移除舊資料並將其封存至 Amazon Web Services (AWS) 上 Amazon Simple Storage Service (Amazon S3) 儲存貯體的步驟，而不必管理伺服器機群。 

此模式使用 Amazon DynamoDB 存留時間 (TTL) 自動刪除舊項目，並使用 Amazon DynamoDB 串流擷取 TTL 過期項目。然後，它會將 DynamoDB Streams 連線至 AWS Lambda，其會執行程式碼，而無需佈建或管理任何伺服器。 

將新項目新增至 DynamoDB 串流時，會啟動 Lambda 函數，並將資料寫入 Amazon Data Firehose 交付串流。Firehose 提供簡單、全受管的解決方案，將資料作為封存載入 Amazon S3。

DynamoDB 通常用於存放時間序列資料，例如網頁點擊串流資料或來自感應器和連線裝置的物聯網 (IoT) 資料。許多客戶不想要刪除較不常存取的項目，而是想要將其封存以供稽核之用。TTL 會根據時間戳記屬性自動刪除項目，簡化此封存。 

TTL 刪除的項目可以在 DynamoDB Streams 中識別，該串流會擷取項目層級修改的時間順序，並將序列存放在日誌中長達 24 小時。此資料可供 Lambda 函數使用，並封存在 Amazon S3 儲存貯體中，以降低儲存成本。為了進一步降低成本，可以建立 [Amazon S3 生命週期規則](https://docs.aws.amazon.com/AmazonS3/latest/userguide/object-lifecycle-mgmt.html)，以自動將資料 （建立後立即） 轉換為成本最低的[儲存類別](https://aws.amazon.com/s3/storage-classes/)。

## 先決條件和限制
<a name="automatically-archive-items-to-amazon-s3-using-dynamodb-ttl-prereqs"></a>

**先決條件**
+ 作用中的 AWS 帳戶
+ [在 macOS、Linux 或 Windows 上安裝和設定 AWS Command Line Interface (AWS CLI) 1.7 或更新版本。](https://docs.aws.amazon.com/cli/latest/userguide/install-cliv1.html) macOS
+ [Python 3.7 ](https://www.python.org/downloads/release/python-370/)或更新版本。
+ [Boto3](https://boto3.amazonaws.com/v1/documentation/api/latest/index.html)，已安裝並設定。如果尚未安裝 Boto3，請執行 `python -m pip install boto3`命令來安裝它。

## Architecture
<a name="automatically-archive-items-to-amazon-s3-using-dynamodb-ttl-architecture"></a>

**技術堆疊**
+ Amazon DynamoDB
+ Amazon DynamoDB Streams
+ Amazon Data Firehose
+ AWS Lambda
+ Amazon S3

![\[從 DynamoDB 到 S3 儲存貯體的四步驟程序。\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/images/pattern-img/9dbc833f-cf3c-4574-8f09-d0b81134fe41/images/50d9da65-5398-4a99-bc8f-58afc80e9d7b.png)


1. TTL 會刪除項目。

1. DynamoDB 串流觸發程序會叫用 Lambda 串流處理器函數。

1. Lambda 函數會以批次格式將記錄放入 Firehose 交付串流中。

1. 資料記錄會封存在 S3 儲存貯體中。

## 工具
<a name="automatically-archive-items-to-amazon-s3-using-dynamodb-ttl-tools"></a>
+ [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-install.html) – AWS Command Line Interface (AWS CLI) 是管理 AWS 服務的統一工具。
+ [Amazon DynamoDB](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Introduction.html) – Amazon DynamoDB 是一種鍵值和文件資料庫，可在任何規模下提供單一位數毫秒的效能。
+ [Amazon DynamoDB 存留時間 (TTL)](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/howitworks-ttl.html) – Amazon DynamoDB TTL 可協助您定義每個項目的時間戳記，以判斷何時不再需要項目。
+ [Amazon DynamoDB Streams](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Types_Amazon_DynamoDB_Streams.html) – Amazon DynamoDB Streams 會擷取任何 DynamoDB 資料表中項目層級修改的時間順序，並將此資訊存放在日誌中長達 24 小時。
+ [Amazon Data Firehose](https://docs.aws.amazon.com/firehose/latest/dev/what-is-this-service.html) – Amazon Data Firehose 是將串流資料可靠載入資料湖、資料存放區和分析服務的最簡單方法。
+ [AWS Lambda](https://docs.aws.amazon.com/lambda/latest/dg/welcome.html) – AWS Lambda 執行程式碼，無需佈建或管理伺服器。您只需為使用的運算時間支付費用。
+ [Amazon S3](https://docs.aws.amazon.com/AmazonS3/latest/dev/Welcome.html) – Amazon Simple Storage Service (Amazon S3) 是一種物件儲存服務，可提供業界領先的可擴展性、資料可用性、安全性和效能。

**Code**

此模式的程式碼可在 GitHub Archive [項目中使用 DynamoDB TTL 儲存庫傳送至 S3](https://github.com/aws-samples/automatically-archive-items-to-s3-using-dynamodb-ttl)。

## 史詩
<a name="automatically-archive-items-to-amazon-s3-using-dynamodb-ttl-epics"></a>

### 設定 DynamoDB 資料表、TTL 和 DynamoDB 串流
<a name="set-up-a-dynamodb-table-ttl-and-a-dynamodb-stream"></a>


| 任務 | Description | 所需的技能 | 
| --- | --- | --- | 
| 建立 DynamoDB 資料表。 | 使用 AWS CLI 在 DynamoDB 中建立名為 的資料表`Reservation`。選擇隨機讀取容量單位 (RCU) 和寫入容量單位 (WCU)，並為您的資料表提供兩個屬性： `ReservationID`和 `ReservationDate`。 <pre>aws dynamodb create-table \<br />--table-name Reservation \<br />--attribute-definitions AttributeName=ReservationID,AttributeType=S AttributeName=ReservationDate,AttributeType=N \<br />--key-schema AttributeName=ReservationID,KeyType=HASH AttributeName=ReservationDate,KeyType=RANGE \<br />--provisioned-throughput ReadCapacityUnits=100,WriteCapacityUnits=100 </pre>`ReservationDate` 是用來開啟 TTL 的 epoch 時間戳記。 | 雲端架構師、應用程式開發人員 | 
| 開啟 DynamoDB TTL。 | 使用 AWS CLI 為 `ReservationDate` 屬性開啟 DynamoDB TTL。<pre>aws dynamodb update-time-to-live \<br />--table-name Reservation\<br />  --time-to-live-specification Enabled=true,AttributeName=ReservationDate</pre> | 雲端架構師、應用程式開發人員 | 
| 開啟 DynamoDB 串流。 | 使用 AWS CLI，透過使用串流類型來開啟`Reservation`資料表的 DynamoDB `NEW_AND_OLD_IMAGES` 串流。 <pre>aws dynamodb update-table \<br />--table-name Reservation \<br />  --stream-specification StreamEnabled=true,StreamViewType=NEW_AND_OLD_IMAGES</pre>此串流將包含新項目、更新項目、已刪除項目和 TTL 刪除項目的記錄。TTL 刪除的項目記錄包含額外的中繼資料屬性，以區分它們與手動刪除的項目。TTL 刪除`userIdentity`的 欄位表示 DynamoDB 服務已執行刪除動作。 在此模式中，只會封存 TTL 刪除的項目，但您只能封存 `eventName`為 `REMOVE`且`userIdentity`包含`principalId`等於 的記錄`dynamodb.amazonaws.com`。 | 雲端架構師、應用程式開發人員 | 

### 建立和設定 S3 儲存貯體
<a name="create-and-configure-an-s3-bucket"></a>


| 任務 | Description | 所需的技能 | 
| --- | --- | --- | 
| 建立 S3 儲存貯體。 | 使用 AWS CLI 在您的 AWS 區域中建立目的地 S3 儲存貯體，`us-east-1`將 取代為您的區域，並將 amzn-s3-demo-destination-bucket 取代為您的儲存貯體名稱。 <pre>aws s3api create-bucket \<br />--bucket amzn-s3-demo-destination-bucket \<br />--region us-east-1</pre>請確定 S3 儲存貯體的名稱是全域唯一的，因為命名空間是由所有 AWS 帳戶共用。 | 雲端架構師、應用程式開發人員 | 
| 建立 S3 儲存貯體的 30 天生命週期政策。 | [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/automatically-archive-items-to-amazon-s3-using-dynamodb-ttl.html) | 雲端架構師、應用程式開發人員 | 

### 建立 Firehose 交付串流
<a name="create-a-akf-delivery-stream"></a>


| 任務 | Description | 所需的技能 | 
| --- | --- | --- | 
| 建立和設定 Firehose 交付串流。 | 從 GitHub 儲存庫下載和編輯`CreateFireHoseToS3.py`程式碼範例。 此程式碼是以 Python 撰寫，並說明如何建立 Firehose 交付串流和 AWS Identity and Access Management (IAM) 角色。IAM 角色會有政策，可供 Firehose 用來寫入目的地 S3 儲存貯體。若要執行指令碼，請使用下列命令和命令列引數。引數 1 = `<Your_S3_bucket_ARN>`，這是您先前建立之儲存貯體的 Amazon Resource Name (ARN)引數 2 = 您的 Firehose 名稱 （此試驗正在使用`firehose_to_s3_stream`。)引數 3 = 您的 IAM 角色名稱 （此試驗使用 `firehose_to_s3`。)<pre>python CreateFireHoseToS3.py <Your_S3_Bucket_ARN> firehose_to_s3_stream firehose_to_s3</pre>如果指定的 IAM 角色不存在，指令碼會建立具有信任關係政策的擔任角色，以及授予足夠 Amazon S3 許可的政策。如需這些政策的範例，請參閱*其他資訊*一節。 | 雲端架構師、應用程式開發人員 | 
| 驗證 Firehose 交付串流。 | 使用 AWS CLI 來驗證已成功建立交付串流，以描述 Firehose 交付串流。<pre>aws firehose describe-delivery-stream --delivery-stream-name firehose_to_s3_stream </pre> | 雲端架構師、應用程式開發人員 | 

### 建立 Lambda 函數來處理 Firehose 交付串流
<a name="create-a-lambda-function-to-process-the-akf-delivery-stream"></a>


| 任務 | Description | 所需的技能 | 
| --- | --- | --- | 
| 建立 Lambda 函數的信任政策。 | 使用下列資訊建立信任政策檔案。<pre> {<br />     "Version": "2012-10-17",		 	 	 <br />     "Statement": [<br />      {<br />          "Effect": "Allow",<br />          "Principal": {<br />              "Service": "lambda.amazonaws.com"<br />           },<br />           "Action": "sts:AssumeRole"<br />      }<br />    ]<br />  } </pre>這可讓您的函數存取 AWS 資源。 | 雲端架構師、應用程式開發人員 | 
| 建立 Lambda 函數的執行角色。 | 若要建立執行角色，請執行下列程式碼。<pre>aws iam create-role --role-name lambda-ex --assume-role-policy-document file://TrustPolicy.json</pre> | 雲端架構師、應用程式開發人員 | 
| 將許可新增至角色。 | 若要將許可新增至角色，請使用 `attach-policy-to-role`命令。<pre>aws iam attach-role-policy --role-name lambda-ex --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole<br />aws iam attach-role-policy --role-name lambda-ex --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaDynamoDBExecutionRole<br />aws iam attach-role-policy --role-name lambda-ex --policy-arn arn:aws:iam::aws:policy/AmazonKinesisFirehoseFullAccess<br />aws iam attach-role-policy --role-name lambda-ex --policy-arn arn:aws:iam::aws:policy/IAMFullAccess </pre> | 雲端架構師、應用程式開發人員 | 
| 建立 Lambda 函式。 | 執行下列命令，從程式碼儲存庫壓縮 `LambdaStreamProcessor.py` 檔案。<pre>zip function.zip LambdaStreamProcessor.py</pre>當您建立 Lambda 函數時，您將需要 Lambda 執行角色 ARN。若要取得 ARN，請執行下列程式碼。<pre>aws iam get-role \<br />--role-name lambda-ex </pre>若要建立 Lambda 函數，請執行下列程式碼。<pre># Review the environment variables and replace them with your values.<br /><br />aws lambda create-function --function-name LambdaStreamProcessor \<br />--zip-file fileb://function.zip --handler LambdaStreamProcessor.handler --runtime python3.8 \<br />--role {Your Lamda Execution Role ARN}\<br />  --environment Variables="{firehose_name=firehose_to_s3_stream,bucket_arn = <Your_S3_bucket_ARN>,iam_role_name = firehose_to_s3, batch_size=400}"</pre> | 雲端架構師、應用程式開發人員 | 
| 設定 Lambda 函數觸發。 | 使用 AWS CLI 來設定觸發 (DynamoDB Streams)，這會叫用 Lambda 函數。400 的批次大小是為了避免在 Lambda 並行問題中執行。<pre>aws lambda create-event-source-mapping --function-name LambdaStreamProcessor \<br />--batch-size 400 --starting-position LATEST \<br />--event-source-arn <Your Latest Stream ARN From DynamoDB Console></pre> | 雲端架構師、應用程式開發人員 | 

### 測試功能
<a name="test-the-functionality"></a>


| 任務 | Description | 所需的技能 | 
| --- | --- | --- | 
| 將具有過期時間戳記的項目新增至保留資料表。 | 若要測試功能，請將具有過期 epoch 時間戳記的項目新增至`Reservation`資料表。TTL 會根據時間戳記自動刪除項目。 Lambda 函數會在 DynamoDB Stream 活動上啟動，並篩選事件以識別`REMOVE`活動或刪除的項目。然後，它會以批次格式將記錄放入 Firehose 交付串流。Firehose 交付串流會使用 `firehosetos3example/year=current year/month=current month/ day=current day/hour=current hour/`字首將項目傳輸到目的地 S3 儲存貯體。若要最佳化資料擷取，請使用 `Prefix`和 設定 Amazon S3`ErrorOutputPrefix`，詳細資訊請參閱*其他資訊*一節。 | 雲端架構師  | 

### 清除資源
<a name="clean-up-the-resources"></a>


| 任務 | Description | 所需的技能 | 
| --- | --- | --- | 
| 刪除所有資源。 | 刪除所有資源，以確保不會針對您未使用的任何服務向您收費。  | 雲端架構師、應用程式開發人員 | 

## 相關資源
<a name="automatically-archive-items-to-amazon-s3-using-dynamodb-ttl-resources"></a>
+ [管理儲存生命週期](https://docs.aws.amazon.com/AmazonS3/latest/user-guide/create-lifecycle.html)
+ [Amazon S3 儲存類別](https://aws.amazon.com/s3/storage-classes/)
+ [適用於 Python 的 AWS 開發套件 (Boto3) 文件](https://boto3.amazonaws.com/v1/documentation/api/latest/index.html)

## 其他資訊
<a name="automatically-archive-items-to-amazon-s3-using-dynamodb-ttl-additional"></a>

**建立和設定 Firehose 交付串流 – 政策範例**

*Firehose 信任關係政策範例文件*

```
firehose_assume_role = {
        'Version': '2012-10-17',
        'Statement': [
            {
                'Sid': '',
                'Effect': 'Allow',
                'Principal': {
                    'Service': 'firehose.amazonaws.com'
                },
                'Action': 'sts:AssumeRole'
            }
        ]
    }
```

*S3 許可政策範例*

```
s3_access = {
        "Version": "2012-10-17",		 	 	 
        "Statement": [
            {
                "Sid": "",
                "Effect": "Allow",
                "Action": [
                    "s3:AbortMultipartUpload",
                    "s3:GetBucketLocation",
                    "s3:GetObject",
                    "s3:ListBucket",
                    "s3:ListBucketMultipartUploads",
                    "s3:PutObject"
                ],
                "Resource": [
                    "{your s3_bucket ARN}/*",
                    "{Your s3 bucket ARN}"
                ]
            }
        ]
    }
```

**測試功能 – Amazon S3 組態**

Amazon S3 組態具有下列特性`Prefix`，且`ErrorOutputPrefix`選擇此組態來最佳化資料擷取。 

*prefix*

```
firehosetos3example/year=! {timestamp: yyyy}/month=! {timestamp:MM}/day=! {timestamp:dd}/hour=!{timestamp:HH}/
```

Firehose 首先會在 S3 儲存貯體`firehosetos3example`下直接建立名為 的基本資料夾。然後，它會使用 Java [DateTimeFormatter](https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html) 格式評估表達式 `!{timestamp:yyyy}`、`!{timestamp:dd}`、 `!{timestamp:MM}`和 `!{timestamp:HH}` 到年、月、日和小時。

例如，Unix epoch 時間中 1604683577 的大致到達時間戳記會評估為 `year=2020`、`day=06`、 `month=11`和 `hour=05`。因此，Amazon S3 中交付資料記錄的位置會評估為 `firehosetos3example/year=2020/month=11/day=06/hour=05/`。

*ErrorOutputPrefix*

```
firehosetos3erroroutputbase/!{firehose:random-string}/!{firehose:error-output-type}/!{timestamp:yyyy/MM/dd}/
```

`ErrorOutputPrefix` 會產生`firehosetos3erroroutputbase`直接在 S3 儲存貯體下呼叫的基本資料夾。表達式會`!{firehose:random-string}`評估為 11 個字元的隨機字串，例如 `ztWxkdg3Thg`。交付失敗記錄的 Amazon S3 物件位置可以評估為 `firehosetos3erroroutputbase/ztWxkdg3Thg/processing-failed/2020/11/06/`。

# 在 Amazon OpenSearch Service 中建置多租戶無伺服器架構
<a name="build-a-multi-tenant-serverless-architecture-in-amazon-opensearch-service"></a>

*Tabby Ward 和 Nisha Gambhir，Amazon Web Services*

## 總結
<a name="build-a-multi-tenant-serverless-architecture-in-amazon-opensearch-service-summary"></a>

Amazon OpenSearch Service 是一種受管服務，可讓您輕鬆部署、操作和擴展 Elasticsearch，這是熱門的開放原始碼搜尋和分析引擎。OpenSearch Service 提供任意文字搜尋，以及近乎即時的串流資料擷取和儀表板，例如日誌和指標。

軟體即服務 (SaaS) 供應商經常使用 OpenSearch Service 來處理各種使用案例，例如以可擴展且安全的方式獲得客戶洞見，同時降低複雜性和停機時間。

在多租戶環境中使用 OpenSearch Service 引入了一系列的考量，會影響 SaaS 解決方案的分割、隔離、部署和管理。SaaS 提供者必須考慮如何使用不斷轉移的工作負載，有效地擴展其 Elasticsearch 叢集。他們還需要考慮分層和嘈雜的鄰國條件如何影響其分割模型。

此模式會檢閱用於使用 Elasticsearch 建構來表示和隔離租戶資料的模型。此外，模式著重於簡單的無伺服器參考架構作為範例，以示範在多租戶環境中使用 OpenSearch Service 進行索引和搜尋。它會實作集區資料分割模型，在所有租用戶之間共用相同的索引，同時維持租用戶的資料隔離。此模式使用下列 AWS 服務：Amazon API Gateway AWS Lambda、Amazon Simple Storage Service (Amazon S3) 和 OpenSearch Service。

如需集區模型和其他資料分割模型的詳細資訊，請參閱[其他資訊](#build-a-multi-tenant-serverless-architecture-in-amazon-opensearch-service-additional)一節。

## 先決條件和限制
<a name="build-a-multi-tenant-serverless-architecture-in-amazon-opensearch-service-prereqs"></a>

**先決條件**
+ 作用中 AWS 帳戶
+ [AWS Command Line Interface (AWS CLI) 2.x 版](https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html)，在 macOS、Linux 或 Windows 上安裝和設定
+ [Python 3.9 版](https://www.python.org/downloads/release/python-3921/)
+ [pip3](https://pip.pypa.io/en/stable/) – Python 原始程式碼以要部署在 Lambda 函數中的 .zip 檔案提供。如果您想要在本機使用或自訂程式碼，請依照下列步驟開發和重新編譯原始程式碼：

  1. 在與 Python 指令碼相同的目錄中執行下列命令來產生`requirements.txt`檔案： `pip3 freeze > requirements.txt`

  1. 安裝相依性： `pip3 install -r requirements.txt`

**限制**
+ 此程式碼在 Python 中執行，目前不支援其他程式設計語言。 
+ 範例應用程式不包含 AWS 跨區域或災難復原 (DR) 支援。 
+ 此模式僅供示範之用。它不適用於生產環境。

## Architecture
<a name="build-a-multi-tenant-serverless-architecture-in-amazon-opensearch-service-architecture"></a>

下圖說明此模式的高階架構。架構包含下列項目：
+ Lambda 索引和查詢內容 
+ OpenSearch Service 執行搜尋 
+ API Gateway 提供與 使用者的 API 互動
+ Amazon S3 儲存原始 （非索引） 資料
+ Amazon CloudWatch 監控日誌
+ AWS Identity and Access Management (IAM) 以建立租戶角色和政策

![\[高階多租戶無伺服器架構。\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/images/pattern-img/750196bb-03f6-4b6e-92cd-eb7141602547/images/1a8501e7-0776-4aca-aed3-28e3ada1d15d.png)


**自動化和擴展**

為了簡化， 模式會使用 AWS CLI 來佈建基礎設施和部署範例程式碼。您可以建立 CloudFormation 範本或 AWS Cloud Development Kit (AWS CDK) 指令碼來自動化模式。

## 工具
<a name="build-a-multi-tenant-serverless-architecture-in-amazon-opensearch-service-tools"></a>

**AWS 服務**
+ [AWS CLI](https://aws.amazon.com/cli/) 是統一的工具，可讓您在命令列 Shell 中使用命令來管理 AWS 服務 和 資源。
+ [Lambda](https://aws.amazon.com/lambda/) 是一種運算服務，可讓您執行程式碼，而無需佈建或管理伺服器。Lambda 只有在需要時才會執行程式碼，可自動從每天數項請求擴展成每秒數千項請求。
+ [API Gateway](https://aws.amazon.com/api-gateway/) 是 ， AWS 服務 用於建立、發佈、維護、監控和保護任何規模的 REST、HTTP 和 WebSocket APIs。
+ [Amazon S3](https://aws.amazon.com/s3/) 是一種物件儲存服務，可讓您隨時從 Web 上的任何位置存放和擷取任意數量的資訊。
+ [OpenSearch Service](https://aws.amazon.com/opensearch-service/) 是一項全受管服務，可讓您以經濟實惠的方式大規模部署、保護和執行 Elasticsearch。

**Code**

附件提供此模式的範例檔案。其中包含：
+ `index_lambda_package.zip` – 使用集區模型為 OpenSearch Service 中的資料編製索引的 Lambda 函數。
+ `search_lambda_package.zip` – 在 OpenSearch Service 中搜尋資料的 Lambda 函數。
+ `Tenant-1-data` – Tenant-1 的原始 （非索引） 資料範例。
+ `Tenant-2-data` – Tenant-2 的原始 （非索引） 資料範例。

**重要**  
此模式中的故事包括針對 Unix、Linux 和 macOS 格式化的 AWS CLI 命令範例。用於 Windows 時，請以插入號 (^) 取代每一行結尾處的 Unix 接續字元斜線 (\$1)。

**注意**  
在 AWS CLI 命令中，將角括號 (<>) 內的所有值取代為正確的值。

## 史詩
<a name="build-a-multi-tenant-serverless-architecture-in-amazon-opensearch-service-epics"></a>

### 建立和設定 S3 儲存貯體
<a name="create-and-configure-an-s3-bucket"></a>


| 任務 | Description | 所需的技能 | 
| --- | --- | --- | 
| 建立 S3 儲存貯體。 | 在 中建立 S3 儲存貯體 AWS 區域。此儲存貯體會保留範例應用程式的非索引租用戶資料。請確定 S3 儲存貯體的名稱是全域唯一的，因為命名空間是由所有 共用 AWS 帳戶。若要建立 S3 儲存貯體，您可以使用 AWS CLI [create-bucket](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/s3api/create-bucket.html) 命令，如下所示：<pre>aws s3api create-bucket \<br />  --bucket <tenantrawdata> \<br />  --region <your-AWS-Region></pre>其中 `tenantrawdata`是 S3 儲存貯體名稱。（您可以使用遵循儲存[貯體命名準則](https://docs.aws.amazon.com/AmazonS3/latest/userguide/bucketnamingrules.html)的任何唯一名稱。) | 雲端架構師、雲端管理員 | 

### 建立和設定 Elasticsearch 叢集
<a name="create-and-configure-an-elasticsearch-cluster"></a>


| 任務 | Description | 所需的技能 | 
| --- | --- | --- | 
| 建立 OpenSearch Service 網域 | 執行 AWS CLI [create-elasticsearch-domain](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/es/create-elasticsearch-domain.html) 命令來建立 OpenSearch Service 網域：<pre>aws es create-elasticsearch-domain \<br />  --domain-name vpc-cli-example \<br />  --elasticsearch-version 7.10 \<br />  --elasticsearch-cluster-config InstanceType=t3.medium.elasticsearch,InstanceCount=1 \<br />  --ebs-options EBSEnabled=true,VolumeType=gp2,VolumeSize=10 \<br />  --domain-endpoint-options "{\"EnforceHTTPS\": true}" \<br />  --encryption-at-rest-options "{\"Enabled\": true}" \<br />  --node-to-node-encryption-options "{\"Enabled\": true}" \<br />  --advanced-security-options "{\"Enabled\": true, \"InternalUserDatabaseEnabled\": true, \<br />    \"MasterUserOptions\": {\"MasterUserName\": \"KibanaUser\", \<br />    \"MasterUserPassword\": \"NewKibanaPassword@123\"}}" \<br />  --vpc-options "{\"SubnetIds\": [\"<subnet-id>\"], \"SecurityGroupIds\": [\"<sg-id>\"]}" \<br />  --access-policies "{\"Version\": \"2012-10-17\", \"Statement\": [ { \"Effect\": \"Allow\", \ <br />    \"Principal\": {\"AWS\": \"*\" }, \"Action\":\"es:*\", \<br />    \"Resource\": \"arn:aws:es:<region>:<account-id>:domain\/vpc-cli-example\/*\" } ] }"</pre>執行個體計數設定為 1，因為網域用於測試目的。您需要使用 `advanced-security-options` 參數啟用精細存取控制，因為在建立網域之後無法變更詳細資訊。 此命令會建立主要使用者名稱 (`KibanaUser`) 和密碼，您可以用來登入 Kibana 主控台。由於網域是虛擬私有雲端 (VPC) 的一部分，因此您必須指定要使用的存取政策，以確保可以連接 Elasticsearch 執行個體。如需詳細資訊，請參閱 AWS 文件中的在 [VPC 內啟動 Amazon OpenSearch Service 網域](https://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/es-vpc.html)。 | 雲端架構師、雲端管理員 | 
| 設定堡壘主機。 | 將 Amazon Elastic Compute Cloud (Amazon EC2) Windows 執行個體設定為堡壘主機，以存取 Kibana 主控台。Elasticsearch 安全群組必須允許來自 Amazon EC2 安全群組的流量。如需說明，請參閱部落格文章[使用堡壘伺服器控制 EC2 執行個體的網路存取](https://aws.amazon.com/blogs/security/controlling-network-access-to-ec2-instances-using-a-bastion-server/)。當堡壘主機已設定，且您有與執行個體相關聯的安全群組可用時，請使用 AWS CLI [authorize-security-group-ingress](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/ec2/authorize-security-group-ingress.html) 命令將許可新增至 Elasticsearch 安全群組，以允許來自 Amazon EC2 （堡壘主機） 安全群組的連接埠 443。<pre>aws ec2 authorize-security-group-ingress \<br />  --group-id <SecurityGroupIdfElasticSearch> \ <br />  --protocol tcp \<br />  --port 443 \<br />  --source-group <SecurityGroupIdfBashionHostEC2></pre> | 雲端架構師、雲端管理員 | 

### 建立和設定 Lambda 索引函數
<a name="create-and-configure-the-lam-index-function"></a>


| 任務 | Description | 所需的技能 | 
| --- | --- | --- | 
| 建立 Lambda 執行角色。 | 執行 AWS CLI [createe-role](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/iam/create-role.html) 命令，以授予 Lambda 索引函數對 AWS 服務 和 資源的存取權：<pre>aws iam create-role \<br />  --role-name index-lambda-role \<br />  --assume-role-policy-document file://lambda_assume_role.json</pre>其中 `lambda_assume_role.json`是將`AssumeRole`許可授予 Lambda 函數的 JSON 文件，如下所示：<pre>{<br />     "Version": "2012-10-17",		 	 	 <br />     "Statement": [<br />         {<br />             "Effect": "Allow",<br />             "Principal": {<br />                 "Service": "lambda.amazonaws.com"<br />               },<br />             "Action": "sts:AssumeRole"<br />         }<br />     ]<br /> }</pre> | 雲端架構師、雲端管理員 | 
| 將受管政策連接至 Lambda 角色。 | 執行 AWS CLI [attach-role-policy](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/iam/attach-role-policy.html) 命令，將受管政策連接到上一個步驟中建立的角色。這兩個政策提供角色建立彈性網路界面和將日誌寫入 CloudWatch Logs 的許可。<pre>aws iam attach-role-policy \<br />  --role-name index-lambda-role \<br />  --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole<br /><br />aws iam attach-role-policy \<br />  --role-name index-lambda-role \<br />  --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole </pre> | 雲端架構師、雲端管理員 | 
| 建立政策以授予 Lambda 索引函數讀取 S3 物件的許可。 | 對 執行 the AWS CLI [create-policy](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/iam/create-policy.html) 命令，授予 Lambda 索引函數讀取 S3 儲存貯體中物件的`s3:GetObject`許可：<pre>aws iam create-policy \<br />  --policy-name s3-permission-policy \<br />  --policy-document file://s3-policy.json</pre>檔案`s3-policy.json`是如下所示的 JSON 文件，授予`s3:GetObject`許可以允許對 S3 物件的讀取存取。如果您在建立 S3 儲存貯體時使用不同的名稱，請在 `Resource `區段中提供正確的儲存貯體名稱：<pre>{<br />    "Version": "2012-10-17",		 	 	 <br />    "Statement": [<br />        {<br />           "Effect": "Allow",<br />           "Action": "s3:GetObject",<br />           "Resource": "arn:aws:s3:::<tenantrawdata>/*"<br />        }<br />    ]<br />}</pre> | 雲端架構師、雲端管理員 | 
| 將 Amazon S3 許可政策連接至 Lambda 執行角色。 | 執行 AWS CLI [attach-role-policy](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/iam/attach-role-policy.html) 命令，將您在上一個步驟中建立的 Amazon S3 許可政策連接至 Lambda 執行角色：<pre>aws iam attach-role-policy \<br />  --role-name index-lambda-role \<br />  --policy-arn <PolicyARN></pre>其中 `PolicyARN`是 Amazon S3 許可政策的 Amazon Resource Name (ARN)。您可以從上一個命令的輸出取得此值。 | 雲端架構師、雲端管理員 | 
| 建立 Lambda 索引函數。 | 執行 AWS CLI [createe-function](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/create-function.html) 命令來建立 Lambda 索引函數，這會存取 OpenSearch Service：<pre>aws lambda create-function \<br />  --function-name index-lambda-function \<br />  --zip-file fileb://index_lambda_package.zip \<br />  --handler lambda_index.lambda_handler \<br />  --runtime python3.9 \<br />  --role "arn:aws:iam::account-id:role/index-lambda-role" \<br />  --timeout 30 \<br />  --vpc-config "{\"SubnetIds\": [\"<subnet-id1\>", \"<subnet-id2>\"], \<br />    \"SecurityGroupIds\": [\"<sg-1>\"]}"</pre> | 雲端架構師、雲端管理員 | 
| 允許 Amazon S3 呼叫 Lambda 索引函數。 | 執行 AWS CLI [add-permission](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/add-permission.html) 命令，給予 Amazon S3 呼叫 Lambda 索引函數的許可：<pre>aws lambda add-permission \<br />  --function-name index-lambda-function \<br />  --statement-id s3-permissions \<br />  --action lambda:InvokeFunction \<br />  --principal s3.amazonaws.com \<br />  --source-arn "arn:aws:s3:::<tenantrawdata>" \<br />  --source-account "<account-id>" </pre> | 雲端架構師、雲端管理員 | 
| 為 Amazon S3 事件新增 Lambda 觸發條件。 | 執行 AWS CLI [put-bucket-notification-configuration](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/s3api/put-bucket-notification-configuration.html) 命令，以在偵測到 Amazon S3 `ObjectCreated`事件時傳送通知至 Lambda 索引函數。索引函數會在物件上傳到 S3 儲存貯體時執行。 <pre>aws s3api put-bucket-notification-configuration \<br />  --bucket <tenantrawdata> \<br />  --notification-configuration file://s3-trigger.json</pre>檔案`s3-trigger.json`是目前資料夾中的 JSON 文件，會在 Amazon S3 `ObjectCreated`事件發生時將資源政策新增至 Lambda 函數。 | 雲端架構師、雲端管理員 | 

### 建立和設定 Lambda 搜尋函數
<a name="create-and-configure-the-lam-search-function"></a>


| 任務 | Description | 所需的技能 | 
| --- | --- | --- | 
| 建立 Lambda 執行角色。 | 執行 AWS CLI [createe-role](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/iam/create-role.html) 命令，以授予 Lambda 搜尋函數對 AWS 服務 和 資源的存取權：<pre>aws iam create-role \<br />  --role-name search-lambda-role \<br />  --assume-role-policy-document file://lambda_assume_role.json</pre>其中 `lambda_assume_role.json` 是目前資料夾中的 JSON 文件，授予 Lambda 函數`AssumeRole`許可，如下所示：<pre>{<br />     "Version": "2012-10-17",		 	 	 <br />     "Statement": [<br />         {<br />             "Effect": "Allow",<br />             "Principal": {<br />                 "Service": "lambda.amazonaws.com"<br />               },<br />             "Action": "sts:AssumeRole"<br />         }<br />     ]<br /> }</pre> | 雲端架構師、雲端管理員 | 
| 將受管政策連接至 Lambda 角色。 | 執行 AWS CLI [attach-role-policy](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/iam/attach-role-policy.html) 命令，將受管政策連接至上一個步驟中建立的角色。這兩個政策提供角色建立彈性網路界面和將日誌寫入 CloudWatch Logs 的許可。<pre>aws iam attach-role-policy \<br />  --role-name search-lambda-role \<br />  --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole<br /><br />aws iam attach-role-policy \<br />  --role-name search-lambda-role \<br />  --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole </pre> | 雲端架構師、雲端管理員 | 
| 建立 Lambda 搜尋函數。 | 執行 AWS CLI [createe-function](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/create-function.html) 命令來建立 Lambda 搜尋函數，這會存取 OpenSearch Service：<pre>aws lambda create-function \<br />  --function-name search-lambda-function \<br />  --zip-file fileb://search_lambda_package.zip \<br />  --handler lambda_search.lambda_handler \<br />  --runtime python3.9 \<br />  --role "arn:aws:iam::account-id:role/search-lambda-role" \<br />  --timeout 30 \<br />  --vpc-config "{\"SubnetIds\": [\"<subnet-id1\>", \"<subnet-id2>\"], \<br />    \"SecurityGroupIds\": [\"<sg-1>\"]}"</pre> | 雲端架構師、雲端管理員 | 

### 建立和設定租戶角色
<a name="create-and-configure-tenant-roles"></a>


| 任務 | Description | 所需的技能 | 
| --- | --- | --- | 
| 建立租戶 IAM 角色。 | 執行 the AWS CLI [create-role](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/iam/create-role.html) 命令來建立兩個租用戶角色，用於測試搜尋功能：<pre>aws iam create-role \<br />  --role-name Tenant-1-role \<br />  --assume-role-policy-document file://assume-role-policy.json</pre><pre>aws iam create-role \<br />  --role-name Tenant-2-role \<br />  --assume-role-policy-document file://assume-role-policy.json</pre>檔案`assume-role-policy.json`是目前資料夾中的 JSON 文件，可將`AssumeRole`許可授予 Lambda 執行角色：<pre>{<br />    "Version": "2012-10-17",		 	 	 <br />    "Statement": [<br />        {<br />            "Effect": "Allow",<br />            "Principal": {<br />                 "AWS": "<Lambda execution role for index function>",<br />                 "AWS": "<Lambda execution role for search function>"<br />             },<br />            "Action": "sts:AssumeRole"<br />        }<br />    ]<br />}</pre> | 雲端架構師、雲端管理員 | 
| 建立租戶 IAM 政策。 | 執行 AWS CLI [createe-policy](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/iam/create-policy.html) 命令來建立租用戶政策，以授予對 Elasticsearch 操作的存取權：<pre>aws iam create-policy \<br />  --policy-name tenant-policy \<br />  --policy-document file://policy.json</pre>檔案`policy.json`是目前資料夾中的 JSON 文件，可授予 Elasticsearch 的許可：<pre>{<br />    "Version": "2012-10-17",		 	 	 <br />    "Statement": [<br />        {<br />            "Effect": "Allow",<br />            "Action": [<br />                "es:ESHttpDelete",<br />                "es:ESHttpGet",<br />                "es:ESHttpHead",<br />                "es:ESHttpPost",<br />                "es:ESHttpPut",<br />                "es:ESHttpPatch"<br />            ],<br />            "Resource": [<br />                "<ARN of Elasticsearch domain created earlier>"<br />            ]<br />        }<br />    ]<br />}</pre> | 雲端架構師、雲端管理員 | 
| 將租戶 IAM 政策連接至租戶角色。 | 執行 AWS CLI [attach-role-policy](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/iam/attach-role-policy.html) 命令，將租用戶 IAM 政策連接至您在先前步驟中建立的兩個租用戶角色：<pre>aws iam attach-role-policy \<br />  --policy-arn arn:aws:iam::account-id:policy/tenant-policy \<br />  --role-name Tenant-1-role<br /><br />aws iam attach-role-policy \<br />  --policy-arn arn:aws:iam::account-id:policy/tenant-policy \<br />  --role-name Tenant-2-role</pre>政策 ARN 來自上一個步驟的輸出。 | 雲端架構師、雲端管理員 | 
| 建立 IAM 政策，授予 Lambda 擔任角色的許可。 | 執行 the AWS CLI [create-policy](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/iam/create-policy.html) 命令，為 Lambda 建立政策以擔任租戶角色：<pre>aws iam create-policy \<br />  --policy-name assume-tenant-role-policy \<br />  --policy-document file://lambda_policy.json</pre>檔案`lambda_policy.json`是目前資料夾中的 JSON 文件，授予 許可`AssumeRole`：<pre>{<br />    "Version": "2012-10-17",		 	 	 <br />    "Statement": [<br />       {<br />            "Effect": "Allow",<br />            "Action":  "sts:AssumeRole",<br />            "Resource": "<ARN of tenant role created earlier>"<br />       }<br />    ]<br />}</pre>對於 `Resource`，您可以使用萬用字元來避免為每個租用戶建立新的政策。 | 雲端架構師、雲端管理員 | 
| 建立 IAM 政策，授予 Lambda 索引角色存取 Amazon S3 的許可。 | 執行 AWS CLI [createe-policy](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/iam/create-policy.html) 命令，授予 Lambda 索引角色存取 S3 儲存貯體中物件的許可：<pre>aws iam create-policy \<br />  --policy-name s3-permission-policy \<br />  --policy-document file://s3_lambda_policy.json</pre>檔案`s3_lambda_policy.json`是目前資料夾中的下列 JSON 政策文件：<pre>{<br />    "Version": "2012-10-17",		 	 	 <br />    "Statement": [<br />        {<br />            "Effect": "Allow",<br />            "Action": "s3:GetObject",<br />            "Resource": "arn:aws:s3:::tenantrawdata/*"<br />        }<br />    ]<br />}</pre> | 雲端架構師、雲端管理員 | 
| 將政策連接至 Lambda 執行角色。 | 執行 AWS CLI [attach-role-policy](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/iam/attach-role-policy.html) 命令，將上一個步驟中建立的政策連接至您先前建立的 Lambda 索引和搜尋執行角色：<pre>aws iam attach-role-policy \<br />  --policy-arn arn:aws:iam::account-id:policy/assume-tenant-role-policy \<br />  --role-name index-lambda-role<br /><br />aws iam attach-role-policy \<br />  --policy-arn arn:aws:iam::account-id:policy/assume-tenant-role-policy \<br />  --role-name search-lambda-role<br /><br />aws iam attach-role-policy \<br />  --policy-arn arn:aws:iam::account-id:policy/s3-permission-policy \<br />  --role-name index-lambda-role</pre>政策 ARN 來自上一個步驟的輸出。 | 雲端架構師、雲端管理員 | 

### 建立和設定搜尋 API
<a name="create-and-configure-a-search-api"></a>


| 任務 | Description | 所需的技能 | 
| --- | --- | --- | 
| 在 API Gateway 中建立 REST API。 | 執行 AWS CLI [create-rest-api](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/apigateway/create-rest-api.html) 命令來建立 REST API 資源：<pre>aws apigateway create-rest-api \<br />  --name Test-Api \<br />  --endpoint-configuration "{ \"types\": [\"REGIONAL\"] }"</pre>對於端點組態類型，您可以指定 `EDGE`，而不是`REGIONAL`使用節點，而不是特定節點 AWS 區域。請注意命令輸出中 `id` 欄位的值。這是您將在後續命令中使用的 API ID。 | 雲端架構師、雲端管理員 | 
| 建立搜尋 API 的資源。 | 搜尋 API 資源會以資源名稱 啟動 Lambda 搜尋函數`search`。（您不需要為 Lambda 索引函數建立 API，因為它會在物件上傳至 S3 儲存貯體時自動執行。)[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/build-a-multi-tenant-serverless-architecture-in-amazon-opensearch-service.html) | 雲端架構師、雲端管理員 | 
| 建立搜尋 API 的 GET 方法。 | 執行 AWS CLI [put-method](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/apigateway/put-method.html) 命令來建立搜尋 API `GET `的方法：<pre>aws apigateway put-method \<br />  --rest-api-id <API-ID> \<br />  --resource-id <ID from the previous command output> \<br />  --http-method GET \<br />  --authorization-type "NONE" \<br />  --no-api-key-required</pre>針對 `resource-id`，指定來自 `create-resource`命令輸出的 ID。 | 雲端架構師、雲端管理員 | 
| 建立搜尋 API 的方法回應。 | 執行 AWS CLI [put-method-response](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/apigateway/put-method-response.html) 命令，為搜尋 API 新增方法回應：<pre>aws apigateway put-method-response \<br />  --rest-api-id <API-ID> \<br />  --resource-id  <ID from the create-resource command output> \<br />  --http-method GET \<br />  --status-code 200 \<br />  --response-models "{\"application/json\": \"Empty\"}"</pre>針對 `resource-id`，指定先前`create-resource`命令輸出的 ID。 | 雲端架構師、雲端管理員 | 
| 設定搜尋 API 的代理 Lambda 整合。 | 執行 AWS CLI [put-integration](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/apigateway/put-integration.html) 命令來設定與 Lambda 搜尋函數的整合：<pre>aws apigateway put-integration \<br />  --rest-api-id <API-ID> \<br />  --resource-id  <ID from the create-resource command output> \<br />  --http-method GET \<br />  --type AWS_PROXY \<br />  --integration-http-method GET \<br />  --uri arn:aws:apigateway:region:lambda:path/2015-03-31/functions/arn:aws:lambda:<region>:<account-id>:function:<function-name>/invocations</pre>針對 `resource-id`，指定先前`create-resource`命令的 ID。 | 雲端架構師、雲端管理員 | 
| 授予 API Gateway 呼叫 Lambda 搜尋函數的許可。 | 執行 AWS CLI [add-permission](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/add-permission.html) 命令，給予 API Gateway 使用搜尋函數的許可：<pre>aws lambda add-permission \<br />  --function-name <function-name> \<br />  --statement-id apigateway-get \<br />  --action lambda:InvokeFunction \<br />  --principal apigateway.amazonaws.com \<br />  --source-arn "arn:aws:execute-api:<region>:<account-id>:api-id/*/GET/search</pre>如果您使用不同的 API 資源名稱而非 ，請變更`source-arn`路徑`search`。 | 雲端架構師、雲端管理員 | 
| 部署搜尋 API。 | 執行 the AWS CLI [create-deployment](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/apigateway/create-deployment.html) 命令來建立名為 的階段資源`dev`：<pre>aws apigateway create-deployment \<br />  --rest-api-id <API-ID> \<br />  --stage-name dev</pre>如果您更新 API，您可以使用相同的 AWS CLI 命令將其重新部署到相同的階段。 | 雲端架構師、雲端管理員 | 

### 建立和設定 Kibana 角色
<a name="create-and-configure-kibana-roles"></a>


| 任務 | Description | 所需的技能 | 
| --- | --- | --- | 
| 登入 Kibana 主控台。 | [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/build-a-multi-tenant-serverless-architecture-in-amazon-opensearch-service.html) | 雲端架構師、雲端管理員 | 
| 建立和設定 Kibana 角色。 | 若要提供資料隔離並確保一個租用戶無法擷取另一個租用戶的資料，您需要使用文件安全，這允許租用戶僅存取包含其租用戶 ID 的文件。[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/build-a-multi-tenant-serverless-architecture-in-amazon-opensearch-service.html) | 雲端架構師、雲端管理員 | 
| 將使用者映射至角色。 | [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/build-a-multi-tenant-serverless-architecture-in-amazon-opensearch-service.html)我們建議您在租戶加入時自動建立租戶和 Kibana 角色。 | 雲端架構師、雲端管理員 | 
| 建立租用戶資料索引。 | 在導覽窗格的**管理**下，選擇**開發工具**，然後執行下列命令。此命令會建立`tenant-data`索引來定義 `TenantId` 屬性的映射。<pre>PUT /tenant-data<br />{<br />  "mappings": {<br />    "properties": {<br />      "TenantId": { "type": "keyword"}<br />    }<br />  }<br />}</pre> | 雲端架構師、雲端管理員 | 

### 為 Amazon S3 和 建立 VPC 端點 AWS STS
<a name="create-vpc-endpoints-for-s3-and-sts"></a>


| 任務 | Description | 所需的技能 | 
| --- | --- | --- | 
| 為 Amazon S3 建立 VPC 端點。 | 執行 AWS CLI [create-vpc-endpoint](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/ec2/create-vpc-endpoint.html) 命令，為 Amazon S3 建立 VPC 端點。端點可讓 VPC 中的 Lambda 索引函數存取 Amazon S3。<pre>aws ec2 create-vpc-endpoint \<br />  --vpc-id <VPC-ID> \<br />  --service-name com.amazonaws.us-east-1.s3 \<br />  --route-table-ids <route-table-ID></pre>針對 `vpc-id`，指定您用於 Lambda 索引函數的 VPC。對於 `service-name`，請使用 Amazon S3 端點的正確 URL。針對 `route-table-ids`，指定與 VPC 端點相關聯的路由表。 | 雲端架構師、雲端管理員 | 
| 為 建立 VPC 端點 AWS STS。 | 執行 AWS CLI [create-vpc-endpoint](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/ec2/create-vpc-endpoint.html) 命令來建立 AWS Security Token Service () 的 VPC 端點AWS STS。端點可讓 VPC 中的 Lambda 索引和搜尋函數存取 AWS STS。函數在擔任 IAM 角色 AWS STS 時使用。<pre>aws ec2 create-vpc-endpoint \<br />  --vpc-id <VPC-ID> \<br />  --vpc-endpoint-type Interface \<br />  --service-name com.amazonaws.us-east-1.sts \<br />  --subnet-id <subnet-ID> \<br />  --security-group-id <security-group-ID></pre>針對 `vpc-id`，指定您用於 Lambda 索引和搜尋函數的 VPC。針對 `subnet-id`，提供應建立此端點的子網路。針對 `security-group-id`，指定要與此端點建立關聯的安全群組。（它可以與 Lambda 使用的安全群組相同。) | 雲端架構師、雲端管理員 | 

### 測試多租戶和資料隔離
<a name="test-multi-tenancy-and-data-isolation"></a>


| 任務 | Description | 所需的技能 | 
| --- | --- | --- | 
| 更新索引和搜尋函數的 Python 檔案。 | [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/build-a-multi-tenant-serverless-architecture-in-amazon-opensearch-service.html)您可以從 OpenSearch Service 主控台的**概觀**索引標籤取得 Elasticsearch 端點。 OpenSearch 其格式為 `<AWS-Region>.es.amazonaws.com`。 | 雲端架構師、應用程式開發人員 | 
| 更新 Lambda 程式碼。 | 使用 AWS CLI [update-function-code](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/update-function-code.html) 命令，使用您對 Python 檔案所做的變更來更新 Lambda 程式碼：<pre>aws lambda update-function-code \<br />  --function-name index-lambda-function \<br />  --zip-file fileb://index_lambda_package.zip<br /><br />aws lambda update-function-code \<br />  --function-name search-lambda-function \<br />  --zip-file fileb://search_lambda_package.zip</pre> | 雲端架構師、應用程式開發人員 | 
| 將原始資料上傳至 S3 儲存貯體。 | 使用 the AWS CLI [cp](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/s3/cp.html) 命令將Tenant-1 和Tenant-2 物件的資料上傳至儲存`tenantrawdata`貯體 （指定您為此目的建立的 S3 儲存貯體名稱）：<pre>aws s3 cp tenant-1-data s3://tenantrawdata<br />aws s3 cp tenant-2-data s3://tenantrawdata</pre>S3 儲存貯體設定為在上傳資料時執行 Lambda 索引函數，以便在 Elasticsearch 中編製文件索引。 | 雲端架構師、雲端管理員 | 
| 從 Kibana 主控台搜尋資料。 | 在 Kibana 主控台上執行下列查詢：<pre>GET tenant-data/_search</pre>此查詢會顯示在 Elasticsearch 中編製索引的所有文件。在此情況下，您應該會看到兩個單獨的Tenant-1 和Tenant-2 文件。 | 雲端架構師、雲端管理員 | 
| 從 API Gateway 測試搜尋 API。 | [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/build-a-multi-tenant-serverless-architecture-in-amazon-opensearch-service.html)如需畫面圖例，請參閱[其他資訊](#build-a-multi-tenant-serverless-architecture-in-amazon-opensearch-service-additional)一節。 | 雲端架構師、應用程式開發人員 | 
| 清除資源。 | 清除您建立的所有資源，以防止您的 帳戶產生額外費用。 | AWS DevOps、雲端架構師、雲端管理員 | 

## 相關資源
<a name="build-a-multi-tenant-serverless-architecture-in-amazon-opensearch-service-resources"></a>
+ [適用於 Python (Boto) 的 AWS SDK](https://aws.amazon.com/sdk-for-python/)
+ [AWS Lambda 文件](https://docs.aws.amazon.com/lambda/)
+ [API Gateway 文件](https://docs.aws.amazon.com/apigateway/)
+ [Amazon S3 文件](https://docs.aws.amazon.com/s3/)
+ [Amazon OpenSearch Service 文件](https://docs.aws.amazon.com/elasticsearch-service/)
  + [Amazon OpenSearch Service 中的精細存取控制](https://docs.amazonaws.cn/en_us/elasticsearch-service/latest/developerguide/fgac.html)
  + [使用 Amazon OpenSearch Service 建立搜尋應用程式](https://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/search-example.html)
  + [在 VPC 中啟動 Amazon OpenSearch Service 網域](https://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/es-vpc.html)

## 其他資訊
<a name="build-a-multi-tenant-serverless-architecture-in-amazon-opensearch-service-additional"></a>

**資料分割模型**

多租戶系統中使用三種常見的資料分割模型：孤立、集區和混合。您選擇的模型取決於您環境的合規、雜訊鄰近、操作和隔離需求。

*Silo 模型*

在孤島模型中，每個租用戶的資料會存放在不同的儲存區域中，其中不會混合租用戶資料。您可以使用兩種方法來使用 OpenSearch Service 實作孤立模型：每個租用戶的網域和每個租用戶的索引。
+ **每個租用戶的網域** – 您可以為每個租用戶使用單獨的 OpenSearch Service 網域 （與 Elasticsearch 叢集同義）。將每個租用戶放在自己的網域中，可提供與在獨立建構中擁有資料相關聯的所有優點。不過，這種方法帶來了管理和敏捷性的挑戰。其分散式性質使彙整和評估租戶的運作狀態和活動更加困難。這是一個昂貴的選項，要求每個 OpenSearch Service 網域至少擁有三個主節點和兩個資料節點供生產工作負載使用。

![\[多租用戶無伺服器架構的每個租用戶孤島模型的網域。\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/images/pattern-img/750196bb-03f6-4b6e-92cd-eb7141602547/images/c2195f82-e5ed-40bb-b76a-3b0210bf1254.png)


 
+ **每個租用戶的索引** – 您可以將租用戶資料放在 OpenSearch Service 叢集中的個別索引中。透過此方法，您可以在建立和命名索引時使用租用戶識別符，方法是在索引名稱前面加上租用戶識別符。每個租用戶的索引方法可協助您實現孤立目標，而無需為每個租用戶引入完全獨立的叢集。不過，如果索引數量增加，您可能會遇到記憶體壓力，因為這種方法需要更多的碎片，主節點必須處理更多的配置和重新平衡。

![\[多租用戶無伺服器架構的每個租用戶孤島模型索引。\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/images/pattern-img/750196bb-03f6-4b6e-92cd-eb7141602547/images/354a9463-25bb-422b-84de-d4875a7c8ea2.png)


 

**孤立模型中的隔離** – 在孤立模型中，您可以使用 IAM 政策來隔離存放每個租戶資料的網域或索引。這些政策可防止一個租用戶存取另一個租用戶的資料。若要實作孤立隔離模型，您可以建立以資源為基礎的政策，以控制對租戶資源的存取。這通常是網域存取政策，指定委託人可以在網域的子資源上執行的動作，包括 Elasticsearch 索引和 APIs。透過 IAM 身分型政策，您可以在 OpenSearch Service 中的網域、索引或 APIs上指定*允許**或拒絕*的動作。IAM 政策的 `Action`元素說明政策允許或拒絕的特定動作，而 `Principal `元素指定受影響的帳戶、使用者或角色。

下列範例政策僅授予Tenant-1 對`tenant-1`網域上子資源的完整存取權 （如 所指定`es:*`)。`Resource`元素`/*`中的結尾表示此政策適用於網域的子資源，而非網域本身。當此政策生效時，租用戶不得在現有網域上建立新的網域或修改設定。

```
{
   "Version": "2012-10-17",		 	 	 
   "Statement": [
      {
         "Effect": "Allow",
         "Principal": {
            "AWS": "arn:aws:iam::<aws-account-id>:user/Tenant-1"
         },
         "Action": "es:*",
         "Resource": "arn:aws:es:<Region>:<account-id>:domain/tenant-1/*"
      }
   ]
}
```

若要實作每個索引孤島模型的租用戶，您需要修改此範例政策，透過指定索引名稱，進一步將Tenant-1 限制為指定的索引或索引。下列範例政策會將Tenant-1 限制為`tenant-index-1`索引。 

```
{
   "Version": "2012-10-17",		 	 	 
   "Statement": [
      {
         "Effect": "Allow",
         "Principal": {
            "AWS": "arn:aws:iam::123456789012:user/Tenant-1"
         },
         "Action": "es:*",
         "Resource": "arn:aws:es:<Region>:<account-id>:domain/test-domain/tenant-index-1/*"
      }
   ]
}
```

*集區模型*

在集區模型中，所有租用戶資料都會存放在相同網域內的索引中。租用戶識別符包含在資料 （文件） 中，並用作分割區索引鍵，因此您可以判斷哪些資料屬於哪個租用戶。此模型可減少管理開銷。操作和管理集區索引比管理多個索引更簡單且更有效率。不過，由於租戶資料在相同索引中混合，您會失去孤立模型提供的自然租戶隔離。這種方法也可能會因為雜訊鄰近效果而降低效能。

![\[多租戶無伺服器架構的集區模型。\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/images/pattern-img/750196bb-03f6-4b6e-92cd-eb7141602547/images/c2c3bb0f-6ccd-47a7-ab67-e7f3f8c7f289.png)


 

**集區模型中的租戶隔離** – 一般而言，在集區模型中實作租戶隔離具有挑戰性。與孤立模型搭配使用的 IAM 機制不允許您根據存放在文件中的租用戶 ID 來描述隔離。

另一種方法是使用 Open Distro for Elasticsearch 提供的[精細存取控制 ](https://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/fgac.html)(FGAC) 支援。FGAC 可讓您在索引、文件或欄位層級控制許可。在每個請求中，FGAC 會評估使用者登入資料，並對使用者進行身分驗證或拒絕存取。如果 FGAC 驗證使用者，它會擷取對應至該使用者的所有角色，並使用完整的許可集來判斷如何處理請求。 

若要在集區模型中實現所需的隔離，您可以使用[文件層級安全性](https://opendistro.github.io/for-elasticsearch-docs/docs/security/access-control/document-level-security/)，這可讓您將角色限制為索引中的文件子集。下列範例角色會將查詢限制為Tenant-1。透過將此角色套用至Tenant-1，您可以實現必要的隔離。 

```
{
   "bool": {
     "must": {
       "match": {
         "tenantId": "Tenant-1"
       }
     }
   }
 }
```

*混合模型*

混合模型在相同環境中使用孤立和集區模型的組合，為每個租用戶層 （例如免費、標準和高級層） 提供獨特的體驗。每個層遵循與集區模型中使用的相同安全性描述檔。

 

![\[多租戶無伺服器架構的混合模型。\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/images/pattern-img/750196bb-03f6-4b6e-92cd-eb7141602547/images/e7def98a-38ef-435a-9881-7e95ae4d4940.png)


**混合模型中的租用戶隔離** – 在混合模型中，您遵循與集區模型相同的安全性設定檔，其中在文件層級使用 FGAC 安全模型提供租用戶隔離。雖然此策略可簡化叢集管理並提供敏捷性，但它會使架構的其他層面變得複雜。例如，您的程式碼需要額外的複雜性，才能判斷哪個模型與每個租用戶相關聯。您也必須確保單一租用戶查詢不會讓整個網域飽和，並降低其他租用戶的體驗。 

**在 API Gateway 中測試**

*Tenant-1 查詢的測試時段*

![\[Tenant-1 查詢的測試時段。\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/images/pattern-img/750196bb-03f6-4b6e-92cd-eb7141602547/images/a6757d3f-977a-4ecc-90cb-83ab7f1c3588.png)


*Tenant-2 查詢的測試時段*

 

![\[Tenant-2 查詢的測試時段。\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/images/pattern-img/750196bb-03f6-4b6e-92cd-eb7141602547/images/31bfd656-33ca-4750-b6e6-da4d703c2071.png)


## 附件
<a name="attachments-750196bb-03f6-4b6e-92cd-eb7141602547"></a>

若要存取與本文件相關聯的其他內容，請解壓縮下列檔案： [attachment.zip](samples/p-attach/750196bb-03f6-4b6e-92cd-eb7141602547/attachments/attachment.zip)

# 使用 AWS CDK 搭配 TypeScript 部署多堆疊應用程式
<a name="deploy-multiple-stack-applications-using-aws-cdk-with-typescript"></a>

*Rahul Sharad Gaikwad 醫生，Amazon Web Services*

## 總結
<a name="deploy-multiple-stack-applications-using-aws-cdk-with-typescript-summary"></a>

此模式提供step-by-step方法。 TypeScript 例如， 模式會部署無伺服器即時分析應用程式。

模式會建置和部署巢狀堆疊應用程式。父 AWS CloudFormation 堆疊會呼叫子堆疊或巢狀堆疊。 每個子堆疊都會建置和部署 CloudFormation 堆疊中定義的 AWS 資源。AWS CDK Toolkit 是命令列界面 (CLI) 命令 `cdk`，是 CloudFormation 堆疊的主要界面。

## 先決條件和限制
<a name="deploy-multiple-stack-applications-using-aws-cdk-with-typescript-prereqs"></a>

**先決條件**
+ 作用中的 AWS 帳戶
+ 現有的虛擬私有雲端 (VPC) 和子網路
+ 安裝並設定 AWS CDK Toolkit
+ 具有管理員許可和一組存取金鑰的使用者。
+ Node.js
+ AWS 命令列界面 (AWS CLI)

**限制**
+ 由於 AWS CDK 使用 AWS CloudFormation，AWS CDK 應用程式受限於 CloudFormation 服務配額。如需詳細資訊，請參閱 [AWS CloudFormation 配額](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cloudformation-limits.html)。

**產品版本**

此模式已使用下列工具和版本建置和測試。
+ AWS CDK Toolkit 1.83.0
+ Node.js 14.13.0
+ npm 7.0.14

模式應適用於任何版本的 AWS CDK 或 npm。請注意，Node.js 13.0.0 到 13.6.0 版與 AWS CDK 不相容。

## Architecture
<a name="deploy-multiple-stack-applications-using-aws-cdk-with-typescript-architecture"></a>

**目標技術堆疊**
+ AWS Amplify 主控台
+ Amazon API Gateway
+ AWS CDK
+ Amazon CloudFront
+ Amazon Cognito
+ Amazon DynamoDB
+ Amazon Data Firehose
+ Amazon Kinesis Data Streams
+ AWS Lambda
+ Amazon Simple Storage Service (Amazon S3)

**目標架構**

下圖顯示使用 AWS CDK 搭配 TypeScript 的多堆疊應用程式部署。

![\[VPC 中的堆疊架構，具有父堆疊和兩個包含資源的子堆疊。\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/images/pattern-img/0ac29a11-1362-4084-92ed-6b85205763ca/images/8f92e86a-aa3d-4f8a-9b11-b92c52a7226c.png)


 

下圖顯示範例無伺服器即時應用程式的架構。

![\[區域中的應用程式架構。\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/images/pattern-img/0ac29a11-1362-4084-92ed-6b85205763ca/images/2df00faf-f871-4aec-9655-19ba2eb14cf8.png)


 

## 工具
<a name="deploy-multiple-stack-applications-using-aws-cdk-with-typescript-tools"></a>

**工具**
+ [AWS Amplify 主控台](https://docs.aws.amazon.com/amplify/latest/userguide/welcome.html)是 AWS 中完全堆疊 Web 和行動應用程式部署的控制中心。Amplify 主控台託管提供以 git 為基礎的工作流程，用於託管具有持續部署的完整堆疊無伺服器 Web 應用程式。Admin UI 是前端 Web 和行動開發人員的視覺化界面，可在 AWS 主控台外部建立和管理應用程式後端。
+ [Amazon API Gateway](https://docs.aws.amazon.com/apigateway/latest/developerguide/welcome.html) 是一種 AWS 服務，可用於建立、發佈、維護、監控和保護任何規模的 REST、HTTP 和 WebSocket APIs。
+ [AWS 雲端開發套件 (AWS CDK)](https://docs.aws.amazon.com/cdk/latest/guide/home.html) 是一種軟體開發架構，可協助您在程式碼中定義和佈建 AWS 雲端基礎設施。
+ [AWS CDK Toolkit](https://docs.aws.amazon.com/cdk/latest/guide/cli.html) 是命令列雲端開發套件，可協助您與 AWS CDK 應用程式互動。CLI `cdk` 命令是與您的 AWS CDK 應用程式互動的主要工具。它會執行您的應用程式、查詢您定義的應用程式模型，以及產生和部署由 AWS CDK 產生的 AWS CloudFormation 範本。
+ [Amazon CloudFront](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/Introduction.html) 是一種 Web 服務，可加速靜態和動態 Web 內容的分佈，例如 .html、.css、.js 和映像檔案。CloudFront 透過稱為節點的全球資料中心網路提供內容，以降低延遲並改善效能。
+ [Amazon Cognito](https://docs.aws.amazon.com/cognito/latest/developerguide/what-is-amazon-cognito.html) 為您的 Web 和行動應用程式提供身分驗證、授權和使用者管理。您的使用者可以直接或透過第三方登入。
+ [Amazon DynamoDB](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Introduction.html) 是全受管的 NoSQL 資料庫服務，可提供快速且可預測的效能和無縫的可擴展性。
+ [Amazon Data Firehose](https://docs.aws.amazon.com/firehose/latest/dev/what-is-this-service.html) 是一項全受管服務，可將即時[串流資料](https://aws.amazon.com/streaming-data/)交付至目的地，例如 Amazon S3、Amazon Redshift、Amazon OpenSearch Service、Splunk，以及受支援的第三方服務供應商擁有的任何自訂 HTTP 端點或 HTTP 端點。
+ [Amazon Kinesis Data Streams](https://docs.aws.amazon.com/streams/latest/dev/introduction.html) 是一項服務，可即時收集和處理大型資料記錄串流。
+ [AWS Lambda](https://docs.aws.amazon.com/lambda/latest/dg/welcome.html) 是一種運算服務，支援執行程式碼，無需佈建或管理伺服器。Lambda 只有在需要時才會執行程式碼，可自動從每天數項請求擴展成每秒數千項請求。只需為使用的運算時間支付費用，一旦未執行程式碼，就會停止計費。
+ [Amazon Simple Storage Service (Amazon S3)](https://docs.aws.amazon.com/AmazonS3/latest/userguide/Welcome.html) 是一種雲端型物件儲存服務，可協助您儲存、保護和擷取任何數量的資料。

**Code**

此模式的程式碼已連接。

## 史詩
<a name="deploy-multiple-stack-applications-using-aws-cdk-with-typescript-epics"></a>

### 安裝 AWS CDK Toolkit
<a name="install-aws-cdk-toolkit"></a>


| 任務 | Description | 所需的技能 | 
| --- | --- | --- | 
| 安裝 AWS CDK Toolkit。 | 若要全域安裝 AWS CDK Toolkit，請執行下列命令。`npm install -g aws-cdk` | DevOps | 
| 驗證版本。 | 若要驗證 AWS CDK Toolkit 版本，請執行下列命令。 `cdk --version` | DevOps | 

### 設定 AWS 登入資料
<a name="set-up-aws-credentials"></a>


| 任務 | Description | 所需的技能 | 
| --- | --- | --- | 
| 設定登入資料。 | 若要設定登入資料，請執行 `aws configure`命令並依照提示操作。<pre>$aws configure<br />AWS Access Key ID [None]: <br />AWS Secret Access Key [None]: your_secret_access_key<br />Default region name [None]:<br />Default output format [None]:</pre> | DevOps | 

### 下載專案程式碼
<a name="download-the-project-code"></a>


| 任務 | Description | 所需的技能 | 
| --- | --- | --- | 
| 下載連接的專案程式碼。 | 如需 目錄和檔案結構的詳細資訊，請參閱*其他資訊*一節。 | DevOps | 

### 引導 AWS CDK 環境
<a name="bootstrap-the-aws-cdk-environment"></a>


| 任務 | Description | 所需的技能 | 
| --- | --- | --- | 
| 引導環境。 | 若要將 AWS CloudFormation 範本部署到您要使用的帳戶和 AWS 區域，請執行下列命令。`cdk bootstrap <account>/<Region>`如需詳細資訊，請參閱 [AWS 文件](https://docs.aws.amazon.com/cdk/latest/guide/bootstrapping.html)。 | DevOps | 

### 建置和部署專案
<a name="build-and-deploy-the-project"></a>


| 任務 | Description | 所需的技能 | 
| --- | --- | --- | 
| 建置專案。 | 若要建置專案程式碼，請執行 `npm run build`命令。 | DevOps | 
| 部署專案。 | 若要部署專案程式碼，請執行 `cdk deploy`命令。 |  | 

### 驗證輸出
<a name="verify-outputs"></a>


| 任務 | Description | 所需的技能 | 
| --- | --- | --- | 
| 驗證堆疊建立。 | 在 AWS 管理主控台上，選擇 **CloudFormation**。在專案的堆疊中，確認已建立父堆疊和兩個子堆疊。 | DevOps | 

### 測試應用程式。
<a name="test-the-application"></a>


| 任務 | Description | 所需的技能 | 
| --- | --- | --- | 
| 將資料傳送至 Kinesis Data Streams。 | 設定您的 AWS 帳戶，使用 Amazon Kinesis Data Generator (KDG) 將資料傳送至 Kinesis Data Streams。如需詳細資訊，請參閱 [Amazon Kinesis Data Generator](https://awslabs.github.io/amazon-kinesis-data-generator/web/help.html)。 | DevOps | 
| 建立 Amazon Cognito 使用者。 | 若要建立 Amazon Cognito 使用者，請從 [Kinesis Data Generator 說明頁面上](https://awslabs.github.io/amazon-kinesis-data-generator/web/help.html)*的建立 Amazon Cognito 使用者*區段下載 cognito-setup.json CloudFormation 範本。啟動範本，然後輸入您的 Amazon Cognito **使用者名稱和密碼******。**Outputs** 索引標籤會列出 Kinesis Data Generator URL。 | DevOps | 
| 登入 Kinesis Data Generator | 若要登入 KDG，請使用您提供的 Amazon Cognito 登入資料和 Kinesis Data Generator URL。 | DevOps | 
| 測試應用程式。 | 在 KDG 的記錄**範本****範本 1 **中，從*其他資訊*區段貼上測試碼，然後選擇**傳送資料**。 | DevOps | 
| 測試 API Gateway。 | 擷取資料之後，請使用 `GET`方法來擷取資料，以測試 API Gateway。 | DevOps | 

## 相關資源
<a name="deploy-multiple-stack-applications-using-aws-cdk-with-typescript-resources"></a>

**參考**
+ [AWS 雲端開發套件](https://aws.amazon.com/cdk/)
+ [GitHub 上的 AWS CDK](https://github.com/aws/aws-cdk)
+ [使用巢狀堆疊](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-nested-stacks.html)
+ [AWS 範例 - 無伺服器即時分析](https://github.com/aws-samples/serverless-realtime-analytics)

## 其他資訊
<a name="deploy-multiple-stack-applications-using-aws-cdk-with-typescript-additional"></a>

**目錄和檔案詳細資訊**

此模式會設定下列三個堆疊。
+ `parent-cdk-stack.ts` – 此堆疊做為父堆疊，並呼叫兩個子應用程式做為巢狀堆疊。 
+ `real-time-analytics-poc-stack.ts` – 此巢狀堆疊包含基礎設施和應用程式程式碼。
+ `real-time-analytics-web-stack.ts` – 此巢狀堆疊僅包含靜態 Web 應用程式程式碼。

*重要檔案及其功能*
+ `bin/real-time-analytics-poc.ts` – AWS CDK 應用程式的進入點。它會載入 下定義的所有堆疊`lib/`。
+ `lib/real-time-analytics-poc-stack.ts` – AWS CDK 應用程式堆疊的定義 (`real-time-analytics-poc`)。
+ `lib/real-time-analytics-web-stack.ts` – AWS CDK 應用程式堆疊的定義 (`real-time-analytics-web-stack`)。
+ `lib/parent-cdk-stack.ts` – AWS CDK 應用程式堆疊的定義 (`parent-cdk`)。
+ `package.json` – npm 模組資訊清單，其中包含應用程式名稱、版本和相依性。
+ `package-lock.json` – 由 npm 維護。
+ `cdk.json` – 用於執行應用程式的 工具組。
+ `tsconfig.json` – 專案的 TypeScript 組態。
+ `.gitignore` – Git 應從來源控制中排除的檔案清單。
+ `node_modules` – 由 npm 維護；包括專案的相依性。

父堆疊中的下一節程式碼會將子應用程式稱為巢狀 AWS CDK 堆疊。

```
import * as cdk from '@aws-cdk/core';
import { Construct, Stack, StackProps } from '@aws-cdk/core';
import { RealTimeAnalyticsPocStack } from './real-time-analytics-poc-stack';
import { RealTimeAnalyticsWebStack } from './real-time-analytics-web-stack';


export class CdkParentStack extends Stack {
  constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);


    new RealTimeAnalyticsPocStack(this, 'RealTimeAnalyticsPocStack');
    new RealTimeAnalyticsWebStack(this, 'RealTimeAnalyticsWebStack');
  }
}
```

**用於測試的程式碼**

```
session={{date.now('YYYYMMDD')}}|sequence={{date.now('x')}}|reception={{date.now('x')}}|instrument={{random.number(9)}}|l={{random.number(20)}}|price_0={{random.number({"min":10000, "max":30000})}}|price_1={{random.number({"min":10000, "max":30000})}}|price_2={{random.number({"min":10000, "max":30000})}}|price_3={{random.number({"min":10000, "max":30000})}}|price_4={{random.number({"min":10000, "max":30000})}}|price_5={{random.number({"min":10000, "max":30000})}}|price_6={{random.number({"min":10000, "max":30000})}}|price_7={{random.number({"min":10000, "max":30000})}}|price_8={{random.number({"min":10000, "max":30000})}}|
```

**測試 API Gateway**

在 API Gateway 主控台上，使用 `GET`方法測試 API Gateway。

![\[在 OPTIONS 下選擇具有 GET 的 API Gateway 主控台。\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/images/pattern-img/0ac29a11-1362-4084-92ed-6b85205763ca/images/452e5b8f-6d61-401d-8484-e5a436cb6f1b.png)


 

## 附件
<a name="attachments-0ac29a11-1362-4084-92ed-6b85205763ca"></a>

若要存取與本文件相關聯的其他內容，請解壓縮下列檔案： [attachment.zip](samples/p-attach/0ac29a11-1362-4084-92ed-6b85205763ca/attachments/attachment.zip)

# 使用 AWS SAM 自動化巢狀應用程式的部署
<a name="automate-deployment-of-nested-applications-using-aws-sam"></a>

*Rahul Sharad Gaikwad 醫生、Ishwar Chauthaiwale、Dmitry Gulin 和 Tabby Ward，Amazon Web Services*

## 總結
<a name="automate-deployment-of-nested-applications-using-aws-sam-summary"></a>

在 Amazon Web Services (AWS) 上，AWS Serverless Application Model (AWS SAM) 是一種開放原始碼架構，提供速記語法來表達函數、APIs、資料庫和事件來源映射。只要為每個資源幾行，您就可以定義所需的應用程式，並使用 YAML 建立模型。在部署期間，SAM 會將 SAM 語法轉換並擴展為 AWS CloudFormation 語法，您可以用來更快速地建置無伺服器應用程式。

AWS SAM 可簡化 AWS 平台上無伺服器應用程式的開發、部署和管理。它提供標準化架構、更快速的部署、本機測試功能、資源管理、與 開發工具的無縫整合，以及支援社群。這些功能使其成為有效建置無伺服器應用程式的寶貴工具。

此模式使用 AWS SAM 範本來自動化巢狀應用程式的部署。巢狀應用程式是另一個應用程式中的應用程式。父應用程式會呼叫其子應用程式。這些是無伺服器架構鬆散耦合的元件。 

使用巢狀應用程式，您可以重複使用獨立撰寫和維護但使用 AWS SAM 和 Serverless Application Repository 組成的服務或元件，快速建置高度複雜的無伺服器架構。巢狀應用程式可協助您建置功能更強大的應用程式，避免重複的工作，並確保團隊和組織的一致性和最佳實務。為了示範巢狀應用程式， 模式會部署[範例 AWS 無伺服器購物車應用程式](https://github.com/aws-samples/aws-sam-nested-stack-sample)。

## 先決條件和限制
<a name="automate-deployment-of-nested-applications-using-aws-sam-prereqs"></a>

**先決條件**
+ 作用中的 AWS 帳戶
+ 現有的虛擬私有雲端 (VPC) 和子網路
+ 整合的開發環境，例如 Visual Studio Code （如需詳細資訊，請參閱[在 AWS 上建置的工具](https://aws.amazon.com/getting-started/tools-sdks/#IDE_and_IDE_Toolkits))
+ 如果尚未安裝 Python wheel 程式庫，請使用 pip 安裝 wheel 安裝

**限制**
+ 可在無伺服器應用程式中巢狀化的應用程式數量上限為 200。
+ 巢狀應用程式的參數數目上限可以有 60 個。

**產品版本**
+ 此解決方案建置在 AWS SAM 命令列界面 (AWS SAM CLI) 1.21.1 版上，但此架構應與更新的 AWS SAM CLI 版本搭配使用。

## Architecture
<a name="automate-deployment-of-nested-applications-using-aws-sam-architecture"></a>

**目標技術堆疊**
+ Amazon API Gateway
+ AWS SAM
+ Amazon Cognito
+ Amazon DynamoDB
+ AWS Lambda
+ Amazon Simple Queue Service (Amazon SQS) 佇列

**目標架構**

下圖顯示使用者如何透過呼叫 APIs 向購物服務提出請求。使用者的請求，包括所有必要的資訊，會傳送至 Amazon API Gateway 和 Amazon Cognito 授權方，該授權方會執行 APIs 的身分驗證和授權機制。

在 DynamoDB 中新增、刪除或更新項目時，會將事件放入 DynamoDB Streams，進而啟動 Lambda 函數。為了避免在同步工作流程中立即刪除舊項目，訊息會放入 SQS 佇列，這會啟動工作者函數來刪除訊息。

![\[從 API Gateway 到 Lambda 函數到 DynamoDB 和產品服務的 POST 和 PUT 操作。\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/images/pattern-img/218adecc-b5b8-4193-9012-b5d584e2e128/images/5b454bae-5fd4-405d-a37d-6bafc3fcf889.png)


在此解決方案設定中，AWS SAM CLI 做為 AWS CloudFormation 堆疊的界面。AWS SAM 範本會自動部署巢狀應用程式。父 SAM 範本會呼叫子範本，而父 CloudFormation 堆疊會部署子堆疊。每個子堆疊都會建置 AWS SAM CloudFormation 範本中定義的 AWS 資源。

![\[使用 AWS SAM CLI 搭配父系和三個子系 CloudFormation 堆疊的四步驟程序。\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/images/pattern-img/218adecc-b5b8-4193-9012-b5d584e2e128/images/5828026e-72ad-4a3f-a5f2-bffac0f13e42.png)


1. 建置和部署堆疊。

1. Auth CloudFormation 堆疊包含 Amazon Cognito。

1. 產品 CloudFormation 堆疊包含 Lambda 函數和 Amazon API Gateway

1. 購物 CloudFormation 堆疊包含 Lambda 函數、Amazon API Gateway、SQS 佇列和 Amazon DynamoDB 資料庫。

## 工具
<a name="automate-deployment-of-nested-applications-using-aws-sam-tools"></a>

**工具**
+ [Amazon API Gateway](https://docs.aws.amazon.com/apigateway/latest/developerguide/welcome.html) 可協助您建立、發佈、維護、監控和保護任何規模的 REST、HTTP 和 WebSocket APIs。
+ [AWS CloudFormation](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/Welcome.html) 可協助您設定 AWS 資源、快速且一致地佈建資源，以及在 AWS 帳戶和區域的整個生命週期中管理這些資源。
+ [Amazon Cognito](https://docs.aws.amazon.com/cognito/latest/developerguide/what-is-amazon-cognito.html) 為 Web 和行動應用程式提供身分驗證、授權和使用者管理。
+ [Amazon DynamoDB](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Introduction.html) 是一項全受管 NoSQL 資料庫服務，可提供快速、可預期且可擴展的效能。
+ [AWS Lambda](https://docs.aws.amazon.com/lambda/latest/dg/welcome.html) 是一種運算服務，可協助您執行程式碼，而無需佈建或管理伺服器。它只會在需要時執行程式碼並自動擴展，因此您只需按使用的運算時間付費。
+ [AWS Serverless Application Model (AWS SAM)](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/what-is-sam.html) 是一種開放原始碼架構，可協助您在 AWS 雲端中建置無伺服器應用程式。
+ [Amazon Simple Queue Service (Amazon SQS)](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/welcome.html) 提供安全、耐用且可用的託管佇列，可協助您整合和分離分散式軟體系統和元件。

**Code**

此模式的程式碼可在 GitHub [AWS SAM 巢狀堆疊範例](https://github.com/aws-samples/aws-sam-nested-stack-sample)儲存庫中使用。

## 史詩
<a name="automate-deployment-of-nested-applications-using-aws-sam-epics"></a>

### 安裝 AWS SAM CLI
<a name="install-aws-sam-cli"></a>


| 任務 | Description | 所需的技能 | 
| --- | --- | --- | 
| 安裝 AWS SAM CLI。 | 若要安裝 AWS SAM CLI，請參閱 [AWS SAM 文件](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html)中的說明。 | DevOps 工程師 | 
| 設定 AWS 登入資料。 | 若要設定 AWS 登入資料，讓 AWS SAM CLI 可以代表您呼叫 AWS 服務，請執行 `aws configure`命令並依照提示操作。<pre>$aws configure<br />AWS Access Key ID [None]: <your_access_key_id><br />AWS Secret Access Key [None]: your_secret_access_key<br />Default region name [None]:<br />Default output format [None]:</pre>如需設定登入資料的詳細資訊，請參閱[身分驗證和存取登入資料](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-authentication.html)。 | DevOps 工程師 | 

### 初始化 AWS SAM 專案
<a name="initialize-the-aws-sam-project"></a>


| 任務 | Description | 所需的技能 | 
| --- | --- | --- | 
| 複製 AWS SAM 程式碼儲存庫。 | [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/automate-deployment-of-nested-applications-using-aws-sam.html) | DevOps 工程師 | 
| 部署 範本以初始化專案。 | 若要初始化專案，請執行 `SAM init`命令。當系統提示您選擇範本來源時，請選擇 `Custom Template Location`。 | DevOps 工程師 | 

### 編譯和建置 SAM 範本程式碼
<a name="compile-and-build-the-sam-template-code"></a>


| 任務 | Description | 所需的技能 | 
| --- | --- | --- | 
| 檢閱 AWS SAM 應用程式範本。 | 檢閱巢狀應用程式的範本。此範例使用以下巢狀應用程式範本：[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/automate-deployment-of-nested-applications-using-aws-sam.html) | DevOps 工程師 | 
| 檢閱父範本。 | 檢閱將調用巢狀應用程式範本的範本。在此範例中，父範本為 `template.yml`。所有個別的應用程式都會巢狀在單一父範本 中`template.yml`。 | DevOps 工程師 | 
| 編譯並建置 AWS SAM 範本程式碼。 | 使用 AWS SAM CLI，執行下列命令。<pre>sam build</pre> | DevOps 工程師 | 

### 部署 AWS SAM 範本
<a name="deploy-the-aws-sam-template"></a>


| 任務 | Description | 所需的技能 | 
| --- | --- | --- | 
| 部署應用程式。 | 若要啟動建立巢狀應用程式 CloudFormation 堆疊並在 AWS 環境中部署程式碼的 SAM 範本程式碼，請執行下列命令。<pre>sam deploy --guided --stack-name shopping-cart-nested-stack --capabilities CAPABILITY_IAM CAPABILITY_AUTO_EXPAND</pre>命令將提示幾個問題。使用 回答所有問題`y`。 | DevOps 工程師 | 

### 驗證部署
<a name="verify-the-deployment"></a>


| 任務 | Description | 所需的技能 | 
| --- | --- | --- | 
| 驗證堆疊。 | 若要檢閱 AWS CloudFormation 範本中定義的 AWS CloudFormation 堆疊和 AWS 資源，請執行下列動作：[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/automate-deployment-of-nested-applications-using-aws-sam.html) | DevOps 工程師 | 

## 相關資源
<a name="automate-deployment-of-nested-applications-using-aws-sam-resources"></a>

**參考**
+ [AWS Serverless 應用程式模型 (AWS SAM)](https://aws.amazon.com/serverless/sam/#:~:text=The%20AWS%20Serverless%20Application%20Model,and%20model%20it%20using%20YAML.)
+ [GitHub 上的 AWS SAM](https://github.com/aws/serverless-application-model)
+ [無伺服器購物車微服務](https://github.com/aws-samples/aws-serverless-shopping-cart) (AWS 範例應用程式）

**教學課程和影片**
+ [建置無伺服器應用程式](https://youtu.be/Hv3YrP8G4ag)
+ [AWS Online Tech Talks：使用 AWS SAM 進行無伺服器應用程式建置和部署](https://youtu.be/1NU7vyJw9LU)

## 其他資訊
<a name="automate-deployment-of-nested-applications-using-aws-sam-additional"></a>

所有程式碼都就緒後，範例會有下列目錄結構：
+ [sam\$1stacks](https://docs.aws.amazon.com/lambda/latest/dg/chapter-layers.html) – 此資料夾包含 `shared.py` layer。layer 是檔案封存，其中包含程式庫、自訂執行時間或其他相依性。透過 layer，您可以在函數中使用程式庫，而無需將其包含在部署套件中。
+ *product-mock-service* – 此資料夾包含所有產品相關的 Lambda 函數和檔案。
+ *shopping-cart-service* – 此資料夾包含所有與購物相關的 Lambda 函數和檔案。

# 使用 AWS Lambda 字符販賣機實作 Amazon S3 的 SaaS 租用戶隔離
<a name="implement-saas-tenant-isolation-for-amazon-s3-by-using-an-aws-lambda-token-vending-machine"></a>

*Tabby Ward、Thomas Davis 和 Sravan Periyathambi，Amazon Web Services*

## 總結
<a name="implement-saas-tenant-isolation-for-amazon-s3-by-using-an-aws-lambda-token-vending-machine-summary"></a>

多租戶 SaaS 應用程式必須實作系統，以確保維持租戶隔離。當您將租戶資料存放在相同的 AWS 資源時，例如當多個租戶將資料存放在相同的 Amazon Simple Storage Service (Amazon S3) 儲存貯體時，您必須確保跨租戶存取不會發生。字符販賣機 (TVMs) 是提供租戶資料隔離的一種方式。這些機器提供一種機制來取得權杖，同時抽象化這些權杖產生方式的複雜性。開發人員可以使用 TVM，而無需詳細了解其如何產生字符。

此模式使用 實作 TVM AWS Lambda。TVM 會產生權杖，其中包含臨時安全權杖服務 (STS) 憑證，以限制對 S3 儲存貯體中單一 SaaS 租用戶資料的存取。

TVMs和此模式提供的程式碼通常用於衍生自 JSON Web Token (JWTs) 的宣告，以將 AWS 資源請求與租用戶範圍 AWS Identity and Access Management (IAM) 政策建立關聯。您可以使用此模式中的程式碼做為實作 SaaS 應用程式的基礎，該應用程式會根據 JWT 權杖中提供的宣告產生範圍廣泛的暫時 STS 憑證。

## 先決條件和限制
<a name="implement-saas-tenant-isolation-for-amazon-s3-by-using-an-aws-lambda-token-vending-machine-prereqs"></a>

**先決條件**
+ 作用中 AWS 帳戶。
+ AWS Command Line Interface (AWS CLI) [1.19.0 版或更新版本](https://docs.aws.amazon.com/cli/latest/userguide/install-cliv1.html)，在 macOS、Linux 或 Windows 上安裝和設定。或者，您可以使用 AWS CLI [2.1 版或更新版本。](https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html)

**限制**
+ 此程式碼在 Java 中執行，目前不支援其他程式設計語言。 
+ 範例應用程式不包含 AWS 跨區域或災難復原 (DR) 支援。 
+ 此模式示範適用於 SaaS 應用程式的 Lambda TVM 如何提供範圍租用戶存取。此模式不適用於生產環境，如果在特定應用程式或使用案例中沒有額外的安全測試。

## Architecture
<a name="implement-saas-tenant-isolation-for-amazon-s3-by-using-an-aws-lambda-token-vending-machine-architecture"></a>

**目標技術堆疊**
+ AWS Lambda
+ Amazon S3
+ IAM
+ AWS Security Token Service (AWS STS)

**目標架構**

![\[產生權杖以取得臨時 STS 登入資料，以存取 S3 儲存貯體中的資料。\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/images/pattern-img/97a34c8e-d04e-40b6-acbf-1baa176d22a9/images/14d0508a-703b-4229-85e6-c5094de7fe01.png)


 

## 工具
<a name="implement-saas-tenant-isolation-for-amazon-s3-by-using-an-aws-lambda-token-vending-machine-tools"></a>

**AWS 服務**
+ [AWS Command Line Interface (AWS CLI)](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-welcome.html) 是一種開放原始碼工具，可協助您 AWS 服務 透過命令列 shell 中的命令與 互動。
+ [AWS Identity and Access Management (IAM)](https://docs.aws.amazon.com/IAM/latest/UserGuide/introduction.html) 透過控制已驗證並獲授權使用的人員，協助您安全地管理對 AWS 資源的存取。
+ [AWS Lambda](https://docs.aws.amazon.com/lambda/latest/dg/welcome.html) 是一項運算服務，可協助您執行程式碼，無需佈建或管理伺服器。它只會在需要時執行程式碼並自動擴展，因此您只需支付使用的運算時間。
+ [AWS Security Token Service (AWS STS)](https://docs.aws.amazon.com/STS/latest/APIReference/welcome.html) 可協助您為使用者請求暫時、有限權限的登入資料。
+ [Amazon Simple Storage Service (Amazon S3)](https://docs.aws.amazon.com/AmazonS3/latest/userguide/Welcome.html) 是一種雲端型物件儲存服務，可協助您儲存、保護和擷取任何數量的資料。

**Code**

此模式的原始碼可做為附件使用，並包含下列檔案：
+ `s3UploadSample.jar` 提供 Lambda 函數的原始碼，可將 JSON 文件上傳至 S3 儲存貯體。
+ `tvm-layer.zip` 提供可重複使用的 Java 程式庫，可為 Lambda 函數提供權杖 (STS 臨時登入資料），以存取 S3 儲存貯體並上傳 JSON 文件。
+ `token-vending-machine-sample-app.zip` 提供用來建立這些成品和編譯指示的原始碼。

若要使用這些檔案，請遵循下一節中的指示。

## 史詩
<a name="implement-saas-tenant-isolation-for-amazon-s3-by-using-an-aws-lambda-token-vending-machine-epics"></a>

### 判斷變數值
<a name="determine-variable-values"></a>


| 任務 | Description | 所需的技能 | 
| --- | --- | --- | 
| 判斷變數值。 | 此模式的實作包含數個必須一致使用的變數名稱。決定應該用於每個變數的值，並在後續步驟中請求時提供該值。[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/implement-saas-tenant-isolation-for-amazon-s3-by-using-an-aws-lambda-token-vending-machine.html) | 雲端管理員 | 

### 建立 S3 儲存貯體
<a name="create-an-s3-bucket"></a>


| 任務 | Description | 所需的技能 | 
| --- | --- | --- | 
| 為範例應用程式建立 S3 儲存貯體。 | 使用下列 AWS CLI 命令來建立 S3 儲存貯體。在程式碼片段中提供 `<sample-app-bucket-name>`****值：<pre>aws s3api create-bucket --bucket <sample-app-bucket-name></pre>Lambda 範例應用程式會將 JSON 檔案上傳至此儲存貯體。 | 雲端管理員 | 

### 建立 IAM TVM 角色和政策
<a name="create-the-iam-tvm-role-and-policy"></a>


| 任務 | Description | 所需的技能 | 
| --- | --- | --- | 
| 建立 TVM 角色。 | 使用下列其中一個 AWS CLI 命令來建立 IAM 角色。在 命令中提供 `<sample-tvm-role-name>`****值。對於 macOSor Linux shell：<pre>aws iam create-role \<br />--role-name <sample-tvm-role-name> \<br />--assume-role-policy-document '{<br />    "Version": "2012-10-17",		 	 	 <br />    "Statement": [<br />        {<br />            "Effect": "Allow",<br />            "Action": [<br />                "sts:AssumeRole"<br />            ],<br />            "Principal": {<br />                "Service": [<br />                    "lambda.amazonaws.com"<br />                ]<br />            },<br />            "Condition": {<br />                "StringEquals": {<br />                    "aws:SourceAccount": "<AWS Account ID>"<br />                }<br />            }<br />        }<br />    ]<br />}'</pre>對於 Windows 命令列：<pre>aws iam create-role ^<br />--role-name <sample-tvm-role-name> ^<br />--assume-role-policy-document "{\"Version\": \"2012-10-17\", \"Statement\": [{\"Effect\": \"Allow\", \"Action\": [\"sts:AssumeRole\"], \"Principal\": {\"Service\": [\"lambda.amazonaws.com\"]}, \"Condition\": {\"StringEquals\": {\"aws:SourceAccount\": \"<AWS Account ID>\"}}}]}"</pre>Lambda 範例應用程式會在叫用應用程式時擔任此角色。使用範圍政策擔任應用程式角色的功能為程式碼提供更廣泛存取 S3 儲存貯體的許可。 | 雲端管理員 | 
| 建立內嵌 TVM 角色政策。 | 使用下列其中一個 AWS CLI 命令來建立 IAM 政策。在命令中提供 `<sample-tvm-role-name>`****`<AWS Account ID>`、 和 `<sample-app-role-name>`值。對於 macOS 或 Linux shell：<pre>aws iam put-role-policy \<br />--role-name <sample-tvm-role-name> \<br />--policy-name assume-app-role \<br />--policy-document '{<br />    "Version": "2012-10-17",		 	 	  <br />    "Statement": [<br />        {<br />            "Effect": "Allow", <br />            "Action": "sts:AssumeRole", <br />            "Resource": "arn:aws:iam::<AWS Account ID>:role/<sample-app-role-name>"<br />        }<br />    ]}'</pre>對於 Windows 命令列：<pre>aws iam put-role-policy ^<br />--role-name <sample-tvm-role-name> ^<br />--policy-name assume-app-role ^<br />--policy-document "{\"Version\": \"2012-10-17\", \"Statement\": [{\"Effect\": \"Allow\", \"Action\": \"sts:AssumeRole\", \"Resource\": \"arn:aws:iam::<AWS Account ID>:role/<sample-app-role-name>\"}]}"</pre>此政策會連接到 TVM 角色。它為程式碼提供擔任應用程式角色的能力，其具有更廣泛存取 S3 儲存貯體的許可。 | 雲端管理員 | 
| 連接 受管 Lambda 政策。 | 使用下列 AWS CLI 命令來連接`AWSLambdaBasicExecutionRole` IAM 政策。在 命令中提供 `<sample-tvm-role-name>`值：<pre>aws iam attach-role-policy \<br />--role-name <sample-tvm-role-name> \<br />--policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole</pre>對於 Windows 命令列：<pre>aws iam attach-role-policy ^<br />--role-name <sample-tvm-role-name> ^<br />--policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole</pre>此受管政策會連接至 TVM 角色，以允許 Lambda 將日誌傳送至 Amazon CloudWatch。 | 雲端管理員 | 

### 建立 IAM 應用程式角色和政策
<a name="create-the-iam-application-role-and-policy"></a>


| 任務 | Description | 所需的技能 | 
| --- | --- | --- | 
| 建立應用程式角色。 | 使用下列其中一個 AWS CLI 命令來建立 IAM 角色。在 命令中提供 `<AWS Account ID>`、 `<sample-app-role-name>`和 `<sample-tvm-role-name>`值。對於 macOS 或 Linux shell：<pre>aws iam create-role \<br />--role-name <sample-app-role-name> \<br />--assume-role-policy-document '{<br />    "Version": "2012-10-17",		 	 	  <br />    "Statement": [<br />        {<br />            "Effect": <br />            "Allow",<br />            "Principal": {<br />                "AWS": "arn:aws:iam::<AWS Account ID>:role/<sample-tvm-role-name>"<br />            },<br />            "Action": "sts:AssumeRole"<br />        }<br />    ]}'</pre>對於 Windows 命令列：<pre>aws iam create-role ^<br />--role-name <sample-app-role-name> ^<br />--assume-role-policy-document "{\"Version\": \"2012-10-17\", \"Statement\": [{\"Effect\": \"Allow\",\"Principal\": {\"AWS\": \"arn:aws:iam::<AWS Account ID>:role/<sample-tvm-role-name>\"},\"Action\": \"sts:AssumeRole\"}]}"</pre>Lambda 範例應用程式會使用範圍政策擔任此角色，以取得 S3 儲存貯體的租戶型存取權。 | 雲端管理員 | 
| 建立內嵌應用程式角色政策。 | 使用下列其中一個 AWS CLI mmands 來建立 IAM 政策。在 命令中提供 `<sample-app-role-name>`和 `<sample-app-bucket-name>`****值。對於 macOS 或 Linux shell：<pre>aws iam put-role-policy \<br />--role-name <sample-app-role-name> \<br />--policy-name s3-bucket-access \<br />--policy-document '{<br />    "Version": "2012-10-17",		 	 	  <br />    "Statement": [<br />        {<br />            "Effect": "Allow", <br />            "Action": [<br />                "s3:PutObject", <br />                "s3:GetObject", <br />                "s3:DeleteObject"<br />            ], <br />            "Resource": "arn:aws:s3:::<sample-app-bucket-name>/*"<br />        }, <br />        {<br />            "Effect": "Allow", <br />            "Action": ["s3:ListBucket"], <br />            "Resource": "arn:aws:s3:::<sample-app-bucket-name>"<br />        }<br />    ]}'</pre>對於 Windows 命令列：<pre>aws iam put-role-policy ^<br />--role-name <sample-app-role-name> ^<br />--policy-name s3-bucket-access ^<br />--policy-document "{\"Version\": \"2012-10-17\", \"Statement\": [{\"Effect\": \"Allow\", \"Action\": [\"s3:PutObject\", \"s3:GetObject\", \"s3:DeleteObject\"], \"Resource\": \"arn:aws:s3:::<sample-app-bucket-name>/*\"}, {\"Effect\": \"Allow\", \"Action\": [\"s3:ListBucket\"], \"Resource\": \"arn:aws:s3:::<sample-app-bucket-name>\"}]}"</pre>此政策會連接至應用程式角色。它提供對 S3 儲存貯體中物件的廣泛存取。當範例應用程式擔任角色時，這些許可的範圍會限定為具有 TVM 動態產生政策的特定租用戶。 | 雲端管理員 | 

### 使用 TVM 建立 Lambda 範例應用程式
<a name="create-the-lam-sample-application-with-tvm"></a>


| 任務 | Description | 所需的技能 | 
| --- | --- | --- | 
| 下載編譯的來源檔案。 | 下載 `s3UploadSample.jar`和 `tvm-layer.zip`****檔案，其中包含為附件。中提供了用於建立這些成品和編譯函數的原始程式碼`token-vending-machine-sample-app.zip`。 | 雲端管理員 | 
| 建立 Lambda 層。 | 使用下列 AWS CLI 命令來建立 Lambda 層，讓 Lambda 可存取 TVM。 如果您不是從下載的位置執行此命令` tvm-layer.zip`，請在 `--zip-file`參數`tvm-layer.zip`中提供正確的路徑。 <pre>aws lambda publish-layer-version \<br />--layer-name sample-token-vending-machine \<br />--compatible-runtimes java11 \<br />--zip-file fileb://tvm-layer.zip</pre>對於 Windows 命令列：<pre>aws lambda publish-layer-version ^<br />--layer-name sample-token-vending-machine ^<br />--compatible-runtimes java11 ^<br />--zip-file fileb://tvm-layer.zip</pre>此命令會建立包含可重複使用 TVM 程式庫的 Lambda 層。 | 雲端管理員、應用程式開發人員 | 
| 建立 Lambda 函數。 | 使用下列 AWS CLI 命令來建立 Lambda 函數。在命令中提供 `<sample-app-function-name>`、`<AWS Account ID>`、`<sample-app-bucket-name>`、、 `<AWS Region>` `<sample-tvm-role-name>`和 `<sample-app-role-name>`值。 如果您不是從下載 的位置執行此命令`s3UploadSample.jar`，請在 `--zip-file`參數`s3UploadSample.jar`中提供正確的路徑。 <pre>aws lambda create-function \<br />--function-name <sample-app-function-name>  \<br />--timeout 30 \<br />--memory-size 256 \<br />--runtime java11 \<br />--role arn:aws:iam::<AWS Account ID>:role/<sample-tvm-role-name> \<br />--handler com.amazon.aws.s3UploadSample.App \<br />--zip-file fileb://s3UploadSample.jar \<br />--layers arn:aws:lambda:<AWS Region>:<AWS Account ID>:layer:sample-token-vending-machine:1 \<br />--environment "Variables={S3_BUCKET=<sample-app-bucket-name>,<br />ROLE=arn:aws:iam::<AWS Account ID>:role/<sample-app-role-name>}"</pre>對於 Windows 命令列：<pre>aws lambda create-function ^<br />--function-name <sample-app-function-name>  ^<br />--timeout 30 ^<br />--memory-size 256 ^<br />--runtime java11 ^<br />--role arn:aws:iam::<AWS Account ID>:role/<sample-tvm-role-name> ^<br />--handler com.amazon.aws.s3UploadSample.App ^<br />--zip-file fileb://s3UploadSample.jar ^<br />--layers arn:aws:lambda:<AWS Region>:<AWS Account ID>:layer:sample-token-vending-machine:1 ^<br />--environment "Variables={S3_BUCKET=<sample-app-bucket-name>,ROLE=arn:aws:iam::<AWS Account ID>:role/<sample-app-role-name>}"</pre>此命令會建立連接範例應用程式程式碼和 TVM layer 的 Lambda 函數。它也會設定兩個環境變數： `S3_BUCKET`和 `ROLE`。範例應用程式使用這些變數來決定要擔任的角色，以及要上傳 JSON 文件的 S3 儲存貯體。 | 雲端管理員、應用程式開發人員 | 

### 測試範例應用程式和 TVM
<a name="test-the-sample-application-and-tvm"></a>


| 任務 | Description | 所需的技能 | 
| --- | --- | --- | 
| 叫用 Lambda 範例應用程式。 | 使用下列其中一個 AWS CLI 命令，以其預期的承載啟動 Lambda 範例應用程式。在 命令中提供 `<sample-app-function-name>`和 `<sample-tenant-name>`值。對於 macOS 和 Linux shell：<pre>aws lambda invoke \<br />--function <sample-app-function-name> \<br />--invocation-type RequestResponse \<br />--payload '{"tenant": "<sample-tenant-name>"}' \<br />--cli-binary-format raw-in-base64-out response.json</pre>對於 Windows 命令列：<pre>aws lambda invoke ^<br />--function <sample-app-function-name> ^<br />--invocation-type RequestResponse ^<br />--payload "{\"tenant\": \"<sample-tenant-name>\"}" ^<br />--cli-binary-format raw-in-base64-out response.json</pre>此命令會呼叫 Lambda 函數，並在`response.json`文件中傳回結果。在許多以 Unix 為基礎的系統上，您可以將 `response.json` 變更為 `/dev/stdout`，直接將結果輸出到您的 shell，而無需建立另一個檔案。 變更此 Lambda 函數後續調用中的`<sample-tenant-name>`值會變更 JSON 文件的位置，以及字符提供的許可。 | 雲端管理員、應用程式開發人員 | 
| 檢視 S3 儲存貯體以查看建立的物件。 | 瀏覽至您先前建立的 S3 儲存貯體 (`<sample-app-bucket-name>`)。此儲存貯體包含值為 的 S3 物件字首`<sample-tenant-name>`。在此字首下，您會找到名為 且具有 UUID 的 JSON 文件。多次叫用範例應用程式會新增更多 JSON 文件。 | 雲端管理員 | 
| 在 CloudWatch Logs 中檢視範例應用程式的日誌。 | 檢視與 CloudWatch Logs `<sample-app-function-name>`中名為 的 Lambda 函數相關聯的日誌。如需說明，請參閱 [Lambda 文件中的將 Lambda 函數日誌傳送至 CloudWatch Logs](https://docs.aws.amazon.com/lambda/latest/dg/monitoring-cloudwatchlogs.html)。您可以在這些日誌中檢視 TVM 產生的租戶範圍政策。此租用戶範圍政策將範例應用程式的許可授予 Amazon S3 **PutObject**、**GetObject**、**DeleteObject** 和 **ListBucket** APIs，但僅適用於與 相關聯的物件字首`<sample-tenant-name>`。在範例應用程式的後續調用中，如果您變更 `<sample-tenant-name>`，TVM 會更新範圍政策，以對應調用承載中提供的租用戶。此動態產生的政策顯示如何在 SaaS 應用程式中使用 TVM 維護租戶範圍存取。 TVM 功能是在 Lambda 層中提供，因此可以連接到應用程式使用的其他 Lambda 函數，而不必複寫程式碼。如需動態產生政策的圖例，請參閱[其他資訊](#implement-saas-tenant-isolation-for-amazon-s3-by-using-an-aws-lambda-token-vending-machine-additional)一節。 | 雲端管理員 | 

## 相關資源
<a name="implement-saas-tenant-isolation-for-amazon-s3-by-using-an-aws-lambda-token-vending-machine-resources"></a>
+ [使用動態產生的 IAM 政策隔離租用戶](https://aws.amazon.com/blogs/apn/isolating-saas-tenants-with-dynamically-generated-iam-policies/) （部落格文章）
+ [在 SaaS 環境中套用動態產生的隔離政策 ](https://aws.amazon.com/blogs/apn/applying-dynamically-generated-isolation-policies-in-saas-environments/)（部落格文章）
+ [上的 SaaS AWS](https://aws.amazon.com/saas/)

## 其他資訊
<a name="implement-saas-tenant-isolation-for-amazon-s3-by-using-an-aws-lambda-token-vending-machine-additional"></a>

以下日誌顯示此模式中 TVM 程式碼產生的動態產生政策。在此螢幕擷取畫面中， `<sample-app-bucket-name>`是`DOC-EXAMPLE-BUCKET` ，而 `<sample-tenant-name>`是 `test-tenant-1`。此範圍政策傳回的 STS 登入資料無法在 S3 儲存貯體中的物件上執行任何動作，但與物件金鑰字首 相關聯的物件除外`test-tenant-1`。

![\[日誌顯示由 TVM 程式碼產生的動態產生政策。\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/images/pattern-img/97a34c8e-d04e-40b6-acbf-1baa176d22a9/images/d4776ebe-fb8f-41ac-b8c5-b4f97a821c8c.png)


## 附件
<a name="attachments-97a34c8e-d04e-40b6-acbf-1baa176d22a9"></a>

若要存取與本文件相關聯的其他內容，請解壓縮下列檔案： [attachment.zip](samples/p-attach/97a34c8e-d04e-40b6-acbf-1baa176d22a9/attachments/attachment.zip)

# 使用 AWS Step Functions 實作無伺服器 saga 模式
<a name="implement-the-serverless-saga-pattern-by-using-aws-step-functions"></a>

*Tabby Ward、Joe Kern 和 Rohan Mehta，Amazon Web Services*

## 摘要
<a name="implement-the-serverless-saga-pattern-by-using-aws-step-functions-summary"></a>

在微服務架構中，主要目標是建置解耦的獨立元件，以提升應用程式的敏捷性、彈性和更快的上市時間。由於解耦，每個微服務元件都有自己的資料持久性層。在分散式架構中，商業交易可以跨越多個微服務。由於這些微服務無法使用單一原子性、一致性、隔離性、耐久性 (ACID) 交易，因此您可能會最終產生部分交易。在此情況下，需要一些控制邏輯才能復原已處理的交易。分散式 saga 模式通常用於此目的。 

saga 模式是一種故障管理模式，可協助在分散式應用程式中建立一致性，並協調多個微服務之間的交易，以維持資料一致性。當您使用 saga 模式時，每個執行交易的服務都會發佈事件，觸發後續服務在鏈結中執行下一個交易。這會持續到鏈結中的最後一個交易完成為止。如果商業交易失敗，saga 會協調一系列補償交易，復原先前交易所做的變更。

此模式示範如何使用 AWS Step Functions、AWS Lambda 和 Amazon DynamoDB 等無伺服器技術，自動設定和部署範例應用程式 （處理行程保留）。範例應用程式也會使用 Amazon API Gateway 和 Amazon Simple Notification Service (Amazon SNS) 來實作 saga 執行協調器。模式可以使用基礎設施即程式碼 (IaC) 架構進行部署，例如 AWS Cloud Development Kit (AWS CDK)、AWS Serverless Application Model (AWS SAM) 或 Terraform。

## 先決條件和限制
<a name="implement-the-serverless-saga-pattern-by-using-aws-step-functions-prereqs"></a>

**先決條件**
+ 作用中的 AWS 帳戶
+ 建立 AWS CloudFormation 堆疊的許可。如需詳細資訊，請參閱 CloudFormation 文件中的[控制存取](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-iam-template.html)。
+ 使用 AWS 帳戶設定您選擇的 IaC 架構 (AWS CDK、AWS SAM 或 Terraform)，以便您可以使用架構 CLI 部署應用程式。
+ NodeJS，用於建置應用程式並在本機執行。
+ 您選擇的程式碼編輯器 （例如 Visual Studio Code、Sublime 或 Atom)。

**產品版本**
+ [NodeJS 第 14 版](https://nodejs.org/en/download/)
+ [AWS CDK 2.37.1 版](https://docs.aws.amazon.com/cdk/v2/guide/getting_started.html#getting_started_install)
+ [AWS SAM 1.71.0 版](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/install-sam-cli.html)
+ [Terraform 1.3.7 版](https://developer.hashicorp.com/terraform/tutorials/aws-get-started/install-cli)

**限制**

事件來源是在微服務架構中實作 saga 協同運作模式的一種自然方式，其中所有元件都鬆散耦合，彼此沒有直接知識。如果您的交易涉及少量步驟 （三到五個），則 Saga 模式可能非常適合。不過，複雜度會隨著微服務數量和步驟數量而增加。 

當您使用此設計時，測試和偵錯可能會變得困難，因為您必須執行所有服務才能模擬交易模式。

## Architecture
<a name="implement-the-serverless-saga-pattern-by-using-aws-step-functions-architecture"></a>

**目標架構 **

提議的架構使用 AWS Step Functions 建置類似模式來預訂航班、預訂租車，以及處理假期的付款。

下列工作流程圖說明行程保留系統的典型流程。工作流程包含預留航空旅程 ("ReserveFlight")、預留車輛 ("ReserveCarRental")、處理付款 ("ProcessPayment")、確認航班保留 ("ConfirmFlight")，以及確認租車 ("ConfirmCarRental")，隨後在這些步驟完成時會收到成功通知。不過，如果系統在執行任何這些交易時遇到任何錯誤，就會開始向後失敗。例如，付款處理 ("ProcessPayment") 的錯誤會觸發退款 ("RefundPayment")，然後觸發租車和航班 ("CancelRentalReservation" 和 "CancelFlightReservation") 的取消，以失敗訊息結束整個交易。

此模式會針對圖表中反白顯示的每個任務部署個別的 Lambda 函數，以及三個用於航班、租車和付款的 DynamoDB 資料表。每個 Lambda 函數都會建立、更新或刪除個別 DynamoDB 資料表中的資料列，視交易是否確認或復原而定。模式使用 Amazon SNS 傳送文字 (SMS) 訊息給訂閱者，通知他們交易失敗或成功。 

![\[根據 saga 模式的旅遊保留系統工作流程。\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/images/pattern-img/fec0789c-d9b1-4d80-b179-dd9a7ecbec07/images/daad3e8e-6e6b-41c2-95c1-ca79d53ead64.png)


 

**自動化和擴展**

您可以使用其中一個 IaC 架構來建立此架構的組態。將下列其中一個連結用於您偏好的 IaC。
+ [使用 AWS CDK 部署](https://serverlessland.com/workflows/saga-pattern-cdk)
+ [使用 AWS SAM 部署](https://serverlessland.com/workflows/saga-pattern-sam)
+ [使用 Terraform 部署](https://serverlessland.com/workflows/saga-pattern-tf)

## 工具
<a name="implement-the-serverless-saga-pattern-by-using-aws-step-functions-tools"></a>

**AWS 服務**
+ [AWS Step Functions](https://aws.amazon.com/step-functions/) 是一種無伺服器協同運作服務，可讓您結合 AWS Lambda 函數和其他 AWS 服務來建置業務關鍵應用程式。透過 Step Functions 圖形主控台，您會將應用程式的工作流程視為一系列的事件驅動步驟。
+ [Amazon DynamoDB](https://aws.amazon.com/dynamodb/) 是全受管的 NoSQL 資料庫服務，可提供快速且可預測的效能和無縫的可擴展性。您可以使用 DynamoDB 建立資料庫資料表，藉此存放和擷取任意數量的資料，並為任何層級的請求流量提供服務。
+ [AWS Lambda](https://aws.amazon.com/lambda/) 是一種運算服務，可讓您執行程式碼，而無需佈建或管理伺服器。Lambda 只有在需要時才會執行程式碼，可自動從每天數項請求擴展成每秒數千項請求。
+ [Amazon API Gateway](https://aws.amazon.com/api-gateway/) 是一種 AWS 服務，可用於建立、發佈、維護、監控和保護任何規模的 REST、HTTP 和 WebSocket APIs。
+ [Amazon Simple Notification Service (Amazon SNS)](https://aws.amazon.com/sns/) 是一種受管服務，可將訊息從發佈者交付給訂閱者。
+ [AWS Cloud Development Kit (AWS CDK)](https://aws.amazon.com/cdk/) 是一種軟體開發架構，可透過使用 TypeScript、JavaScript、Python、Java 和 C\$1/ 等熟悉的程式設計語言來定義您的雲端應用程式資源。淨額。
+ [AWS Serverless Application Model (AWS SAM)](https://aws.amazon.com/serverless/sam/) 是用於建置無伺服器應用程式的開放原始碼架構。它提供速記語法來表達函數、APIs、資料庫和事件來源映射。

**Code**

您可以在以下連結中找到示範 saga 模式的範例應用程式的程式碼，包括 IaC 範本 (AWS CDK、AWS SAM 或 Terraform)、Lambda 函數和 DynamoDB 資料表。請遵循第一個 epic 中的指示來安裝這些項目。
+ [使用 AWS CDK 部署](https://serverlessland.com/workflows/saga-pattern-cdk)
+ [使用 AWS SAM 部署](https://serverlessland.com/workflows/saga-pattern-sam)
+ [使用 Terraform 部署](https://serverlessland.com/workflows/saga-pattern-tf)

## 史詩
<a name="implement-the-serverless-saga-pattern-by-using-aws-step-functions-epics"></a>

### 安裝套件、編譯和建置
<a name="install-packages-compile-and-build"></a>


| 任務 | Description | 所需的技能 | 
| --- | --- | --- | 
| 安裝 NPM 套件。 | 建立新的目錄、導覽至終端機中的該目錄，並從此模式稍早的*程式碼*區段複製您選擇的 GitHub 儲存庫。在具有 `package.json` 檔案的根資料夾中，執行下列命令來下載並安裝所有 Node Package Manager (NPM) 套件：<pre>npm install</pre> | 開發人員、雲端架構師 | 
| 編譯指令碼。 | 在根資料夾中，執行下列命令，指示 TypeScript 轉換器建立所有必要的 JavaScript 檔案：<pre>npm run build</pre> | 開發人員、雲端架構師 | 
| 留意變更並重新編譯。 | 在根資料夾中，在不同的終端機視窗中執行下列命令，以 監看程式碼變更，並在偵測到變更時編譯程式碼：<pre>npm run watch</pre> | 開發人員、雲端架構師 | 
| 執行單位測試 （僅限 AWS CDK)。 | 如果您使用的是 AWS CDK，請在根資料夾中執行下列命令來執行 Jest 單位測試：<pre>npm run test</pre> | 開發人員、雲端架構師 | 

### 將資源部署到目標 AWS 帳戶
<a name="deploy-resources-to-the-target-aws-account"></a>


| 任務 | Description | 所需的技能 | 
| --- | --- | --- | 
| 將示範堆疊部署至 AWS。 | 應用程式與 AWS 區域無關。如果您使用設定檔，則必須在 [AWS Command Line Interface (AWS CLI) 設定檔](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html)中或透過 [AWS CLI 環境變數明確宣告區域。](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-envvars.html)在根資料夾中，執行下列命令來建立部署組件，並將其部署到預設的 AWS 帳戶和區域。AWS CDK：<pre>cdk bootstrap<br />cdk deploy</pre>AWS SAM：<pre>sam build<br />sam deploy --guided</pre>Terraform：<pre>terraform init<br />terraform apply</pre>此步驟可能需要幾分鐘的時間才能完成。此命令使用為 AWS CLI 設定的預設登入資料。請注意，在部署完成後，主控台上顯示的 API Gateway URL。您需要此資訊來測試 saga 執行流程。 | 開發人員、雲端架構師 | 
| 比較已部署的堆疊與目前狀態。 | 在根資料夾中，執行下列命令，在變更原始碼之後，將部署的堆疊與目前狀態 進行比較：AWS CDK：<pre>cdk diff</pre>AWS SAM：<pre>sam deploy</pre>Terraform：<pre>terraform plan</pre> | 開發人員、雲端架構師 | 

### 測試執行流程
<a name="test-the-execution-flow"></a>


| 任務 | Description | 所需的技能 | 
| --- | --- | --- | 
| 測試 saga 執行流程。 | 當您部署堆疊時，導覽至您在先前步驟中記下的 API Gateway URL。此 URL 會觸發狀態機器啟動。如需如何透過傳遞不同的 URL 參數來操作狀態機器流程的詳細資訊，請參閱[其他資訊](#implement-the-serverless-saga-pattern-by-using-aws-step-functions-additional)一節。若要 檢視結果，請登入 AWS 管理主控台，然後導覽至 Step Functions 主控台。在這裡，您可以看到 saga 狀態機器的每個步驟。您也可以檢視 DynamoDB 資料表，以查看插入、更新或刪除的記錄。如果您經常重新整理畫面，您可以觀看交易狀態從 變更為 `pending` `confirmed`。 您可以訂閱 SNS 主題，方法是使用手機號碼更新 `stateMachine.ts` 檔案中的程式碼，以便在成功或失敗的保留時接收簡訊。如需詳細資訊，請參閱[其他資訊](#implement-the-serverless-saga-pattern-by-using-aws-step-functions-additional)區段中的 *Amazon SNS*。 | 開發人員、雲端架構師 | 

### 清除
<a name="clean-up"></a>


| 任務 | Description | 所需的技能 | 
| --- | --- | --- | 
| 清除資源。 | 若要清除為此應用程式部署的資源，您可以使用下列其中一個命令。AWS CDK：<pre>cdk destroy</pre>AWS SAM：<pre>sam delete</pre>Terraform：<pre>terraform destroy</pre> | 應用程式開發人員、雲端架構師 | 

## 相關資源
<a name="implement-the-serverless-saga-pattern-by-using-aws-step-functions-resources"></a>

**技術論文**
+ [在 AWS 上實作微服務](https://docs.aws.amazon.com/pdfs/whitepapers/latest/microservices-on-aws/microservices-on-aws.pdf)
+ [無伺服器應用程式鏡頭](https://docs.aws.amazon.com/wellarchitected/latest/serverless-applications-lens/welcome.html)

**AWS 服務文件**
+ [AWS CDK 入門](https://docs.aws.amazon.com/cdk/latest/guide/getting_started.html)
+ [AWS SAM 入門](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-getting-started.html)
+ [AWS Step Functions](https://docs.aws.amazon.com/step-functions/)
+ [Amazon DynamoDB](https://docs.aws.amazon.com/dynamodb/)
+ [AWS Lambda](https://docs.aws.amazon.com/lambda/)
+ [Amazon API Gateway](https://docs.aws.amazon.com/apigateway/)
+ [Amazon SNS](https://docs.aws.amazon.com/sns/)

**教學課程**
+ [無伺服器運算實作研討會](https://aws.amazon.com/serverless-workshops/)

## 其他資訊
<a name="implement-the-serverless-saga-pattern-by-using-aws-step-functions-additional"></a>

**Code**

為了測試目的，此模式會部署 API Gateway 和測試 Lambda 函數，以觸發 Step Functions 狀態機器。使用 Step Functions，您可以透過傳遞`run_type`參數來模擬 "ReserveFlight"、"ReserveCarRental"、"ProcessPayment"、"ConfirmFlight" 和 "ConfirmCarRental."

`saga` Lambda 函數 (`sagaLambda.ts`) 會從 API Gateway URL 中的查詢參數取得輸入，建立下列 JSON 物件，並將其傳遞給 Step Functions 執行：

```
let input = {
"trip_id": tripID, //  value taken from query parameter, default is AWS request ID
"depart_city": "Detroit",
"depart_time": "2021-07-07T06:00:00.000Z",
"arrive_city": "Frankfurt",
"arrive_time": "2021-07-09T08:00:00.000Z",
"rental": "BMW",
"rental_from": "2021-07-09T00:00:00.000Z",
"rental_to": "2021-07-17T00:00:00.000Z",
"run_type": runType // value taken from query parameter, default is "success"
};
```

您可以傳遞下列 URL 參數來實驗 Step Functions 狀態機器的不同流程：
+ **成功執行** ─ https：//\$1api 閘道 url\$1
+ **預留航班失敗** - https：//\$1api 閘道 url\$1？**runType=failFlightsReservation**
+ **確認航班失敗** - https：//\$1api 閘道 url\$1？**runType=failFlightsConfirmation**
+ **預留租車失敗** - https：//\$1api 閘道 url\$1？**runType=failCarRentalReservation**
+ **確認租車失敗** - https：//\$1api 閘道 url\$1？**runType=failCarRentalConfirmation**
+ **處理付款失敗** - https：//\$1api 閘道 url\$1？**runType=failPayment**
+ **傳遞行程 ID** - https：//\$1api 閘道 url\$1？**tripID=**\$1預設情況下，行程 ID 將是 AWS 請求 ID\$1

**IaC 範本**

連結的儲存庫包含 IaC 範本，可用來建立整個範例行程保留應用程式。
+ [使用 AWS CDK 部署](https://serverlessland.com/workflows/saga-pattern-cdk)
+ [使用 AWS SAM 部署](https://serverlessland.com/workflows/saga-pattern-sam)
+ [使用 Terraform 部署](https://serverlessland.com/workflows/saga-pattern-tf)

**DynamoDB 資料表**

以下是航班、租車和付款資料表的資料模型。

```
Flight Data Model:
 var params = {
      TableName: process.env.TABLE_NAME,
      Item: {
        'pk' : {S: event.trip_id},
        'sk' : {S: flightReservationID},
        'trip_id' : {S: event.trip_id},
        'id': {S: flightReservationID},
        'depart_city' : {S: event.depart_city},
        'depart_time': {S: event.depart_time},
        'arrive_city': {S: event.arrive_city},
        'arrive_time': {S: event.arrive_time},
        'transaction_status': {S: 'pending'}
      }
    };

Car Rental Data Model:
var params = {
      TableName: process.env.TABLE_NAME,
      Item: {
        'pk' : {S: event.trip_id},
        'sk' : {S: carRentalReservationID},
        'trip_id' : {S: event.trip_id},
        'id': {S: carRentalReservationID},
        'rental': {S: event.rental},
        'rental_from': {S: event.rental_from},
        'rental_to': {S: event.rental_to},
        'transaction_status': {S: 'pending'}
      }
    };

Payment Data Model:
var params = {
      TableName: process.env.TABLE_NAME,
      Item: {
        'pk' : {S: event.trip_id},
        'sk' : {S: paymentID},
        'trip_id' : {S: event.trip_id},
        'id': {S: paymentID},
        'amount': {S: "750.00"}, // hard coded for simplicity as implementing any monetary transaction functionality is beyond the scope of this pattern
        'currency': {S: "USD"},
        'transaction_status': {S: "confirmed"}
      }
    };
```

**Lambda 函數**

將建立下列函數，以支援 Step Functions 中的狀態機器流程和執行：
+ **預留航班**：使用 `transaction_status`的 將記錄插入 DynamoDB 航班資料表`pending`，以預訂航班。
+ **確認航班**：更新 DynamoDB 航班資料表中的記錄，將 `transaction_status`設定為 `confirmed`，以確認航班。
+ **取消航班保留**：從 DynamoDB 航班資料表刪除記錄，以取消待定航班。
+ **預留租車**：使用 `transaction_status`的 將記錄插入 DynamoDB CarRentals 資料表`pending`，以預訂租車。
+ **確認租車**：更新 DynamoDB CarRentals 資料表中的記錄，將 `transaction_status`設定為 `confirmed`，以確認租車。
+ **取消租車保留：**從 DynamoDB CarRentals 資料表刪除記錄，以取消待定的租車。
+ **處理付款**：將記錄插入 DynamoDB 付款資料表以進行付款。
+ **取消付款**：從 DynamoDB 付款資料表中刪除付款的記錄。

**Amazon SNS**

範例應用程式會建立下列主題和訂閱來傳送簡訊，並通知客戶保留成功或失敗。如果您想要在測試範例應用程式時接收文字訊息，請在狀態機器定義檔案中使用有效的電話號碼更新簡訊訂閱。

AWS CDK 程式碼片段 （在下列程式碼的第二行中新增電話號碼）：

```
const topic = new  sns.Topic(this, 'Topic');
topic.addSubscription(new subscriptions.SmsSubscription('+11111111111'));
const snsNotificationFailure = new tasks.SnsPublish(this ,'SendingSMSFailure', {
topic:topic,
integrationPattern: sfn.IntegrationPattern.REQUEST_RESPONSE,
message: sfn.TaskInput.fromText('Your Travel Reservation Failed'),
});
 
const snsNotificationSuccess = new tasks.SnsPublish(this ,'SendingSMSSuccess', {
topic:topic,
integrationPattern: sfn.IntegrationPattern.REQUEST_RESPONSE,
message: sfn.TaskInput.fromText('Your Travel Reservation is Successful'),
});
```

AWS SAM 程式碼片段 （將`+1111111111`字串取代為您的有效電話號碼）：

```
  StateMachineTopic11111111111:
    Type: 'AWS::SNS::Subscription'
    Properties:
      Protocol: sms
      TopicArn:
        Ref: StateMachineTopic
      Endpoint: '+11111111111'
    Metadata:
      'aws:sam:path': SamServerlessSagaStack/StateMachine/Topic/+11111111111/Resource
```

Terraform 程式碼片段 （將`+111111111`字串取代為您的有效電話號碼）：

```
resource "aws_sns_topic_subscription" "sms-target" {
  topic_arn = aws_sns_topic.topic.arn
  protocol  = "sms"
  endpoint  = "+11111111111"
}
```

**成功的保留**

以下流程說明「ReserveFlight」、「ReserveCarRental」和「ProcessPayment」後接「ConfirmFlight」和「ConfirmCarRental." 客戶會透過傳送給 SNS 主題訂閱者的簡訊收到成功預訂的通知。

![\[Step Functions 使用 saga 模式成功實作保留的範例。\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/images/pattern-img/fec0789c-d9b1-4d80-b179-dd9a7ecbec07/images/f58c894e-7721-4bc7-8f7d-29f23faa5dc1.png)


**失敗的保留**

此流程是 saga 模式失敗的範例。如果預訂航班和租車後，「ProcessPayment」失敗，步驟會依相反順序取消。 會釋出保留，並透過傳送給 SNS 主題訂閱者的簡訊通知客戶失敗。

![\[Step Functions 使用 saga 模式實作的失敗保留範例。\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/images/pattern-img/fec0789c-d9b1-4d80-b179-dd9a7ecbec07/images/7c64d326-be27-42c3-b03f-d677efedb9a7.png)


# 使用 AWS CDK 設定 Amazon ECS Anywhere 來管理內部部署容器應用程式
<a name="manage-on-premises-container-applications-by-setting-up-amazon-ecs-anywhere-with-the-aws-cdk"></a>

*Rahul Sharad Gaikwad 醫生，Amazon Web Services*

## 總結
<a name="manage-on-premises-container-applications-by-setting-up-amazon-ecs-anywhere-with-the-aws-cdk-summary"></a>

[Amazon ECS Anywhere](https://aws.amazon.com/ecs/anywhere/) 是 Amazon Elastic Container Service (Amazon ECS) 的延伸。您可以使用 ECS Anywhere 在內部部署或客戶受管環境中部署原生 Amazon ECS 任務。此功能有助於降低成本，並減少複雜的本機容器協同運作和操作。您可以使用 ECS Anywhere 在內部部署和雲端環境中部署和執行容器應用程式。它消除了您的團隊學習多個網域和技能集，或自行管理複雜軟體的需求。

此模式示範使用 [AWS Cloud Development Kit (AWS CDK)](https://aws.amazon.com/cdk/) 堆疊設定 ECS Anywhere 的步驟。

## 先決條件和限制
<a name="manage-on-premises-container-applications-by-setting-up-amazon-ecs-anywhere-with-the-aws-cdk-prereqs"></a>

**先決條件**
+ 作用中的 AWS 帳戶
+ 安裝並設定 AWS Command Line Interface (AWS CLI)。（請參閱 [AWS CLI 文件中的安裝、更新和解除安裝](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-install.html) AWS CLI。) 
+ AWS CDK Toolkit，已安裝並設定。（請參閱 [AWS CDK 文件](https://docs.aws.amazon.com/cdk/v2/guide/cli.html)中的 AWS CDK Toolkit，並依照指示在全球安裝第 2 版。)
+ 節點套件管理員 (npm)，已安裝並設定 TypeScript 中的 AWS CDK。（請參閱 [npm 文件中的下載和安裝 Node.js 和](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm) npm。)

**限制**
+ 如需限制和考量，請參閱 [Amazon ECS Anywhere)](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-anywhere.html#ecs-anywhere-considerations)。

**產品版本**
+ AWS CDK Toolkit 第 2 版
+ npm 7.20.3 版或更新版本
+ Node.js 16.6.1 版或更新版本

## Architecture
<a name="manage-on-premises-container-applications-by-setting-up-amazon-ecs-anywhere-with-the-aws-cdk-architecture"></a>

**目標技術堆疊**
+ AWS CloudFormation
+ AWS CDK
+ Amazon ECS Anywhere
+ AWS Identity and Access Management (IAM)

**目標架構**

下圖說明使用 AWS CDK 搭配 TypeScript 的 ECS Anywhere 設定的高階系統架構，如此模式所實作。

1. 當您部署 AWS CDK 堆疊時，它會在 AWS 上建立 CloudFormation 堆疊。

1. CloudFormation 堆疊會佈建 Amazon ECS 叢集和相關的 AWS 資源。

1. 若要向 Amazon ECS 叢集註冊外部執行個體，您必須在虛擬機器 (VM) 上安裝 AWS Systems Manager Agent (SSM Agent)，並將 VM 註冊為 AWS Systems Manager 受管執行個體。 

1. 您還必須在 VM 上安裝 Amazon ECS 容器代理程式和 Docker，以將其註冊為 Amazon ECS 叢集的外部執行個體。

1. 使用 Amazon ECS 叢集註冊和設定外部執行個體時，它可以在您的 VM 上執行多個容器，其已註冊為外部執行個體。

![\[ECS Anywhere 設定搭配 TypeScript 使用 AWS CDK。\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/images/pattern-img/3ed63c00-40e7-4831-bb9d-63049c3490aa/images/ff7dc774-830d-4b9f-8262-7314afe7a033.png)


 

**自動化和擴展**

此模式隨附的 [GitHub 儲存庫](https://github.com/aws-samples/amazon-ecs-anywhere-cdk-samples/)會使用 AWS CDK 做為基礎設施做為程式碼 (IaC) 工具，來建立此架構的組態。AWS CDK 可協助您協調資源並設定 ECS Anywhere。

## 工具
<a name="manage-on-premises-container-applications-by-setting-up-amazon-ecs-anywhere-with-the-aws-cdk-tools"></a>
+ [AWS 雲端開發套件 (AWS CDK)](https://docs.aws.amazon.com/cdk/latest/guide/home.html) 是一種軟體開發架構，可協助您在程式碼中定義和佈建 AWS 雲端基礎設施。
+ [AWS Command Line Interface (AWS CLI)](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-welcome.html) 是一種開放原始碼工具，可協助您透過命令列 shell 中的命令與 AWS 服務互動。

**Code**

此模式的原始碼可在 GitHub 上的 [Amazon ECS Anywhere CDK 範例](https://github.com/aws-samples/amazon-ecs-anywhere-cdk-samples)儲存庫中取得。若要複製和使用儲存庫，請遵循下一節中的指示。

## 史詩
<a name="manage-on-premises-container-applications-by-setting-up-amazon-ecs-anywhere-with-the-aws-cdk-epics"></a>

### 驗證 AWS CDK 組態
<a name="verify-aws-cdk-configuration"></a>


| 任務 | Description | 所需的技能 | 
| --- | --- | --- | 
| 驗證 AWS CDK 版本。 | 執行下列命令來驗證 AWS CDK Toolkit 的版本：<pre>cdk --version</pre>此模式需要 AWS CDK 第 2 版。如果您有舊版的 AWS CDK，請遵循 [AWS CDK 文件](https://docs.aws.amazon.com/cdk/v2/guide/cli.html)中的指示進行更新。 | DevOps 工程師 | 
| 設定 AWS 登入資料。 | 若要設定登入資料，請執行 `aws configure`命令並遵循提示：<pre>$aws configure<br />AWS Access Key ID [None]: <your-access-key-ID><br />AWS Secret Access Key [None]: <your-secret-access-key><br />Default region name [None]: <your-Region-name><br />Default output format [None]:</pre> | DevOps 工程師 | 

### 引導 AWS CDK 環境
<a name="bootstrap-the-aws-cdk-environment"></a>


| 任務 | Description | 所需的技能 | 
| --- | --- | --- | 
| 複製 AWS CDK 程式碼儲存庫。 | 使用 命令複製此模式的 GitHub 程式碼儲存庫：<pre>git clone https://github.com/aws-samples/amazon-ecs-anywhere-cdk-samples.git</pre> | DevOps 工程師 | 
| 引導環境。 | 若要將 AWS CloudFormation 範本部署到您要使用的帳戶和 AWS 區域，請執行下列命令：<pre>cdk bootstrap <account-number>/<Region></pre>如需詳細資訊，請參閱 AWS CDK 文件中的[啟動](https://docs.aws.amazon.com/cdk/latest/guide/bootstrapping.html)。 | DevOps 工程師 | 

### 建置和部署專案
<a name="build-and-deploy-the-project"></a>


| 任務 | Description | 所需的技能 | 
| --- | --- | --- | 
| 安裝套件相依性並編譯 TypeScript 檔案。 | 安裝套件相依性，並執行下列命令編譯 TypeScript 檔案：<pre>$cd amazon-ecs-anywhere-cdk-samples<br />$npm install<br />$npm fund </pre>這些命令會從範例儲存庫安裝所有套件。 如果您收到有關遺失套件的任何錯誤，請使用下列其中一個命令：<pre>$npm ci   </pre>—或—<pre>$npm install -g @aws-cdk/<package_name></pre>如需詳細資訊，請參閱 [npm 文件中的 npm ci](https://docs.npmjs.com/cli/v7/commands/npm-ci) 和 [npm 安裝](https://docs.npmjs.com/cli/v7/commands/npm-install)。 | DevOps 工程師 | 
| 建置專案。 | 若要建置專案程式碼，請執行 命令：<pre>npm run build</pre>如需建置和部署專案的詳細資訊，請參閱 [AWS CDK 文件中的您的第一個 AWS CDK 應用程式](https://docs.aws.amazon.com/cdk/latest/guide/hello_world.html#:~:text=the%20third%20parameter.-,Synthesize%20an%20AWS%20CloudFormation%20template,-Synthesize%20an%20AWS)。 | DevOps 工程師 | 
| 部署專案。 | 若要部署專案程式碼，請執行 命令：<pre>cdk deploy</pre> | DevOps 工程師 | 
| 驗證堆疊建立和輸出。 | 開啟位於 https：//[https://console.aws.amazon.com/cloudformation](https://console.aws.amazon.com/cloudformation/) 的 AWS CloudFormation 主控台，****然後選擇`EcsAnywhereStack`堆疊。**Outputs** 索引標籤會顯示要在外部 VM 上執行的命令。 | DevOps 工程師 | 

### 設定內部部署機器
<a name="set-up-an-on-premises-machine"></a>


| 任務 | Description | 所需的技能 | 
| --- | --- | --- | 
| 使用 Vagrant 設定您的 VM。 | 基於示範目的，您可以使用 [HashiCorp Vagrant](https://www.vagrantup.com/) 來建立 VM。Vagrant 是一種開放原始碼公用程式，用於建置和維護可攜式虛擬軟體開發環境。從放置 Vagrantfile 的根目錄執行`vagrant up`命令來建立 Vagrant VM。如需詳細資訊，請參閱 [Vagrant 文件](https://www.vagrantup.com/docs/cli/up)。 | DevOps 工程師 | 
| 將您的 VM 註冊為外部執行個體。 | 1. 使用`vagrant ssh` 命令登入 Vagrant VM。如需詳細資訊，請參閱 [Vagrant 文件](https://www.vagrantup.com/docs/cli/ssh)。2. 建立啟用代碼和 ID，供您用來向 AWS Systems Manager 註冊 VM，以及啟用外部執行個體。此命令的輸出包含`ActivationId` 和`ActivationCode` 值： <pre>aws ssm create-activation --iam-role EcsAnywhereInstanceRole | tee ssm-activation.json</pre>3. 匯出啟用 ID 和程式碼值：<pre>export ACTIVATION_ID=<activation-ID><br />export ACTIVATION_CODE=<activation-code></pre>4. 將安裝指令碼下載到您的現場部署伺服器或 VM：<pre>curl -o "ecs-anywhere-install.sh" "https://amazon-ecs-agent.s3.amazonaws.com/ecs-anywhere-install-latest.sh" && sudo chmod +x ecs-anywhere-install.sh</pre>5. 在內部部署伺服器或 VM 上執行安裝指令碼：<pre>sudo ./ecs-anywhere-install.sh \<br />    --cluster test-ecs-anywhere \<br />     --activation-id $ACTIVATION_ID \<br />     --activation-code $ACTIVATION_CODE \<br />    --region <Region></pre>如需設定和註冊 VM 的詳細資訊，請參閱 Amazon ECS 文件中的[將外部執行個體註冊至叢集](https://docs.amazonaws.cn/en_us/AmazonECS/latest/developerguide/ecs-anywhere-registration.html)。 | DevOps 工程師 | 
| 驗證 ECS Anywhere 和外部 VM 的狀態。 | 若要驗證您的虛擬盒是否已連線至 Amazon ECS 控制平面並執行，請使用下列命令：<pre>aws ssm describe-instance-information<br />aws ecs list-container-instances --cluster $CLUSTER_NAME</pre> | DevOps 工程師 | 

### 清除
<a name="clean-up"></a>


| 任務 | Description | 所需的技能 | 
| --- | --- | --- | 
| 清除和刪除資源。 | 完成此模式之後，您應該移除您建立的資源，以避免產生任何進一步的費用。若要清除，請執行 命令：<pre>cdk destroy</pre> | DevOps 工程師 | 

## 相關資源
<a name="manage-on-premises-container-applications-by-setting-up-amazon-ecs-anywhere-with-the-aws-cdk-resources"></a>
+ [Amazon ECS Anywhere 文件](https://aws.amazon.com/ecs/anywhere/) 
+ [Amazon ECS Anywhere 示範](https://www.youtube.com/watch?v=-eud6yUXsJM)
+ [Amazon ECS Anywhere 研討會範例](https://github.com/aws-samples/aws-ecs-anywhere-workshop-samples)

# 在 AWS 上現代化 ASP.NET Web Forms 應用程式
<a name="modernize-asp-net-web-forms-applications-on-aws"></a>

*Vijai Anand Ramalingam 和 Sreelaxmi Pai，Amazon Web Services*

## 總結
<a name="modernize-asp-net-web-forms-applications-on-aws-summary"></a>

此模式說明透過將舊版 ASP.NET Web Forms 應用程式移植到 AWS 上的 ASP.NET Core 來現代化舊版 Web Forms 應用程式的步驟。

將 ASP.NET Web Forms 應用程式移植到 ASP.NET Core 可協助您利用 Linux 的效能、節省成本和強大的生態系統。不過，這可能會是大量的手動工作。在此模式中，舊版應用程式會使用分階段方法逐步現代化，然後在 AWS 雲端中容器化。

考慮購物車的舊版整體應用程式。假設它是建立為 ASP.NET Web Forms 應用程式，並由具有程式碼後面 (`aspx.cs`) 檔案的 .aspx 頁面組成。現代化程序包含下列步驟：

1. 使用適當的分解模式，將整體分解為微服務。如需詳細資訊，請參閱 AWS 方案指引網站上的將[整體分解為微服務](https://docs.aws.amazon.com/prescriptive-guidance/latest/modernization-decomposing-monoliths/)指南。

1. 將舊版 ASP.NET Web Forms (.NET Framework) 應用程式移植到 .NET 5 或更新版本中的 ASP.NET Core。在此模式中，您可以使用適用於 .NET 的移植助理來掃描 ASP.NET Web Forms 應用程式，並識別與 ASP.NET Core 的不相容。這可減少手動移植工作。

1. 使用 React 重新開發 Web Forms UI layer。此模式不包含 UI 重新開發。如需說明，請參閱 [React 文件中的建立新的 React 應用程式](https://reactjs.org/docs/create-a-new-react-app.html)。

1. 將 Web 表單程式碼落後檔案 （業務界面） 重新開發為 ASP.NET Core Web API。此模式使用 NDepend 報告來協助識別必要的檔案和相依性。

1. 使用適用於 .NET 的移植助理，將舊版應用程式中的共用/常見專案，例如商業邏輯和資料存取，升級至 .NET 5 或更新版本。 

1. 新增 AWS 服務以補充您的應用程式。例如，您可以使用 [Amazon CloudWatch Logs](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/WhatIsCloudWatchLogs.html) 來監控、存放和存取應用程式的日誌，以及使用 [AWS Systems Manager](https://aws.amazon.com/systems-manager/) 來存放應用程式設定。

1. 容器化現代化 ASP.NET Core 應用程式。此模式會建立以 Visual Studio 中的 Linux 為目標的 Docker 檔案，並使用 Docker 桌面在本機進行測試。此步驟假設您的舊版應用程式已在內部部署或 Amazon Elastic Compute Cloud (Amazon EC2) Windows 執行個體上執行。如需詳細資訊，請參閱模式 在 [Amazon EC2 Linux 執行個體上執行 ASP.NET Core Web API Docker 容器](https://docs.aws.amazon.com/prescriptive-guidance/latest/patterns/run-an-asp-net-core-web-api-docker-container-on-an-amazon-ec2-linux-instance.html)。

1. 將現代化 ASP.NET 核心應用程式部署至 Amazon Elastic Container Service (Amazon ECS)。此模式不包含部署步驟。如需說明，請參閱 [Amazon ECS 研討會](https://ecsworkshop.com/)。

**注意**  
此模式不包含 UI 開發、資料庫現代化或容器部署步驟。

## 先決條件和限制
<a name="modernize-asp-net-web-forms-applications-on-aws-prereqs"></a>

**先決條件**
+ [Visual Studio](https://visualstudio.microsoft.com/downloads/) 或 [Visual Studio Code](https://code.visualstudio.com/download)，已下載並安裝。
+ 使用 AWS 管理主控台和 AWS Command Line Interface (AWS CLI) 第 2 版存取 AWS 帳戶。（請參閱[設定 AWS CLI 的說明](https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html)。)
+ AWS Toolkit for Visual Studio （請參閱[設定指示](https://docs.aws.amazon.com/toolkit-for-visual-studio/latest/user-guide/setup.html))。
+ Docker Desktop，[已下載](https://www.docker.com/products/docker-desktop)並安裝。
+ .NET SDK，[已下載](https://download.visualstudio.microsoft.com/download/pr/4263dc3b-dc67-4f11-8d46-cc0ae86a232e/66782bbd04c53651f730b2e30a873f18/dotnet-sdk-5.0.203-win-x64.exe)並安裝。
+ NDepend 工具，[下載](https://www.ndepend.com/download)並安裝。若要安裝 Visual Studio 的 NDepend 延伸模組，請執行 `NDepend.VisualStudioExtension.Installer`([請參閱說明](https://www.ndepend.com/docs/getting-started-with-ndepend#Part1))。根據您的需求，您可以選擇 Visual Studio 2019 或 2022。 
+ 適用於 .NET 的移植助理，[已下載](https://aws.amazon.com/porting-assistant-dotnet/)並安裝。

## Architecture
<a name="modernize-asp-net-web-forms-applications-on-aws-architecture"></a>

**現代化購物車應用程式**

下圖說明舊版 ASP.NET 購物車應用程式的現代化程序。

![\[現代化傳統購物車應用程式\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/images/pattern-img/36cda8e6-f2cb-4f1a-b37f-fa3045cc5ba1/images/4367e259-9bb3-4eb6-a54d-1c1e2dece7d4.png)


**目標架構**

下圖說明 AWS 上現代化購物車應用程式的架構。ASP.NET Core Web APIs會部署到 Amazon ECS 叢集。記錄和組態服務由 Amazon CloudWatch Logs 和 AWS Systems Manager 提供。

![\[AWS 上 ASP.NET Web Forms 應用程式的目標架構\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/images/pattern-img/36cda8e6-f2cb-4f1a-b37f-fa3045cc5ba1/images/ed6d65ec-0dc9-43ab-ac07-1f172e089399.png)


## 工具
<a name="modernize-asp-net-web-forms-applications-on-aws-tools"></a>

**AWS 服務**
+ [Amazon ECS](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/Welcome.html) – Amazon Elastic Container Service (Amazon ECS) 是一種高度可擴展的快速容器管理服務，用於執行、停止和管理叢集上的容器。您可以在 AWS Fargate 管理的無伺服器基礎設施上執行任務和服務。或者，若要進一步控制您的基礎設施，您可以在您管理的 EC2 執行個體叢集上執行任務和服務。
+ [Amazon CloudWatch Logs](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/WhatIsCloudWatchLogs.html) – Amazon CloudWatch Logs 會集中來自您使用之所有系統、應用程式和 AWS 服務的日誌。您可以檢視和監控日誌、搜尋特定錯誤代碼或模式、根據特定欄位篩選日誌，或安全地封存日誌以供未來分析。
+ [AWS Systems Manager](https://docs.aws.amazon.com/systems-manager/latest/userguide/what-is-systems-manager.html) - AWS Systems Manager 是一種 AWS 服務，可用來檢視和控制 AWS 上的基礎設施。使用 Systems Manager 主控台，您可以檢視來自多個 AWS 服務的操作資料，並自動化 AWS 資源的操作任務。Systems Manager 會掃描受管執行個體，並在偵測到任何政策違規時回報 （或採取修正動作），以協助您維護安全性和合規性。

**工具**
+ [Visual Studio](https://visualstudio.microsoft.com/) 或 [Visual Studio 程式碼](https://code.visualstudio.com/) – 用於建置 .NET 應用程式、Web APIs和其他程式的工具。
+ [AWS Toolkit for Visual Studio](https://docs.aws.amazon.com/toolkit-for-visual-studio/latest/user-guide/welcome.html) – Visual Studio 的延伸，可協助開發、偵錯和部署使用 AWS 服務的 .NET 應用程式。
+ [Docker Desktop](https://www.docker.com/products/docker-desktop) – 一種工具，可簡化建置和部署容器化應用程式。
+ [NDepend](https://www.ndepend.com/features/) – 監控 .NET 程式碼是否有相依性、品質問題和程式碼變更的分析器。
+ 適用於 [.NET 的移植助理](https://aws.amazon.com/porting-assistant-dotnet/) – 掃描 .NET 程式碼以識別與 .NET Core 不相容的分析工具，並估計遷移工作量。

## 史詩
<a name="modernize-asp-net-web-forms-applications-on-aws-epics"></a>

### 將舊版應用程式移植到 .NET 5 或更新版本
<a name="port-your-legacy-application-to-net-5-or-later-version"></a>


| 任務 | Description | 所需的技能 | 
| --- | --- | --- | 
| 將 your.NET Framework 舊版應用程式升級至 .NET 5。 | 您可以使用適用於 .NET 的移植助理，將舊版 ASP.NET Web Forms 應用程式轉換為 .NET 5 或更新版本。遵循[適用於 .NET 的移植助理文件中](https://docs.aws.amazon.com/portingassistant/latest/userguide/porting-assistant-getting-started.html)的指示。 | 應用程式開發人員 | 
| 產生 NDepend 報告。 | 當您將 ASP.NET Web Forms 應用程式分解為微服務來現代化時，您可能不需要舊版應用程式中的所有 .cs 檔案。您可以使用 NDepend 來產生任何程式碼後面 (.cs) 檔案的報告，以取得所有來電者和來電者。此報告可協助您識別和僅使用微服務中的必要檔案。安裝 NDepend 後 [（請參閱先決條件](#modernize-asp-net-web-forms-applications-on-aws-prereqs)區段），請在 Visual Studio 中開啟舊版應用程式的解決方案 (.sln 檔案），並遵循下列步驟：[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/modernize-asp-net-web-forms-applications-on-aws.html)此程序會產生代碼後面檔案的報告，列出所有來電者和來電者。如需相依性圖表的詳細資訊，請參閱 [NDepend 文件](https://www.ndepend.com/docs/visual-studio-dependency-graph)。 | 應用程式開發人員 | 
| 建立新的 .NET 5 解決方案。 | 若要為現代化 ASP.NET Core Web APIs 建立新的 .NET 5 （或更新版本） 結構：[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/modernize-asp-net-web-forms-applications-on-aws.html)如需建立專案和解決方案的詳細資訊，請參閱 [Visual Studio 文件](https://docs.microsoft.com/en-us/visualstudio/ide/creating-solutions-and-projects)。當您建置解決方案並驗證功能時，除了 NDepend 識別的檔案之外，您還可以識別要新增到解決方案的其他幾個檔案。 | 應用程式開發人員 | 

### 更新您的應用程式程式碼
<a name="update-your-application-code"></a>


| 任務 | Description | 所需的技能 | 
| --- | --- | --- | 
| 使用 ASP.NET Core 實作 Web APIs。 | 假設您在舊版單體購物車應用程式中識別的其中一個微服務是*產品*。您已在上一個史詩中為*產品*建立新的 ASP.NET Core Web API 專案。在此步驟中，您會識別和現代化與 *產品*相關的所有 Web 表單 (.aspx 頁面）。假設*產品*由四個 Web 表單組成，如先前[架構](#modernize-asp-net-web-forms-applications-on-aws-architecture)一節所示：[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/modernize-asp-net-web-forms-applications-on-aws.html)您應該分析每個 Web 表單、識別傳送至資料庫以執行一些邏輯的所有請求，以及取得回應。您可以實作每個請求做為 Web API 端點。鑑於其 Web 表單，*產品*可以有下列可能端點：[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/modernize-asp-net-web-forms-applications-on-aws.html)如前所述，您也可以重複使用升級至 .NET 5 的所有其他專案，包括商業邏輯、資料存取和共用/常見專案。 | 應用程式開發人員 | 
| 設定 Amazon CloudWatch Logs。 | 您可以使用 [Amazon CloudWatch Logs](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/WhatIsCloudWatchLogs.html) 來監控、存放和存取應用程式的日誌。您可以使用 AWS 開發套件將資料記錄到 Amazon CloudWatch Logs。您也可以使用 [NLog](https://www.nuget.org/packages/AWS.Logger.NLog/)、Log[Log4Net](https://www.nuget.org/packages/AWS.Logger.Log4net/) 和 [ASP.NET Core 記錄架構等熱門 .NET 記錄架構](https://www.nuget.org/packages/AWS.Logger.AspNetCore/)，將 .NET 應用程式與 CloudWatch Logs 整合。如需此步驟的詳細資訊，請參閱部落格文章 [Amazon CloudWatch Logs 和 .NET Logging Frameworks](https://aws.amazon.com/blogs/developer/amazon-cloudwatch-logs-and-net-logging-frameworks/)。 | 應用程式開發人員 | 
| 設定 AWS Systems Manager 參數存放區。 | 您可以使用 [AWS Systems Manager 參數存放區](https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-paramstore.html)，將連線字串與應用程式的程式碼分開存放應用程式設定。NuGet [packageAmazon.Extensions.Configuration.SystemsManager](https://www.nuget.org/packages/Amazon.Extensions.Configuration.SystemsManager/) 可簡化您的應用程式如何將這些設定從 AWS Systems Manager 參數存放區載入 .NET Core 組態系統。 如需此步驟的詳細資訊，請參閱 [ AWS Systems Manager 的部落格文章 .NET Core 組態提供者](https://aws.amazon.com/blogs/developer/net-core-configuration-provider-for-aws-systems-manager/)。 | 應用程式開發人員 | 

### 新增身分驗證和授權
<a name="add-authentication-and-authorization"></a>


| 任務 | Description | 所需的技能 | 
| --- | --- | --- | 
| 使用共用 Cookie 進行身分驗證。 | 將傳統整體應用程式現代化是一種反覆程序，需要整體及其現代化版本才能共存。您可以使用共用 Cookie 來實現兩個版本之間的無縫身分驗證。舊版 ASP.NET 應用程式會繼續驗證使用者登入資料並發出 Cookie，同時現代化 ASP.NET Core 應用程式會驗證 Cookie。 如需說明和範例程式碼，請參閱[範例 GitHub 專案](https://github.com/aws-samples/dotnet-share-auth-cookie-between-monolith-and-modernized-apps)。 | 應用程式開發人員 | 

### 在本機建置和執行容器
<a name="build-and-run-the-container-locally"></a>


| 任務 | Description | 所需的技能 | 
| --- | --- | --- | 
| 使用 Visual Studio 建立 Docker 映像。 | 在此步驟中，您會使用 Visual Studio for .NET Core Web API 來建立 Docker 檔案。[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/modernize-asp-net-web-forms-applications-on-aws.html)Visual Studio 會為您的專案建立 Docker 檔案。如需 Docker 檔案範例，請參閱 Microsoft 網站上的[適用於 Docker 的 Visual Studio 容器工具](https://docs.microsoft.com/en-us/visualstudio/containers/overview)。 | 應用程式開發人員 | 
| 使用 Docker 桌面建置和執行容器。 | 現在您可以在 Docker 桌面中建置、建立和執行容器。[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/modernize-asp-net-web-forms-applications-on-aws.html) | 應用程式開發人員 | 

## 相關資源
<a name="modernize-asp-net-web-forms-applications-on-aws-resources"></a>
+ [在 Amazon EC2 Linux 執行個體上執行 ASP.NET Core Web API Docker 容器](https://docs.aws.amazon.com/prescriptive-guidance/latest/patterns/run-an-asp-net-core-web-api-docker-container-on-an-amazon-ec2-linux-instance.html) (AWS 方案指引）
+ [Amazon ECS 研討會](https://ecsworkshop.com/)
+ [使用 AWS CloudFormation (AWS CloudFormation 文件） 透過 CodeDeploy 執行 ECS 藍/綠部署](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/blue-green.html) AWS CloudFormation 
+ [NDepend 入門 ](https://www.ndepend.com/docs/getting-started-with-ndepend)(NDepend 文件）
+ [.NET 的移植助理](https://aws.amazon.com/porting-assistant-dotnet/)

## 其他資訊
<a name="modernize-asp-net-web-forms-applications-on-aws-additional"></a>

下表提供舊版購物車應用程式的範例專案，以及現代化 ASP.NET Core 應用程式中的同等專案。

**舊版解決方案：**


| 
| 
| Project name (專案名稱) | 專案範本 | 目標架構 | 
| --- |--- |--- |
| 業務界面  | 類別程式庫  | .NET Framework  | 
| BusinessLogic  | 類別程式庫  | .NET Framework  | 
| WebApplication  | ASP.NET Framework Web 應用程式  | .NET Framework  | 
| UnitTests  | NUnit 測試專案  | .NET Framework  | 
| 共用 -> 常見  | 類別程式庫  | .NET Framework  | 
| 共用 -> 架構  | 類別程式庫  | .NET Framework  | 

**新解決方案：**


| 
| 
| Project name (專案名稱) | 專案範本 | 目標架構 | 
| --- |--- |--- |
| BusinessLogic  | 類別程式庫  | .NET 5.0  | 
| <WebAPI>  | ASP.NET Core Web API  | .NET 5.0  | 
| <WebAPI>。UnitTests  | NUnit 3 測試專案  | .NET 5.0  | 
| 共用 -> 常見  | 類別程式庫  | .NET 5.0  | 
| 共用 -> 架構  | 類別程式庫  | .NET 5.0  | 

# 使用 C\$1 和 AWS CDK 在孤立模型的 SaaS 架構中加入租用戶
<a name="tenant-onboarding-in-saas-architecture-for-the-silo-model-using-c-and-aws-cdk"></a>

*Tabby Ward、Susmitha Reddy Gankidi 和 Vijai Anand Ramalingam，Amazon Web Services*

## 總結
<a name="tenant-onboarding-in-saas-architecture-for-the-silo-model-using-c-and-aws-cdk-summary"></a>

軟體即服務 (SaaS) 應用程式可以使用各種不同的架構模型建置。*孤島模型*是指提供租戶專用資源的架構。

SaaS 應用程式依賴無摩擦模型，將新租戶引入其環境。這通常需要協調多個元件，才能成功佈建和設定建立新租用戶所需的所有元素。在 SaaS 架構中，此程序稱為租戶加入。應針對每個 SaaS 環境使用基礎設施做為加入程序中的程式碼，以完全自動化加入。

此模式會引導您完成在 Amazon Web Services (AWS) 上建立租用戶和佈建租用戶基本基礎設施的範例。模式使用 C\$1 和 AWS 雲端開發套件 (AWS CDK)。

由於此模式會建立帳單警示，因此建議您在美國東部 （維吉尼亞北部） 或 us-east-1 AWS 區域部署堆疊。如需詳細資訊，請參閱 [AWS 文件](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/monitor_estimated_charges_with_cloudwatch.html)。

## 先決條件和限制
<a name="tenant-onboarding-in-saas-architecture-for-the-silo-model-using-c-and-aws-cdk-prereqs"></a>

**先決條件******
+ 作用中的 [AWS 帳戶](https://aws.amazon.com/account/)。
+ 具有足夠 IAM 存取權的 AWS Identity and Access Management (IAM) 主體，可為此模式建立 AWS 資源。如需詳細資訊，請參閱 [IAM 角色](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles.html)。
+ [安裝 Amazon Command Line Interface (AWS CLI)](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) 並[設定 AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-configure.html) 以執行 AWS CDK 部署。
+ [Visual Studio 2022](https://visualstudio.microsoft.com/downloads/) 已下載並安裝，或 [Visual Studio Code](https://code.visualstudio.com/download) 已下載並安裝。
+ [AWS Toolkit for Visual Studio](https://docs.aws.amazon.com/toolkit-for-visual-studio/latest/user-guide/setup.html) 設定。
+ [.NET Core 3.1 或更新版本](https://dotnet.microsoft.com/download/dotnet-core/3.1) (C\$1 AWS CDK 應用程式需要）
+ 已安裝 [Amazon.Lambda.Tools](https://github.com/aws/aws-extensions-for-dotnet-cli#aws-lambda-amazonlambdatools)。

**限制******
+ AWS CDK 使用 [AWS CloudFormation](https://aws.amazon.com/cloudformation/)，因此 AWS CDK 應用程式受限於 CloudFormation 服務配額。如需詳細資訊，請參閱 [AWS CloudFormation 配額](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cloudformation-limits.html)。 
+ 租用戶 CloudFormation 堆疊是使用 CloudFormation 服務角色建立的，`infra-cloudformation-role`其動作上有萬用字元 (`sns`\$1 和 `sqs*`)，但資源鎖定為`tenant-cluster`字首。對於生產使用案例，請評估此設定，並僅提供對此服務角色的必要存取權。`InfrastructureProvision` Lambda 函數也會使用萬用字元 (`cloudformation*`) 來佈建 CloudFormation 堆疊，但資源會鎖定為`tenant-cluster`字首。
+ 此範例程式碼的 docker 組建使用 `--platform=linux/amd64` 來強制以映像`linux/amd64`為基礎。這是為了確保最終影像成品適用於 Lambda，依預設會使用 x86-64 架構。如果您需要變更目標 Lambda 架構，請務必同時變更 Dockerfile 和 AWS CDK 代碼。如需詳細資訊，請參閱部落格文章將 [ AWS Lambda 函數遷移至 Arm 型 AWS Graviton2 處理器](https://aws.amazon.com/blogs/compute/migrating-aws-lambda-functions-to-arm-based-aws-graviton2-processors/)。
+ 堆疊刪除程序不會清除堆疊產生的 CloudWatch Logs （日誌群組和日誌）。您必須透過 AWS 管理主控台 Amazon CloudWatch 主控台或透過 API 手動清除日誌。

此模式設定為範例。針對生產用途，請評估下列設定，並根據您的業務需求進行變更：
+ 此範例中的 [AWS Simple Storage Service (Amazon S3)](https://aws.amazon.com/s3/) 儲存貯體尚未啟用版本控制以簡化操作。視需要評估和更新設定。
+ 此範例設定 [Amazon API Gateway](https://aws.amazon.com/api-gateway/) REST API 端點，無需身分驗證、授權或限流即可簡化。對於生產用途，我們建議您將系統與商業安全基礎設施整合。評估此設定並視需要新增必要的安全設定。
+ 在此租戶基礎設施範例中，[Amazon Simple Notification Service (Amazon SNS)](https://aws.amazon.com/sns/) 和 [Amazon Simple Queue Service (Amazon SQS)](https://aws.amazon.com/sqs/) 只有最低設定。每個租用戶的 [AWS Key Management Service (AWS KMS)](https://aws.amazon.com/kms/) 會開啟帳戶中的 [Amazon CloudWatch](https://aws.amazon.com/cloudwatch/) 和 Amazon SNS 服務，以根據 [AWS KMS 金鑰政策](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-key-management.html#compatibility-with-aws-services)使用。設定只是範例預留位置。根據您的業務使用案例，視需要調整設定。
+ 整個設定包括但不限於 API 端點，以及使用 AWS CloudFormation 進行後端租用戶佈建和刪除，僅涵蓋基本的快樂路徑案例。根據您的業務需求，使用必要的重試邏輯、額外的錯誤處理邏輯和安全邏輯來評估和更新設定。
+ 範例程式碼使用up-to-date [cdk-nag](https://github.com/cdklabs/cdk-nag) 進行測試，以在撰寫本文時檢查政策。未來可能會強制執行新政策。這些新政策可能需要您根據建議手動修改堆疊，才能部署堆疊。檢閱現有的程式碼，以確保其符合您的業務需求。
+ 此程式碼倚賴 AWS CDK 產生隨機尾碼，而不是倚賴大多數建立資源的靜態指派實體名稱。此設定旨在確保這些資源是唯一的，並且不會與其他堆疊衝突。如需詳細資訊，請參閱 [AWS CDK 文件](https://docs.aws.amazon.com/cdk/v2/guide/resources.html#resources_physical_names)。根據您的業務需求進行調整。
+ 此範例程式碼會將 .NET Lambda 成品封裝至以 Docker 為基礎的映像，並使用 Lambda 提供的[容器映像執行時間](https://docs.aws.amazon.com/lambda/latest/dg/csharp-image.html)執行。容器映像執行時間對於標準傳輸和儲存機制 （容器登錄檔） 和更準確的本機測試環境 （透過容器映像） 具有優勢。您可以切換專案以使用 [Lambda 提供的 .NET 執行時間](https://docs.aws.amazon.com/lambda/latest/dg/lambda-csharp.html)，以減少 Docker 映像的建置時間，但接著您需要設定傳輸和儲存機制，並確保本機設定符合 Lambda 設定。調整程式碼以符合使用者的業務需求。

**產品版本**
+ AWS CDK 2.45.0 版或更新版本
+ Visual Studio 2022

## Architecture
<a name="tenant-onboarding-in-saas-architecture-for-the-silo-model-using-c-and-aws-cdk-architecture"></a>

**技術堆疊**
+ Amazon API Gateway
+ AWS CloudFormation
+ Amazon CloudWatch
+ Amazon DynamoDB
+ AWS Identity and Access Management (IAM)
+ AWS KMS
+ AWS Lambda
+ Amazon S3
+ Amazon SNS
+ Amazon SQS

**架構**

下圖顯示租戶堆疊建立流程。如需控制平面和租戶技術堆疊的詳細資訊，請參閱*其他資訊*一節。

![\[建立租用戶並為 AWS 上的租用戶佈建基本基礎設施的工作流程。\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/images/pattern-img/5baef800-fe39-4eb8-b11d-2c23eb3175fc/images/0b579484-b87c-4acb-8c60-8c33c18370e3.png)


**租戶堆疊建立流程**

1. 使用者將具有 JSON 中新租用戶承載 （租用戶名稱、租用戶描述） 的 POST API 請求傳送至 Amazon API Gateway 託管的 REST API。API Gateway 會處理請求，並將其轉送至後端 Lambda 租戶加入函數。在此範例中，沒有授權或身分驗證。在生產設定中，此 API 應與 SaaS 基礎設施安全系統整合。

1. 租戶加入函數會驗證請求。然後，它會嘗試將租用戶記錄存放在 Amazon DynamoDB 租用戶加入資料表中，其中包含租用戶名稱、產生的租用戶通用唯一識別符 (UUID) 和租用戶描述。 

1. DynamoDB 儲存記錄後，DynamoDB 串流會啟動下游 Lambda 租用戶基礎設施函數。

1. 租戶基礎設施 Lambda 函數會根據收到的 DynamoDB 串流來運作。如果串流適用於 INSERT 事件，則函數會使用串流的 NewImage 區段 （最新更新記錄，租戶名稱欄位） 來叫用 CloudFormation，以使用存放在 S3 儲存貯體中的範本建立新的租戶基礎設施。CloudFormation 範本需要租用戶名稱參數。 

1. AWS CloudFormation 會根據 CloudFormation 範本和輸入參數建立租戶基礎設施。

1. 每個租戶基礎設施設定都有 CloudWatch 警示、帳單警示和警示事件。

1. 警示事件會變成 SNS 主題的訊息，由租戶的 AWS KMS 金鑰加密。

1. SNS 主題會將收到的警示訊息轉送至 SQS 佇列，該佇列由租戶的 AWS KMS 加密以進行加密金鑰。

其他系統可與 Amazon SQS 整合，以根據佇列中的訊息執行動作。在此範例中，若要保持程式碼通用，傳入的訊息會保留在佇列中，且需要手動刪除。

**租戶堆疊刪除流程**

1. 使用者將具有 JSON 中新租用戶承載 （租用戶名稱、租用戶描述） 的 DELETE API 請求傳送至 Amazon API Gateway 託管的 REST API，這會處理請求並轉送至租用戶加入函數。在此範例中，沒有授權或身分驗證。在生產設定中，此 API 將與 SaaS 基礎設施安全系統整合。

1. 租戶加入函數將驗證請求，然後嘗試從租戶加入資料表中刪除租戶記錄 （租戶名稱）。 

1. DynamoDB 成功刪除記錄後 （記錄存在於資料表中並刪除），DynamoDB 串流會啟動下游 Lambda 租用戶基礎設施函數。

1. 租戶基礎設施 Lambda 函數會根據收到的 DynamoDB 串流記錄運作。如果串流是用於 REMOVE 事件，則函數會使用記錄的 OldImage 區段 （記錄資訊和租用戶名稱欄位，在最新變更之前為刪除），根據該記錄資訊啟動現有堆疊的刪除。

1. AWS CloudFormation 會根據輸入刪除目標租用戶堆疊。

## 工具
<a name="tenant-onboarding-in-saas-architecture-for-the-silo-model-using-c-and-aws-cdk-tools"></a>

**AWS 服務**
+ [Amazon API Gateway](https://docs.aws.amazon.com/apigateway/latest/developerguide/welcome.html) 可協助您建立、發佈、維護、監控和保護任何規模的 REST、HTTP 和 WebSocket APIs。
+ [AWS Cloud Development Kit (AWS CDK)](https://docs.aws.amazon.com/cdk/v2/guide/home.html) 是一種軟體開發架構，可協助您在程式碼中定義和佈建 AWS Cloud 基礎設施。
+ [AWS CDK Toolkit](https://docs.aws.amazon.com/cdk/v2/guide/cli.html) 是命令列雲端開發套件，可協助您與 AWS Cloud Development Kit (AWS CDK) 應用程式互動。
+ [AWS Command Line Interface (AWS CLI)](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-welcome.html) 是一種開放原始碼工具，可協助您透過命令列 shell 中的命令與 AWS 服務互動。
+ [AWS CloudFormation](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/Welcome.html) 可協助您設定 AWS 資源、快速一致地佈建資源，以及在整個 AWS 帳戶和區域的生命週期進行管理。
+ [Amazon DynamoDB](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Introduction.html) 是一項全受管 NoSQL 資料庫服務，可提供快速、可預期且可擴展的效能。
+ [AWS Identity and Access Management (IAM)](https://docs.aws.amazon.com/IAM/latest/UserGuide/introduction.html) 可透過控制已驗證並獲授權使用的人員，協助您安全地管理對 AWS 資源的存取。
+ [AWS Key Management Service (AWS KMS) ](https://docs.aws.amazon.com/kms/latest/developerguide/overview.html)可協助您建立和控制密碼編譯金鑰，以協助保護您的資料。
+ [AWS Lambda](https://docs.aws.amazon.com/lambda/latest/dg/welcome.html) 是一種運算服務，可協助您執行程式碼，而不需要佈建或管理伺服器。它只會在需要時執行程式碼並自動擴展，因此您只需按使用的運算時間付費。
+ [Amazon Simple Storage Service (Amazon S3)](https://docs.aws.amazon.com/AmazonS3/latest/userguide/Welcome.html) 是一種雲端型物件儲存服務，可協助您儲存、保護和擷取任何數量的資料。
+ [Amazon Simple Notification Service (Amazon SNS)](https://docs.aws.amazon.com/sns/latest/dg/welcome.html) 可協助您協調和管理發佈者和用戶端之間的訊息交換，包括 Web 伺服器和電子郵件地址。
+ [Amazon Simple Queue Service (Amazon SQS)](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/welcome.html) 提供安全、耐用且可用的託管佇列，可協助您整合和分離分散式軟體系統和元件。
+ [AWS Toolkit for Visual Studio](https://docs.aws.amazon.com/toolkit-for-visual-studio/latest/user-guide/welcome.html) 是 Visual Studio 整合開發環境 (IDE) 的外掛程式。Toolkit for Visual Studio 支援開發、偵錯和部署使用 AWS 服務的 .NET 應用程式。

**其他工具**
+ [Visual Studio](https://docs.microsoft.com/en-us/visualstudio/ide/whats-new-visual-studio-2022?view=vs-2022) 是一種 IDE，其中包含編譯器、程式碼完成工具、圖形設計師和其他支援軟體開發的功能。

**Code**

此模式的程式碼位於 [ SaaS Architecture for Silo Model APG 範例儲存庫中的租戶加入](https://github.com/aws-samples/tenant-onboarding-in-saas-architecture-for-silo-model-apg-example)中。

## 史詩
<a name="tenant-onboarding-in-saas-architecture-for-the-silo-model-using-c-and-aws-cdk-epics"></a>

### 設定 AWS CDK
<a name="set-up-aws-cdk"></a>


| 任務 | Description | 所需的技能 | 
| --- | --- | --- | 
| 驗證 Node.js 安裝。 | 若要確認您的本機電腦上已安裝 Node.js，請執行下列命令。<pre>node --version</pre> | AWS 管理員、AWS DevOps | 
| 安裝 AWS CDK Toolkit。 | 若要在本機電腦上安裝 AWS CDK Toolkit，請執行下列命令。<pre>npm install -g aws-cdk</pre>如果未安裝 npm，您可以從 [Node.js 網站安裝。](https://nodejs.org/en/download/package-manager/) | AWS 管理員、AWS DevOps | 
| 驗證 AWS CDK Toolkit 版本。 | 若要確認您的電腦上已正確安裝 AWS CDK Toolkit 版本，請執行下列命令。 <pre>cdk --version</pre> | AWS 管理員、AWS DevOps | 

### 檢閱租戶加入控制平面的程式碼
<a name="review-the-code-for-the-tenant-onboarding-control-plane"></a>


| 任務 | Description | 所需的技能 | 
| --- | --- | --- | 
| 複製儲存庫。 | 複製[儲存庫](https://github.com/aws-samples/tenant-onboarding-in-saas-architecture-for-silo-model-apg-example)，然後導覽至 `\tenant-onboarding-in-saas-architecture-for-silo-model-apg-example` 資料夾。在 Visual Studio 2022 中，開啟`\src\TenantOnboardingInfra.sln`解決方案。開啟 `TenantOnboardingInfraStack.cs` 檔案並檢閱程式碼。下列資源會建立為此堆疊的一部分：[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/tenant-onboarding-in-saas-architecture-for-the-silo-model-using-c-and-aws-cdk.html) | AWS 管理員、AWS DevOps | 
| 檢閱 CloudFormation 範本。 | 在 `\tenant-onboarding-in-saas-architecture-for-silo-model-apg-example\template`資料夾中，開啟 `infra.yaml`並檢閱 CloudFormation 範本。此範本將使用從租戶加入 DynamoDB 資料表擷取的租戶名稱進行補充。範本會佈建租戶特定的基礎設施。在此範例中，它會佈建 AWS KMS 金鑰、Amazon SNS、Amazon SQS 和 CloudWatch 警示。 | 應用程式開發人員、AWS DevOps | 
| 檢閱租戶加入函數。 | 開啟 `Function.cs`，並檢閱租戶加入函數的程式碼，該函數是使用 Visual Studio AWS Lambda 專案 (.NET Core- C\$1) 範本搭配 .NET 6 （容器映像） 藍圖所建立。開啟 `Dockerfile`，並檢閱程式碼。`Dockerfile` 是一個文字檔案，其中包含建置 Lambda 容器映像的說明。請注意，下列 NuGet 套件會新增為`TenantOnboardingFunction`專案的相依性：[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/tenant-onboarding-in-saas-architecture-for-the-silo-model-using-c-and-aws-cdk.html) | 應用程式開發人員、AWS DevOps | 
| 檢閱租戶 InfraProvisioning 函數。 | 導覽至 `\tenant-onboarding-in-saas-architecture-for-silo-model-apg-example\src\InfraProvisioningFunction`。開啟 `Function.cs`，並檢閱租用戶基礎設施佈建函數的程式碼，該函數是使用 Visual Studio AWS Lambda 專案 (.NET Core- C\$1) 範本搭配 .NET 6 （容器映像） 藍圖所建立。開啟 `Dockerfile`，並檢閱程式碼。請注意，下列 NuGet 套件會新增為`InfraProvisioningFunction`專案的相依性：[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/tenant-onboarding-in-saas-architecture-for-the-silo-model-using-c-and-aws-cdk.html) | 應用程式開發人員、AWS DevOps | 

### 部署 AWS 資源
<a name="deploy-the-aws-resources"></a>


| 任務 | Description | 所需的技能 | 
| --- | --- | --- | 
| 建置解決方案。 | 若要建置解決方案，請執行下列步驟：[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/tenant-onboarding-in-saas-architecture-for-the-silo-model-using-c-and-aws-cdk.html)在建置解決方案之前，請務必將`Amazon.CDK.Lib NuGet`套件更新至`\tenant-onboarding-in-saas-architecture-for-silo-model-apg-example\src\TenantOnboardingInfra`專案中的最新版本。 | 應用程式開發人員 | 
| 引導 AWS CDK 環境。 | 開啟 Windows 命令提示字元，並導覽至可使用 `cdk.json` 檔案的 AWS CDK 應用程式根資料夾 (`\tenant-onboarding-in-saas-architecture-for-silo-model-apg-example`)。執行下列命令進行引導。<pre>cdk bootstrap </pre>如果您已為登入資料建立 AWS 設定檔，請使用 命令搭配您的設定檔。<pre>cdk bootstrap --profile <profile name><br />  </pre> | AWS 管理員、AWS DevOps | 
| 列出 AWS CDK 堆疊。 | 若要列出要建立做為此專案一部分的所有堆疊，請執行下列命令。<pre>cdk ls<br />cdk ls --profile <profile name></pre>如果您已為登入資料建立 AWS 設定檔，請使用 命令搭配您的設定檔。<pre>cdk ls --profile <profile name></pre> | AWS 管理員、AWS DevOps | 
| 檢閱要建立的 AWS 資源。 | 若要檢閱將建立為此專案一部分的所有 AWS 資源，請執行下列命令。<pre>cdk diff</pre>如果您已為登入資料建立 AWS 設定檔，請使用 命令搭配您的設定檔。<pre>cdk diff --profile <profile name></pre> | AWS 管理員、AWS DevOps | 
| 使用 AWS CDK 部署所有 AWS 資源。 | 若要部署所有 AWS 資源，請執行下列命令。<pre>cdk deploy --all --require-approval never</pre>如果您已為登入資料建立 AWS 設定檔，請使用 命令搭配您的設定檔。<pre>cdk deploy --all --require-approval never --profile <profile name></pre>部署完成後，請從命令提示中的輸出區段複製 API URL，如下列範例所示。<pre>Outputs:<br />TenantOnboardingInfraStack.TenantOnboardingAPIEndpoint42E526D7 = https://j2qmp8ds21i1i.execute-api.us-west-2.amazonaws.com/prod/</pre> | AWS 管理員、AWS DevOps | 

### 驗證功能
<a name="verify-the-functionality"></a>


| 任務 | Description | 所需的技能 | 
| --- | --- | --- | 
| 建立新的租用戶。 | 若要建立新的租用戶，請傳送下列 curl 請求。<pre>curl -X POST <TenantOnboardingAPIEndpoint* from CDK Output>tenant -d '{"Name":"Tenant123", "Description":"Stack for Tenant123"}'</pre>將預留位置變更為 AWS CDK `<TenantOnboardingAPIEndpoint* from CDK Output>`的實際值，如下列範例所示。<pre>curl -X POST https://j2qmp8ds21i1i.execute-api.us-west-2.amazonaws.com/prod/tenant -d '{"Name":"Tenant123", "Description":"test12"}'</pre>下列範例顯示輸出。<pre>{"message": "A new tenant added - 5/4/2022 7:11:30 AM"}</pre> | 應用程式開發人員、AWS 管理員、AWS DevOps | 
| 驗證 DynamoDB 中新建立的租戶詳細資訊。 | 若要在 DynamoDB 中驗證新建立的租戶詳細資訊，請執行下列步驟。[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/tenant-onboarding-in-saas-architecture-for-the-silo-model-using-c-and-aws-cdk.html) | 應用程式開發人員、AWS 管理員、AWS DevOps | 
| 驗證新租用戶的堆疊建立。 | 根據 CloudFormation 範本，確認新堆疊已成功使用新建立租用戶的基礎設施建立和佈建。[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/tenant-onboarding-in-saas-architecture-for-the-silo-model-using-c-and-aws-cdk.html) | 應用程式開發人員、AWS 管理員、AWS DevOps | 
| 刪除租戶堆疊。 | 若要刪除租戶堆疊，請傳送下列 curl 請求。<pre>curl -X DELETE <TenantOnboardingAPIEndpoint* from CDK Output>tenant/<Tenant Name from previous step></pre>將預留位置`<TenantOnboardingAPIEndpoint* from CDK Output>`變更為 AWS CDK 的實際值，並將 `<Tenant Name from previous step>`變更為上一個租用戶建立步驟的實際值，如下列範例所示。<pre>curl -X DELETE https://j2qmp8ds21i1i.execute-api.us-west-2.amazonaws.com/prod/tenant/Tenant123</pre>下列範例顯示輸出。<pre>{"message": "Tenant destroyed - 5/4/2022 7:14:48 AM"}</pre> | 應用程式開發人員、AWS DevOps、AWS 管理員 | 
| 驗證現有租用戶的堆疊刪除。 | 若要確認現有租用戶堆疊已刪除，請執行下列步驟：[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/tenant-onboarding-in-saas-architecture-for-the-silo-model-using-c-and-aws-cdk.html) | 應用程式開發人員、AWS 管理員、AWS DevOps | 

### 清除
<a name="clean-up"></a>


| 任務 | Description | 所需的技能 | 
| --- | --- | --- | 
| 銷毀環境。 | 在清除堆疊之前，請確定下列事項：[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/tenant-onboarding-in-saas-architecture-for-the-silo-model-using-c-and-aws-cdk.html)測試完成後，AWS CDK 可以透過執行下列命令來銷毀所有堆疊和相關資源。<pre>cdk destroy --all;</pre>如果您已為登入資料建立 AWS 設定檔，請使用該設定檔。確認堆疊刪除提示以刪除堆疊。 | AWS 管理員、AWS DevOps | 
| 清除 Amazon CloudWatch Logs。 | 堆疊刪除程序不會清除堆疊產生的 CloudWatch Logs （日誌群組和日誌）。使用 CloudWatch 主控台或 API 手動清除 CloudWatch 資源。 | 應用程式開發人員、AWS DevOps、AWS 管理員 | 

## 相關資源
<a name="tenant-onboarding-in-saas-architecture-for-the-silo-model-using-c-and-aws-cdk-resources"></a>
+ [AWS CDK .NET 研討會](https://cdkworkshop.com/40-dotnet.html)
+ [在 C\$1 中使用 AWS CDK](https://docs.aws.amazon.com/cdk/v2/guide/work-with-cdk-csharp.html)
+ [CDK .NET 參考](https://docs.aws.amazon.com/cdk/api/v2/dotnet/api/index.html)

## 其他資訊
<a name="tenant-onboarding-in-saas-architecture-for-the-silo-model-using-c-and-aws-cdk-additional"></a>

**控制平面技術堆疊**

以 .NET 撰寫的 CDK 程式碼用於佈建控制平面基礎設施，其中包含下列資源：

1. **API Gateway**

   做為控制平面堆疊的 REST API 進入點。

1. **租用戶加入 Lambda 函數**

   此 Lambda 函數是由 API Gateway 使用 m 方法啟動。

   POST 方法 API 請求會導致 (`tenant name`、`tenant description`) 插入 DynamoDB `Tenant Onboarding`資料表。

   在此程式碼範例中，租用戶名稱也會用作租用戶堆疊名稱的一部分，以及該堆疊內資源的名稱。這是為了讓這些資源更容易識別。此租用戶名稱在整個設定中必須是唯一的，以避免衝突或錯誤。詳細的輸入驗證設定會在 [IAM 角色](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles.html)文件和*限制*一節中說明。

   DynamoDB 資料表的持久性程序只有在未用於資料表中任何其他記錄時，才會成功。

   在這種情況下，租戶名稱是此表格的分割區索引鍵，因為只有分割區索引鍵可以用作`PutItem`條件表達式。

   如果先前從未記錄過租戶名稱，則記錄將成功儲存至資料表。

   不過，如果 資料表中的現有記錄已使用租用戶名稱，則操作將會失敗並啟動 DynamoDB `ConditionalCheckFailedException`例外狀況。例外狀況將用於傳回失敗訊息 (`HTTP BadRequest`)，指出租用戶名稱已存在。

   `DELETE` 方法 API 請求會從 `Tenant Onboardin`g 資料表中移除特定租用戶名稱的記錄。

   即使記錄不存在，此範例中的 DynamoDB 記錄刪除仍會成功。

   如果目標記錄存在且已刪除，則會建立 DynamoDB 串流記錄。否則，將不會建立任何下游記錄。

1. **啟用 Amazon DynamoDB Streams 的租戶加入 DynamoDB **

   這會記錄租戶中繼資料資訊，而任何記錄儲存或刪除都會將串流傳送至 `Tenant Infrastructure` Lambda 函數下游。 

1. **租戶基礎設施 Lambda 函數**

   此 Lambda 函數是由上一個步驟的 DynamoDB 串流記錄啟動。如果記錄是針對`INSERT`事件，它會叫用 AWS CloudFormation，以使用存放在 S3 儲存貯體中的 CloudFormation 範本建立新的租用戶基礎設施。如果記錄適用於 `REMOVE`，則會根據串流記錄的 `Tenant Name` 欄位啟動現有堆疊的刪除。

1. **S3 bucket (S3 儲存貯體)**

   這是用於存放 CloudFormation 範本。

1. **每個 Lambda 函數的 IAM 角色和 CloudFormation 的服務角色**

   每個 Lambda 函數都有其唯一的 IAM 角色，具有實現其任務[的最低權限許可](https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#grant-least-privilege)。例如，`Tenant On-boarding`Lambda 函數具有 DynamoDB 的讀取/寫入存取權，Lambda `Tenant Infrastructure` 函數只能讀取 DynamoDB 串流。

   為租戶堆疊佈建建立自訂 CloudFormation 服務角色。此服務角色包含 CloudFormation 堆疊佈建的其他許可 （例如 AWS KMS 金鑰）。這會在 Lambda 和 CloudFormation 之間分割角色，以避免單一角色 （基礎設施 Lambda 角色） 的所有許可。

   允許強大動作 （例如建立和刪除 CloudFormation 堆疊） 的許可會遭到鎖定，且僅允許在以 開頭的資源上`tenantcluster-`進行。例外狀況是 AWS KMS，因為其資源命名慣例。從 API 擷取的租用戶名稱將與其他驗證檢查`tenantcluster-`一起加上 （僅含破折號的英數字元，且限制為少於 30 個字元，以符合大多數 AWS 資源命名）。這可確保租戶名稱不會意外導致核心基礎設施堆疊或資源中斷。

**租戶技術堆疊**

CloudFormation 範本存放在 S3 儲存貯體中。範本會佈建租戶特定的 AWS KMS 金鑰、CloudWatch 警示、SNS 主題、SQS 佇列和 [SQS 政策](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-using-identity-based-policies.html)。

Amazon SNS 和 Amazon SQS 會將 AWS KMS 金鑰用於其訊息的資料加密。[AwsSolutions-SNS2 和 AwsSolutions-SQS2](https://github.com/cdklabs/cdk-nag/blob/main/RULES.md) 的安全實務建議您使用加密設定 Amazon SNS 和 Amazon SQS。不過，使用 AWS 受管金鑰時，CloudWatch 警示不適用於 Amazon SNS，因此在這種情況下，您必須使用客戶受管金鑰。如需詳細資訊，請參閱 [AWS 知識中心](https://aws.amazon.com/premiumsupport/knowledge-center/cloudwatch-receive-sns-for-alarm-trigger/)。

SQS 政策用於 Amazon SQS 佇列，以允許建立的 SNS 主題將訊息傳遞至佇列。如果沒有 SQS 政策，存取將被拒絕。如需詳細資訊，請參閱 [Amazon SNS 文件](https://docs.aws.amazon.com/sns/latest/dg/subscribe-sqs-queue-to-sns-topic.html#SendMessageToSQS.sqs.permissions)。

# 使用 CQRS 和事件來源將整體分解為微服務
<a name="decompose-monoliths-into-microservices-by-using-cqrs-and-event-sourcing"></a>

*Rodolfo Jr. Cerrada、Dmitry Gulin 和 Tabby Ward，Amazon Web Services*

## 總結
<a name="decompose-monoliths-into-microservices-by-using-cqrs-and-event-sourcing-summary"></a>

此模式結合兩種模式，同時使用命令查詢責任分離 (CQRS) 模式和事件來源模式。CQRS 模式會區隔命令和查詢模型的責任。事件來源模式會利用非同步事件驅動的通訊來改善整體使用者體驗。

您可以使用 CQRS 和 Amazon Web Services (AWS) 服務獨立維護和擴展每個資料模型，同時將整體應用程式重構為微服務架構。然後，您可以使用事件來源模式，將資料從命令資料庫同步到查詢資料庫。

此模式使用包含解決方案 (\$1.sln) 檔案的範例程式碼，您可以使用最新版本的 Visual Studio 開啟該檔案。此範例包含獎勵 API 程式碼，示範 CQRS 和事件來源如何在 AWS 無伺服器和傳統或內部部署應用程式中運作。

若要進一步了解 CQRS 和事件來源，請參閱[其他資訊](#decompose-monoliths-into-microservices-by-using-cqrs-and-event-sourcing-additional)一節。

## 先決條件和限制
<a name="decompose-monoliths-into-microservices-by-using-cqrs-and-event-sourcing-prereqs"></a>

**先決條件**
+ 作用中的 AWS 帳戶
+ Amazon CloudWatch
+ Amazon DynamoDB 資料表
+ Amazon DynamoDB Streams
+ AWS Identity and Access Management (IAM) 存取金鑰和私密金鑰；如需詳細資訊，請參閱*相關資源*區段中的影片
+ AWS Lambda
+ 熟悉 Visual Studio
+ 熟悉 AWS Toolkit for Visual Studio；如需詳細資訊，請參閱*相關資源*區段中的 *AWS Toolkit for Visual Studio 示範*影片

**產品版本**
+ [Visual Studio 2019 Community Edition](https://visualstudio.microsoft.com/downloads/)。
+ [AWS Toolkit for Visual Studio 2019](https://aws.amazon.com/visualstudio/)。
+ .NET Core 3.1。此元件是 Visual Studio 安裝中的選項。若要在安裝期間包含 .NET Core，請選取 **NET Core 跨平台開發**。

**限制**
+ 傳統內部部署應用程式 (ASP.NET Core Web API 和資料存取物件） 的範例程式碼不會隨附資料庫。不過，它隨附記憶體`CustomerData`內物件，可做為模擬資料庫。提供的程式碼足以讓您測試模式。

## Architecture
<a name="decompose-monoliths-into-microservices-by-using-cqrs-and-event-sourcing-architecture"></a>

**來源技術堆疊**
+ ASP.NET Core Web API 專案
+ IIS Web 伺服器
+ 資料存取物件
+ CRUD 模型

**來源架構**

在來源架構中，CRUD 模型在一個應用程式中包含命令和查詢介面。如需範例程式碼，請參閱 `CustomerDAO.cs`（已連接）。

![\[應用程式、服務介面、客戶 CRUD 模型和資料庫之間的連線。\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/images/pattern-img/9f1bc700-def4-4201-bb2d-f1fa27404f15/images/1cd3a84c-12c7-4306-99aa-23f2c53d3cd3.png)


**目標技術堆疊**
+ Amazon DynamoDB
+ Amazon DynamoDB Streams
+ AWS Lambda
+ （選用） Amazon API Gateway
+ （選用） Amazon Simple Notification Service (Amazon SNS)

**目標架構**

在目標架構中，命令和查詢界面會分開。下圖中顯示的架構可以使用 API Gateway 和 Amazon SNS 擴充。如需詳細資訊，請參閱[其他資訊](#decompose-monoliths-into-microservices-by-using-cqrs-and-event-sourcing-additional)一節。

![\[與無伺服器 Customer Command 和 Customer Query 微服務連線的應用程式。\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/images/pattern-img/9f1bc700-def4-4201-bb2d-f1fa27404f15/images/1c665697-e3ac-4ef4-98d0-86c2cbf164c1.png)


1. 命令 Lambda 函數會在資料庫上執行寫入操作，例如建立、更新或刪除。

1. 查詢 Lambda 函數會在資料庫上執行讀取操作，例如取得或選取。

1. 此 Lambda 函數會處理來自 命令資料庫的 DynamoDB 串流，並更新查詢資料庫以進行變更。

## 工具
<a name="decompose-monoliths-into-microservices-by-using-cqrs-and-event-sourcing-tools"></a>

**工具**
+ [Amazon DynamoDB](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Introduction.html) – Amazon DynamoDB 是全受管的 NoSQL 資料庫服務，可提供快速且可預測的效能和無縫的可擴展性。
+ [Amazon DynamoDB Streams](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Streams.html) – DynamoDB Streams 會擷取任何 DynamoDB 資料表中項目層級修改的時間順序序列。然後，它會將此資訊存放在日誌中長達 24 小時。靜態加密功能會加密 DynamoDB Streams 中的資料。
+ [AWS Lambda](https://docs.aws.amazon.com/lambda/latest/dg/welcome.html) – AWS Lambda 是一種運算服務，支援執行程式碼，無需佈建或管理伺服器。Lambda 只有在需要時才會執行程式碼，可自動從每天數項請求擴展成每秒數千項請求。只需為使用的運算時間支付費用，一旦未執行程式碼，就會停止計費。
+ [AWS 管理主控台](https://docs.aws.amazon.com/awsconsolehelpdocs/latest/gsg/learn-whats-new.html) – AWS 管理主控台是一種 Web 應用程式，包含用於管理 AWS 服務的廣泛服務主控台集合。
+ [Visual Studio 2019 Community Edition](https://visualstudio.microsoft.com/downloads/) – Visual Studio 2019 是整合式開發環境 (IDE)。開放原始碼參與者可免費使用 Community Edition。在此模式中，您將使用 Visual Studio 2019 Community Edition 來開啟、編譯和執行範例程式碼。僅供檢視，您可以使用任何文字編輯器或 [Visual Studio 程式碼](https://docs.aws.amazon.com/toolkit-for-vscode/latest/userguide/welcome.html)。
+ [AWS Toolkit for Visual Studio](https://docs.aws.amazon.com/toolkit-for-visual-studio/latest/user-guide/welcome.html) – AWS Toolkit for Visual Studio 是 Visual Studio IDE 的外掛程式。AWS Toolkit for Visual Studio 可讓您更輕鬆地開發、偵錯和部署使用 AWS 服務的 .NET 應用程式。

**Code**

已連接範例程式碼。如需部署範例程式碼的指示，請參閱 *Epics* 一節。

## 史詩
<a name="decompose-monoliths-into-microservices-by-using-cqrs-and-event-sourcing-epics"></a>

### 開啟並建置解決方案
<a name="open-and-build-the-solution"></a>


| 任務 | Description | 所需的技能 | 
| --- | --- | --- | 
| 開啟解決方案。 | [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/decompose-monoliths-into-microservices-by-using-cqrs-and-event-sourcing.html) | 應用程式開發人員 | 
| 建置解決方案。 | 開啟解決方案的內容 （按一下滑鼠右鍵） 選單，然後選擇**建置解決方案**。這將建置和編譯解決方案中的所有專案。它應該可以成功編譯。Visual Studio Solution Explorer 應會顯示目錄結構。[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/decompose-monoliths-into-microservices-by-using-cqrs-and-event-sourcing.html) | 應用程式開發人員 | 

### 建置 DynamoDB 資料表
<a name="build-the-dynamodb-tables"></a>


| 任務 | Description | 所需的技能 | 
| --- | --- | --- | 
| 提供登入資料。 | 如果您還沒有存取金鑰，請參閱*相關資源*一節中的影片。[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/decompose-monoliths-into-microservices-by-using-cqrs-and-event-sourcing.html) | 應用程式開發人員、資料工程師、DBA | 
| 建置專案。 | 若要建置專案，請開啟 **AwS.APG.CQRSES.Build** 專案的內容 （按一下滑鼠右鍵） 選單，然後選擇**建置**。 | 應用程式開發人員、資料工程師、DBA | 
| 建置和填入資料表。 | 若要建置資料表並填入種子資料，請開啟 **AwS.APG.CQRSES.Build** 專案的內容 （按一下滑鼠右鍵） 選單，然後選擇**偵錯**、**啟動新執行個體**。 | 應用程式開發人員、資料工程師、DBA | 
| 驗證資料表建構和資料。 | 若要驗證，請導覽至 **AWS Explorer**，然後展開 **Amazon DynamoDB**。它應該會顯示資料表。開啟每個資料表以顯示範例資料。 | 應用程式開發人員、資料工程師、DBA | 

### 執行本機測試
<a name="run-local-tests"></a>


| 任務 | Description | 所需的技能 | 
| --- | --- | --- | 
| 建置 CQRS 專案。 | [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/decompose-monoliths-into-microservices-by-using-cqrs-and-event-sourcing.html) | 應用程式開發人員、測試工程師 | 
| 建置事件來源專案。 | [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/decompose-monoliths-into-microservices-by-using-cqrs-and-event-sourcing.html) | 應用程式開發人員、測試工程師 | 
| 執行測試。 | 若要執行所有測試，請選擇**檢視**、**測試總**管，然後選擇在**檢視中執行所有測試**。所有測試都應通過，以綠色核取記號圖示表示。  | 應用程式開發人員、測試工程師 | 

### 將 CQRS Lambda 函數發佈至 AWS
<a name="publish-the-cqrs-lambda-functions-to-aws"></a>


| 任務 | Description | 所需的技能 | 
| --- | --- | --- | 
| 發佈第一個 Lambda 函數。 | [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/decompose-monoliths-into-microservices-by-using-cqrs-and-event-sourcing.html) | 應用程式開發人員、DevOps 工程師 | 
| 驗證函數上傳。 | （選用） 您可以透過導覽至 AWS Explorer 並展開 **AWS Lambda** 來驗證函數是否已成功載入。若要開啟測試視窗，請選擇 Lambda 函數 （按兩下）。 | 應用程式開發人員、DevOps 工程師 | 
| 測試 Lambda 函數。 | [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/decompose-monoliths-into-microservices-by-using-cqrs-and-event-sourcing.html)所有 CQRS Lambda 專案都位於 `CQRS AWS Serverless\CQRS\Command Microservice`和` CQRS AWS Serverless\CQRS\Command Microservice` 解決方案資料夾下。如需解決方案目錄和專案，請參閱[其他資訊](#decompose-monoliths-into-microservices-by-using-cqrs-and-event-sourcing-additional)區段中的**原始程式碼目錄**。 | 應用程式開發人員、DevOps 工程師 | 
| 發佈剩餘的 函數。 | 針對下列專案重複上述步驟：[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/decompose-monoliths-into-microservices-by-using-cqrs-and-event-sourcing.html) | 應用程式開發人員、DevOps 工程師 | 

### 將 Lambda 函數設定為事件接聽程式
<a name="set-up-the-lambda-function-as-an-event-listener"></a>


| 任務 | Description | 所需的技能 | 
| --- | --- | --- | 
| 發佈 Customer and Reward Lambda 事件處理常式。 | 若要發佈每個事件處理常式，請遵循上述史詩中的步驟。專案位於 `CQRS AWS Serverless\Event Source\Customer Event`和 `CQRS AWS Serverless\Event Source\Reward Event` 解決方案資料夾下。如需詳細資訊，請參閱[其他資訊](#decompose-monoliths-into-microservices-by-using-cqrs-and-event-sourcing-additional)區段中的*原始程式碼目錄*。 | 應用程式開發人員 | 
| 連接事件來源 Lambda 事件接聽程式。 | [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/decompose-monoliths-into-microservices-by-using-cqrs-and-event-sourcing.html)接聽程式成功連接到 DynamoDB 資料表後，它將顯示在 Lambda 設計工具頁面上。 | 應用程式開發人員 | 
| 發佈並連接 EventSourceReward Lambda 函數。 | 若要發佈並連接 `EventSourceReward` Lambda 函數，請重複前兩個故事中的步驟，從 **DynamoDB 資料表**下拉式清單中選取 **cqrses-reward-cmd**。 | 應用程式開發人員 | 

### 測試和驗證 DynamoDB 串流和 Lambda 觸發
<a name="test-and-validate-the-dynamodb-streams-and-lambda-trigger"></a>


| 任務 | Description | 所需的技能 | 
| --- | --- | --- | 
| 測試串流和 Lambda 觸發。 | [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/decompose-monoliths-into-microservices-by-using-cqrs-and-event-sourcing.html) | 應用程式開發人員 | 
| 驗證，使用 DynamodDB 獎勵查詢表。 | [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/decompose-monoliths-into-microservices-by-using-cqrs-and-event-sourcing.html) | 應用程式開發人員 | 
| 使用 CloudWatch Logs 驗證。 | [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/decompose-monoliths-into-microservices-by-using-cqrs-and-event-sourcing.html) | 應用程式開發人員 | 
| 驗證 EventSourceCustomer 觸發程序。 | 若要驗證`EventSourceCustomer`觸發條件，請使用`EventSourceCustomer`觸發條件各自的客戶資料表和 CloudWatch 日誌，重複此史詩中的步驟。 | 應用程式開發人員 | 

## 相關資源
<a name="decompose-monoliths-into-microservices-by-using-cqrs-and-event-sourcing-resources"></a>

**參考**
+ [Visual Studio 2019 Community Edition 下載](https://visualstudio.microsoft.com/downloads/)
+ [AWS Toolkit for Visual Studio 下載](https://aws.amazon.com/visualstudio/)
+ [AWS Toolkit for Visual Studio 使用者指南](https://docs.aws.amazon.com/toolkit-for-visual-studio/latest/user-guide/welcome.html)
+ [AWS 上的無伺服器](https://aws.amazon.com/serverless/)
+ [DynamoDB 使用案例和設計模式](https://aws.amazon.com/blogs/database/dynamodb-streams-use-cases-and-design-patterns/)
+ [Martin Fowler CQRS](https://martinfowler.com/bliki/CQRS.html)
+ [Martin Fowler 事件來源](https://martinfowler.com/eaaDev/EventSourcing.html)

**影片**
+ [AWS Toolkit for Visual Studio 示範](https://www.youtube.com/watch?v=B190tcu1ERk)
+ [如何為新的 IAM 使用者建立存取金鑰 ID？](https://www.youtube.com/watch?v=665RYobRJDY)

## 其他資訊
<a name="decompose-monoliths-into-microservices-by-using-cqrs-and-event-sourcing-additional"></a>

**CQRS 和事件來源**

*CQRS*

CQRS 模式會將單一概念操作模型，例如資料存取物件單一 CRUD （建立、讀取、更新、刪除） 模型，分成命令和查詢操作模型。命令模型是指變更狀態的任何操作，例如建立、更新或刪除。查詢模型是指傳回值的任何操作。

![\[具有服務介面、CRUD 模型和資料庫的架構。\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/images/pattern-img/9f1bc700-def4-4201-bb2d-f1fa27404f15/images/3f64756d-681e-4f0e-8034-746263d857b2.png)


1. Customer CRUD 模型包含下列界面：
   + `Create Customer()`
   + `UpdateCustomer()`
   + `DeleteCustomer()`
   + `AddPoints()`
   + `RedeemPoints()`
   + `GetVIPCustomers()`
   + `GetCustomerList()`
   + `GetCustomerPoints()`

隨著您的需求變得更加複雜，您可以從此單一模型方法中移動。CQRS 使用命令模型和查詢模型來區隔寫入和讀取資料的責任。如此一來，資料就可以獨立維護和管理。透過明確的責任分離，每個模型的增強功能不會影響另一個模型。此區隔可改善維護和效能，並降低應用程式的複雜性。

![\[應用程式分成命令和查詢模型，共用單一資料庫。\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/images/pattern-img/9f1bc700-def4-4201-bb2d-f1fa27404f15/images/12db023c-eb81-4c27-bbb9-b085b13176ae.png)


 

1. Customer Command 模型中的界面：
   + `Create Customer()`
   + `UpdateCustomer()`
   + `DeleteCustomer()`
   + `AddPoints()`
   + `RedeemPoints()`

1. 客戶查詢模型中的界面：
   + `GetVIPCustomers()`
   + `GetCustomerList()`
   + `GetCustomerPoints()`
   + `GetMonthlyStatement()`

如需範例程式碼，請參閱*原始程式碼目錄*。

然後，CQRS 模式會解耦資料庫。這種解耦會導致每個服務的整體獨立性，這是微服務架構的主要組成部分。

![\[命令和查詢模型的個別資料庫。\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/images/pattern-img/9f1bc700-def4-4201-bb2d-f1fa27404f15/images/016dbfa8-3bd8-42ee-afa1-38a98986c7d5.png)


 在 AWS 雲端中使用 CQRS，您可以進一步最佳化每個服務。例如，您可以設定不同的運算設定，或在無伺服器或容器型微服務之間進行選擇。您可以使用 Amazon ElastiCache 取代內部部署快取。如果您有內部部署發佈/訂閱訊息，您可以將其取代為 Amazon Simple Notification Service (Amazon SNS)。此外，您可以利用pay-as-you-go定價和各種 AWS 服務，這些服務僅針對您使用的項目付費。

CQRS 包含下列優點：
+ 獨立擴展 – 每個模型都可以調整其擴展策略，以滿足服務的需求。與高效能應用程式類似，分開讀取和寫入可讓模型獨立擴展，以滿足每個需求。您也可以新增或減少運算資源，以滿足某個模型的可擴展性需求，而不會影響另一個模型。
+ 獨立維護 – 查詢和命令模型的分離可改善模型的可維護性。您可以對一個模型進行程式碼變更和增強功能，而不會影響另一個模型。
+ 安全 – 將許可和政策套用至個別模型以進行讀取和寫入更為容易。
+ 最佳化讀取 – 您可以定義針對查詢最佳化的結構描述。例如，您可以為彙總資料定義結構描述，並為事實資料表定義單獨的結構描述。
+ 整合 – CQRS 非常適合事件型程式設計模型。
+ 受管複雜性 – 對查詢和命令模型的分離適用於複雜的網域。

使用 CQRS 時，請記住下列注意事項：
+ CQRS 模式僅適用於應用程式的特定部分，而非整個應用程式。如果實作在不符合 模式的網域上，它可以降低生產力、增加風險並引入複雜性。
+ 此模式最適合具有不平衡讀取和寫入操作的常用模型。
+ 對於大量讀取的應用程式，例如需要時間處理的大型報告，CQRS 可讓您選擇正確的資料庫並建立結構描述來存放彙總資料。這可透過僅處理一次報告資料並將其傾印在彙總資料表中，來改善讀取和檢視報告的回應時間。
+ 對於寫入密集型應用程式，您可以設定用於寫入操作的資料庫，並允許命令微服務在寫入需求增加時獨立擴展。如需範例，請參閱 `AWS.APG.CQRSES.CommandRedeemRewardLambda`和 `AWS.APG.CQRSES.CommandAddRewardLambda` 微服務。

*事件來源*

下一個步驟是使用事件來源，在執行命令時同步查詢資料庫。例如，請考慮下列事件：
+ 新增的客戶獎勵點需要更新查詢資料庫中的客戶總獎勵點或彙總獎勵點。
+ 命令資料庫中會更新客戶的姓氏，這需要更新查詢資料庫中的代理客戶資訊。

在傳統 CRUD 模型中，您可以鎖定資料直到完成交易，以確保資料的一致性。在事件來源中，資料會透過發佈一系列事件來同步，訂閱者將使用該事件來更新其個別資料。

事件來源模式可確保並記錄對資料採取的完整一系列動作，並透過一系列事件發佈。這些事件代表一組對資料所做的變更，該事件的訂閱者必須處理這些變更，才能讓記錄保持最新狀態。訂閱者會使用這些事件，同步訂閱者資料庫中的資料。在這種情況下，這是查詢資料庫。

下圖顯示與 AWS 上的 CQRS 搭配使用的事件來源。

![\[使用 AWS 無伺服器服務的 CQRS 和事件來源模式的微服務架構。\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/images/pattern-img/9f1bc700-def4-4201-bb2d-f1fa27404f15/images/cc9bc84a-60b4-4459-9a5c-2334c69dbb4e.png)


1. 命令 Lambda 函數會在資料庫上執行寫入操作，例如建立、更新或刪除。

1. 查詢 Lambda 函數會在資料庫上執行讀取操作，例如取得或選取。

1. 此 Lambda 函數會從命令資料庫處理 DynamoDB 串流，並更新查詢資料庫以進行變更。您也可以使用此函數來發佈訊息至 Amazon SNS，以便其訂閱者可以處理資料。

1. （選用） Lambda 事件訂閱者會處理 Amazon SNS 發佈的訊息，並更新查詢資料庫。

1. （選用） Amazon SNS 會傳送寫入操作的電子郵件通知。

在 AWS 上，DynamoDB Streams 可以同步查詢資料庫。DynamoDB 會以近乎即時的方式擷取 DynamobDB 資料表中項目層級修改的時間順序，並在 24 小時內持久儲存資訊。

啟用 DynamoDB Streams 可讓資料庫發佈一系列事件，使事件來源模式成為可能。事件來源模式會新增事件訂閱者。事件訂閱者應用程式會使用事件，並根據訂閱者的責任來處理事件。在上圖中，事件訂閱者會將變更推送至 Query DynamoDB 資料庫，以保持資料同步。使用 Amazon SNS、訊息中介裝置和事件訂閱者應用程式會保持架構解耦。

事件來源包含下列優點：
+ 交易資料的一致性
+ 可靠的稽核線索和動作歷史記錄，可用於監控資料中採取的動作
+ 允許微型服務等分散式應用程式跨環境同步其資料
+ 每當狀態變更時，可靠發佈事件
+ 重建或重播過去狀態
+ 鬆散耦合的實體，交換事件以從單體應用程式遷移到微服務
+ 減少並行更新所造成的衝突；事件來源可避免直接在資料存放區中更新物件的需求
+ 解耦任務和事件的彈性和可擴展性
+ 外部系統更新
+ 在單一事件中管理多個任務

使用事件來源時，請記住下列注意事項：
+ 由於來源訂閱者資料庫之間的資料更新有所延遲，復原變更的唯一方法是將補償事件新增至事件存放區。
+ 實作事件來源具有自其程式設計風格不同的學習曲線。

**測試資料**

成功部署後，請使用下列測試資料來測試 Lambda 函數。

**CommandCreate 客戶**

```
{  "Id":1501,  "Firstname":"John",  "Lastname":"Done",  "CompanyName":"AnyCompany",  "Address": "USA",  "VIP":true }
```

**CommandUpdate 客戶**

```
{  "Id":1501,  "Firstname":"John",  "Lastname":"Doe",  "CompanyName":"Example Corp.",  "Address": "Seattle, USA",  "VIP":true }
```

**CommandDelete 客戶**

輸入客戶 ID 做為請求資料。例如，如果客戶 ID 為 151，請輸入 151 做為請求資料。

```
151
```

**QueryCustomerList**

這是空白的。調用時，它會傳回所有客戶。

**CommandAddReward**

這會新增 40 點給 ID 為 1 的客戶 (Richard)。

```
{
  "Id":10101,
  "CustomerId":1,
  "Points":40
}
```

**CommandRedeemReward**

這會扣除 ID 為 1 (Richard) 的客戶 15 點。

```
{
  "Id":10110,
  "CustomerId":1,
  "Points":15
}
```

**QueryReward**

輸入客戶的 ID。例如，輸入 1 表示 Richard，2 表示 Arnav，3 表示 Shirley。

```
2 
```

**原始程式碼目錄**

使用下表做為 Visual Studio 解決方案目錄結構的指南。 

*CQRS 現場部署程式碼範例解決方案目錄*

![\[擴展 Command and Query 服務的解決方案目錄。\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/images/pattern-img/9f1bc700-def4-4201-bb2d-f1fa27404f15/images/4811c2c0-643b-410f-bb87-0b86ec5e194c.png)


**客戶 CRUD 模型**

CQRS 現場部署程式碼範例\$1CRUD Model\$1AWS.APG.CQRSES.DAL 專案

**Customer CRUD 模型的 CQRS 版本**
+ 客戶命令：`CQRS On-Premises Code Sample\CQRS Model\Command Microservice\AWS.APG.CQRSES.Command`專案
+ 客戶查詢：`CQRS On-Premises Code Sample\CQRS Model\Query Microservice\AWS.APG.CQRSES.Query`專案

**命令和查詢微服務**

命令微服務位於解決方案資料夾 下`CQRS On-Premises Code Sample\CQRS Model\Command Microservice`：
+ `AWS.APG.CQRSES.CommandMicroservice` ASP.NET Core API 專案可做為消費者與服務互動的進入點。
+ `AWS.APG.CQRSES.Command` .NET Core 專案是託管命令相關物件和界面的物件。

查詢微服務位於解決方案資料夾 下`CQRS On-Premises Code Sample\CQRS Model\Query Microservice`：
+ `AWS.APG.CQRSES.QueryMicroservice` ASP.NET Core API 專案做為消費者與服務互動的進入點。
+ `AWS.APG.CQRSES.Query` .NET Core 專案是託管查詢相關物件和界面的物件。

*CQRS AWS Serverless 程式碼解決方案目錄*

![\[顯示微服務和事件來源已展開的解決方案目錄。\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/images/pattern-img/9f1bc700-def4-4201-bb2d-f1fa27404f15/images/23f8655c-95ad-422c-b20a-e29dc145e995.png)


 

此程式碼是使用 AWS 無伺服器服務的現場部署程式碼的 AWS 版本。

在 C\$1 .NET Core 中，每個 Lambda 函數都由一個 .NET Core 專案表示。在此模式的範例程式碼中，命令和查詢模型中的每個界面都有單獨的專案。

**使用 AWS 服務的 CQRS**

您可以在 `CQRS AWS Serverless\CQRS`資料夾中找到使用 AWS 無伺服器服務的 CQRS 根解決方案目錄。此範例包含兩種模型：客戶和獎勵。

Customer and Reward 的命令 Lambda 函數位於 `CQRS\Command Microservice\Customer`和 `CQRS\Command Microservice\Reward` 資料夾下。它們包含下列 Lambda 專案：
+ 客戶命令：`CommandDeleteLambda`、 `CommandCreateLambda`和 `CommandUpdateLambda`
+ 獎勵命令： `CommandAddRewardLambda` 和 `CommandRedeemRewardLambda`

客戶和獎勵的查詢 Lambda 函數位於 `CQRS\Query Microservice\Customer`和 `CQRS\QueryMicroservice\Reward`資料夾下。它們包含 `QueryCustomerListLambda`和 `QueryRewardLambda` Lambda 專案。

**CQRS 測試專案**

測試專案位於 `CQRS\Tests` 資料夾下。此專案包含測試指令碼，可自動測試 CQRS Lambda 函數。

**使用 AWS 服務的事件來源**

客戶和獎勵 DynamoDB 串流會啟動下列 Lambda 事件處理常式，以處理和同步查詢資料表中的資料。
+ `EventSourceCustomer` Lambda 函數會映射至客戶資料表 (`cqrses-customer-cmd`) DynamoDB 串流。
+ `EventSourceReward` Lambda 函數會映射至獎勵資料表 (`cqrses-reward-cmd`) DynamoDB 串流。

## 附件
<a name="attachments-9f1bc700-def4-4201-bb2d-f1fa27404f15"></a>

若要存取與本文件相關聯的其他內容，請解壓縮下列檔案： [attachment.zip](samples/p-attach/9f1bc700-def4-4201-bb2d-f1fa27404f15/attachments/attachment.zip)

# 更多模式
<a name="modernization-more-patterns-pattern-list"></a>

**Topics**
+ [使用 AWS PrivateLink 和 Network Load Balancer 在 Amazon EKS 上私下存取容器應用程式](access-container-applications-privately-on-amazon-eks-using-aws-privatelink-and-a-network-load-balancer.md)
+ [使用 AWS Systems Manager 自動化新增或更新 Windows 登錄項目](automate-adding-or-updating-windows-registry-entries-using-aws-systems-manager.md)
+ [使用 DR Orchestrator Framework 自動化跨區域容錯移轉和容錯回復](automate-cross-region-failover-and-failback-by-using-dr-orchestrator-framework.md)
+ [使用 CI/CD 管道自動建置 Java 應用程式並將其部署到 Amazon EKS](automatically-build-and-deploy-a-java-application-to-amazon-eks-using-a-ci-cd-pipeline.md)
+ [使用 AWS CDK 自動為微服務建置 CI/CD 管道和 Amazon ECS 叢集](automatically-build-ci-cd-pipelines-and-amazon-ecs-clusters-for-microservices-using-aws-cdk.md)
+ [使用 BMC AMI Cloud Data 將大型主機資料備份並封存至 Amazon S3](back-up-and-archive-mainframe-data-to-amazon-s3-using-bmc-ami-cloud-data.md)
+ [使用 Amazon EC2 Auto Scaling 和 Systems Manager 建置 Micro Focus Enterprise Server PAC](build-a-micro-focus-enterprise-server-pac-with-amazon-ec2-auto-scaling-and-systems-manager.md)
+ [使用 Amazon DataZone 建置企業資料網格 AWS CDK，以及 AWS CloudFormation](build-enterprise-data-mesh-amazon-data-zone.md)
+ [容器化已由 Blu Age 現代化的大型主機工作負載](containerize-mainframe-workloads-that-have-been-modernized-by-blu-age.md)
+ [使用 Python 將 EBCDIC 資料轉換為 AWS 上的 ASCII](convert-and-unpack-ebcdic-data-to-ascii-on-aws-by-using-python.md)
+ [使用 Micro Focus 轉換具有複雜記錄配置的大型主機資料檔案](convert-mainframe-data-files-with-complex-record-layouts-using-micro-focus.md)
+ [使用、 AWS Amplify Angular 和 Module Federation 建立微型前端的入口網站](create-amplify-micro-frontend-portal.md)
+ [使用 Elastic Beanstalk 部署容器](deploy-containers-by-using-elastic-beanstalk.md)
+ [使用 PostgreSQL 相容 Aurora 全域資料庫模擬 Oracle DR](emulate-oracle-dr-by-using-a-postgresql-compatible-aurora-global-database.md)
+ [在 Quick Sight 中使用 AWS Mainframe Modernization 和 Amazon Q 產生資料洞見](generate-data-insights-by-using-aws-mainframe-modernization-and-amazon-q-in-quicksight.md)
+ [使用 Quick Sight 中的 AWS Mainframe Modernization 和 Amazon Q 產生 Db2 z/OS 資料洞見](generate-db2-zos-data-insights-aws-mainframe-modernization-amazon-q-in-quicksight.md)
+ [遷移至 Amazon ECR 儲存庫時，自動識別重複的容器映像](identify-duplicate-container-images-automatically-when-migrating-to-ecr-repository.md)
+ [使用 K8sGPT 和 Amazon Bedrock 整合實作採用 AI 技術的 Kubernetes 診斷和故障診斷](implement-ai-powered-kubernetes-diagnostics-and-troubleshooting-with-k8sgpt-and-amazon-bedrock-integration.md)
+ [在 AWS Blu Age 現代化大型主機應用程式中實作 Microsoft Entra ID 型身分驗證](implement-entra-id-authentication-in-aws-blu-age-modernized-mainframe-application.md)
+ [在 Amazon API Gateway 中使用自訂網域實作路徑型 API 版本控制](implement-path-based-api-versioning-by-using-custom-domains.md)
+ [使用 Oracle SQL Developer 和 AWS SCT，逐步從 Amazon RDS for Oracle 遷移至 Amazon RDS for PostgreSQL](incrementally-migrate-from-amazon-rds-for-oracle-to-amazon-rds-for-postgresql-using-oracle-sql-developer-and-aws-sct.md)
+ [將stonebranch 通用控制器與 AWS Mainframe Modernization 整合](integrate-stonebranch-universal-controller-with-aws-mainframe-modernization.md)
+ [在多個 AWS 帳戶和 AWS 區域中管理 AWS Service Catalog 產品](manage-aws-service-catalog-products-in-multiple-aws-accounts-and-aws-regions.md)
+ [將 AWS 成員帳戶從 遷移 AWS Organizations 至 AWS Control Tower](migrate-an-aws-member-account-from-aws-organizations-to-aws-control-tower.md)
+ [使用來自 Precisely 的 Connect 將 VSAM 檔案遷移和複寫至 Amazon RDS 或 Amazon MSK](migrate-and-replicate-vsam-files-to-amazon-rds-or-amazon-msk-using-connect-from-precisely.md)
+ [使用 AWS DMS 從 SAP ASE 遷移至 Amazon RDS for SQL Server](migrate-from-sap-ase-to-amazon-rds-for-sql-server-using-aws-dms.md)
+ [將 Oracle 外部資料表遷移至 Amazon Aurora PostgreSQL 相容](migrate-oracle-external-tables-to-amazon-aurora-postgresql-compatible.md)
+ [使用 現代化 CardDemo 大型主機應用程式 AWS Transform](modernize-carddemo-mainframe-app.md)
+ [使用 和 Terraform 現代化 AWS Transform 和部署大型主機應用程式](modernize-mainframe-app-transform-terraform.md)
+ [使用 Rocket Enterprise Server 和 LRS VPSX/MFI AWS 在 上現代化大型主機批次列印工作負載](modernize-mainframe-batch-printing-workloads-on-aws-by-using-rocket-enterprise-server-and-lrs-vpsx-mfi.md)
+ [使用 Micro Focus Enterprise Server 和 LRS VPSX/MFI 將 AWS 上的大型主機線上列印工作負載現代化](modernize-mainframe-online-printing-workloads-on-aws-by-using-micro-focus-enterprise-server-and-lrs-vpsx-mfi.md)
+ [AWS 使用 Rocket Enterprise Server 和 LRS PageCenterX 在 上現代化大型主機輸出管理](modernize-mainframe-output-management-on-aws-by-using-rocket-enterprise-server-and-lrs-pagecenterx.md)
+ [使用 Transfer 系列將大型主機檔案直接移至 Amazon S3](move-mainframe-files-directly-to-amazon-s3-using-transfer-family.md)
+ [使用 AWS CDK 和 GitHub Actions 工作流程最佳化多帳戶無伺服器部署](optimize-multi-account-serverless-deployments.md)
+ [最佳化 AWS Blu Age 現代化應用程式的效能](optimize-performance-aws-blu-age-modernized-application.md)
+ [使用 IaC 原則自動化 Amazon Aurora 全域資料庫的藍/綠部署](p-automate-blue-green-deployments-aurora-global-databases-iac.md)
+ [使用 Precisely Connect 將大型主機資料庫複寫至 AWS](replicate-mainframe-databases-to-aws-by-using-precisely-connect.md)
+ [使用 Amazon ECS Anywhere 在 Amazon WorkSpaces 上執行 Amazon ECS 任務 Amazon ECS Anywhere](run-amazon-ecs-tasks-on-amazon-workspaces-with-amazon-ecs-anywhere.md)
+ [將遙測資料從 AWS Lambda 傳送至 OpenSearch，以進行即時分析和視覺化](send-telemetry-data-from-lambda-to-opensearch-for-analytics-visualization.md)
+ [在多區域、多帳戶組織中設定 CloudFormation 偏離偵測](set-up-aws-cloudformation-drift-detection-in-a-multi-region-multi-account-organization.md)
+ [使用 AWS Lambda 在六邊形架構中建構 Python 專案](structure-a-python-project-in-hexagonal-architecture-using-aws-lambda.md)
+ [使用 LocalStack 和 Terraform Tests 測試 AWS 基礎設施](test-aws-infra-localstack-terraform.md)
+ [使用 AWS Transform 自訂將 Easytrieve 轉換為現代語言](transform-easytrieve-modern-languages.md)
+ [從 ENSA1 升級 SAP Pacemaker 叢集到 ENSA2](upgrade-sap-pacemaker-clusters-from-ensa1-to-ensa2.md)
+ [使用 Amazon Q Developer 作為編碼助理，以提高您的生產力](use-q-developer-as-coding-assistant-to-increase-productivity.md)
+ [在本機驗證帳戶工廠的 Terraform (AFT) 程式碼](validate-account-factory-for-terraform-aft-code-locally.md)