

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

# 發布訂閱模式
<a name="publish-subscribe"></a>

## 意圖
<a name="publish-subscribe-intent"></a>

發布-訂閱模式 (亦稱為 pub-sub 模式) 是一種消息傳遞模式，可用來將訊息傳送者 (*發布者*) 與感興趣的接收者 (*訂閱用戶*) 解耦。此模式會透過稱為*訊息代理程式*或*路由器* (訊息基礎結構) 的中介發行訊息或事件，藉此實作非同步通訊。發布-訂閱模式會卸除郵件傳遞至訊息基礎結構的責任，藉此增加寄件者的可擴展性和回應能力，讓傳送者可以專注於核心訊息處理。

## 動機
<a name="publish-subscribe-motivation"></a>

在分散式架構中，系統組件通常需要在系統內發生事件時向其他組件提供資訊。發布-訂閱模式會分隔考量，讓應用程式可以專注於其核心功能，而訊息基礎結構則會處理訊息路由和可靠傳遞等通訊責任。發布-訂閱模式會啟用非同步傳訊功能來解耦發布者和訂閱用戶。發布者也可以在沒有訂閱用戶知識的情況下傳送訊息。

## 適用性
<a name="publish-subscribe-applicability"></a>

出現下列情況時，請使用發布-訂閱模式：
+ 如果單一訊息具有不同的工作流程，則需要平行處理。
+ 不需要向多個訂閱用戶廣播訊息，也不需要來自接收者的即時回應。
+ 系統或應用程式可以容忍資料或狀態的最終一致性。
+ 應用程式或元件必須與其他可能使用不同語言、通訊協定或平台的應用程式或服務進行通訊。

## 問題和考量
<a name="publish-subscribe-issues"></a>
+ **訂閱用戶可用性：**發布者不知道訂閱用戶是否正在接聽，而且訂閱用戶可能並未接聽。已發布的訊息本質上是暫時的，如果訂閱用戶無法使用，則可能會導致捨棄。
+ **訊息傳遞保證：**通常，發布-訂閱模式無法保證訊息傳遞給所有訂閱用戶類型，但某些服務 (例如 Amazon Simple Notiﬁcation Service (Amazon SNS) 可以[僅提供一次交付給某](https://docs.aws.amazon.com/sns/latest/dg/fifo-message-dedup.html)些訂閱用戶子集。
+ **存留時間 (TTL)：**訊息有生命週期，如果訊息未在此期間內處理，則會過期。請考慮將已發布的訊息新增至佇列，以便它們可以持續存在，並保證處理時間超過 TTL 期間。
+ **訊息相關性：**生產者可以設置相關性的時間範圍作為訊息資料的一部分，並且可以在此日期之後丟棄該訊息。在決定如何處理訊息之前，請考慮設計消費者來檢查此資訊。
+ **最終一致性：**訊息發布到訂閱用戶使用的時間之間存在延遲。這可能會導致在需要強式一致性時，訂閱用戶資料存放區最終變得一致。當生產者和消費者需要接近實時的互動時，最終一致性也可能是一個問題。
+ **單向通信：**發布-訂閱模式被認為是單向的。如果需要同步回應，則需要具有傳回訂閱通道的雙向傳訊應該考慮使用要求-回覆模式的應用程式。
+ **訊息順序：**不保證訊息排序。如果消費者需要訂購的訊息，建議您使用 [Amazon SNS FIFO 主題](https://docs.aws.amazon.com/sns/latest/dg/fifo-topic-message-ordering.html)來保證訂購。
+ **訊息複製：**根據訊息基礎結構，重複的訊息可以傳遞給消費者。消費者必須被設計為冪等來處理重複的訊息處理。或者，您也可以使用 [Amazon SNS FIFO 主題](https://docs.aws.amazon.com/sns/latest/dg/fifo-topic-message-ordering.html)來保證只能交付一次。
+ **訊息篩選：**消費者通常只對生產者所發布的訊息子集感興趣。提供機制，讓訂閱用戶透過提供主題或內容篩選器來篩選或縮小收到的訊息範圍。
+ **訊息重新顯示：**訊息重新顯示功能可能取決於訊息基礎結構。您還可以根據用例提供自定義實現。
+ **無效信件佇列：**在郵政系統中，無效信件辦事處是處理無法遞送之郵件的設施。在 [pub/sub 傳訊功能](https://aws.amazon.com/pub-sub-messaging/)中，無效字母佇列 (DLQ) 是無法傳遞至已訂閱端點之訊息的佇列。

## 實作
<a name="publish-subscribe-implementation"></a>

### 高層級架構
<a name="publish-subscribe-high-level-arch"></a>

在發布-訂閱模式中，稱為訊息代理程式或路由器的非同步訊息子系統會追蹤訂閱。當生產者發布事件時，訊息基礎結構會傳送訊息給每個消費者。將訊息傳送給訂閱用戶之後，就會從訊息基礎結構中移除，因此無法重新顯示訊息，而新訂閱用戶也看不到該事件。訊息代理程式或路由器會透過下列方式來解耦事件生產者與訊息消費者：
+ 為生產者提供輸入通道，以使用定義的訊息格式來發布封裝成訊息的事件。
+ 為每個訂閱建立個別的輸出通道。*訂閱*是取用者的連線，它們透過此連線接聽與特定輸入通道相關聯的事件訊息。
+ 發布事件時，將訊息從輸入通道複製到所有消費者的輸出通道。

![將訊息從輸入複製到輸出通道。](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/cloud-design-patterns/images/publish-subscribe-1.png)


### 使用 AWS 服務來實作
<a name="publish-subscribe-aws-services"></a>

**Amazon SNS**

Amazon SNS 是一種全受管的發布者-訂閱用戶服務，可提供應用程式至應用程式 (A2A) 傳訊功能以解耦分散式應用程式。它還提供應用程式至人員 (A2P) 訊息，用於傳送簡訊、電子郵件和其他推播通知。

Amazon SNS 提供兩種類型的主題：標準主題和先進先出 (FIFO)。
+ 標準主題支援每秒不限數量的訊息，並提供最佳的排序和重複資料刪除功能。  
![Amazon SNS 中的標準主題。](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/cloud-design-patterns/images/publish-subscribe-2.png)
+ FIFO 主題提供嚴格的排序和重複資料刪除功能，每個 FIFO 主題最多支援每秒 300 則訊息或每秒 10 MB (以先到者為準)。  
![Amazon SNS 中的先進先出主題](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/cloud-design-patterns/images/publish-subscribe-3.png)

下圖顯示如何使用 Amazon SNS 實作發布-訂閱模式。使用者付款後，`Payments` Lambda 函數會將 SNS 訊息傳送至 `Payments` SNS 主題。此 SNS 主題有三個訂閱用戶。每個訂閱用戶都會收到訊息的副本並加以處理。

![如何使用 Amazon SNS 來實作發布-訂閱模式。](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/cloud-design-patterns/images/publish-subscribe-4.png)


**Amazon EventBridge**

當您需要更複雜地將來自多個生產者的訊息跨不同協定路由傳送至訂閱的消費者，或直接和散發訂閱時，可以使用 Amazon EventBridge。EventBridge 也支援以內容為基礎的路由、篩選、排序以及分割或彙總。在下圖中，EventBridge 是用來建立發布-訂閱模式的版本，其中訂閱用戶是使用事件規則來定義。使用者付款後，`Payments` Lambda 函數會根據具有三個指向不同目標的自訂結構描述，使用預設事件匯流排將訊息傳送至 EventBridge。每個微服務都會處理訊息並執行必要的動作。

![如何使用 Amazon EventBridge 來實作發布-訂閱模式。](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/cloud-design-patterns/images/publish-subscribe-5.png)


### 研討會
<a name="publish-subscribe-workshop"></a>
+ [在 AWS 上建立事件驅動架構](https://catalog.us-east-1.prod.workshops.aws/workshops/63320e83-6abc-493d-83d8-f822584fb3cb/en-US/) 
+ [使用 Amazon Simple Queue Service (Amazon SQS) 和 Amazon Simple Notiﬁcation Service (Amazon SNS) 來傳送扇出事件通知](https://aws.amazon.com/getting-started/hands-on/send-fanout-event-notifications/)

## 部落格參考
<a name="publish-subscribe-blog"></a>
+ [選擇無伺服器應用程式的傳訊服務](https://aws.amazon.com/blogs/compute/choosing-between-messaging-services-for-serverless-applications/)
+ [使用適用於 Amazon SNS、Amazon SQS 和 AWS Lambda 的 DLQ 來設計耐用的無伺服器應用程式](https://aws.amazon.com/blogs/compute/designing-durable-serverless-apps-with-dlqs-for-amazon-sns-amazon-sqs-aws-lambda/)
+ [使用 Amazon SNS 傳訊篩選簡化 pub/sub 傳訊](https://aws.amazon.com/blogs/compute/simplify-pubsub-messaging-with-amazon-sns-message-filtering/)

## 相關內容
<a name="publish-subscribe-resources"></a>
+ [pub/sub 傳訊的功能](https://aws.amazon.com/what-is/pub-sub-messaging/)