事件驅動架構在現代軟體開發,特別是微服務和無伺服器架構中扮演著至關重要的角色。理解事件的結構和不同類別事件的應用,是構建鬆散耦合、可擴充套件且具有容錯能力的系統的關鍵。本文詳細介紹了事件的組成(source
、detail
、metadata
),以及設計事件結構時需要遵循的統一性、可擴充套件性和簡潔性原則。此外,更進一步區分了事件類別和事件型別,並分別說明瞭領域事件和營運事件在實際應用中的差異和範例,以及 AWS 事件在無伺服器環境下的應用場景。
事件驅動架構中的事件結構
在事件驅動架構中,事件的結構是非常重要的。一個良好的事件結構可以幫助我們更好地理解和處理事件。下面,我們將探討事件結構的組成和設計原則。
事件結構的組成
一個事件通常由三個部分組成:source
、detail
和 metadata
。其中,source
是事件的來源,detail
是事件的具體內容,metadata
是事件的後設資料。
Source
source
是事件的來源,通常是一個字串值,用於標識事件的來源。
Detail
detail
是事件的具體內容,通常是一個 JSON 物件,用於承載事件的實際資料。這個欄位的值由使用者定義,可以包含任何有關事件的資訊。
Metadata
metadata
是事件的後設資料,通常是一個 JSON 物件,用於包含事件的元資訊。這個欄位可以包含如事件型別、網域名稱、服務名等資訊。
設計原則
設計事件結構時,需要遵循一些原則,以確保事件結構的統一性和易用性。下面是一些設計原則:
- 統一性:應該在組織或業務域級別上統一事件結構,以促進統一性和易用性。
- 可擴充套件性:應該設計事件結構為可擴充套件的,以便於未來的變化和擴充套件。
- 簡潔性:應該盡量簡化事件結構,以減少複雜性和提高效率。
事件結構範例
下面是一個事件結構範例:
{
"source": "example-source",
"detail": {
"metadata": {
"domain": "ecommerce",
"subdomain": "orders",
"service": "payments",
"category": "domain_event",
"type": "data",
"name": "payment_received"
},
"data": {
"customer_id": "730e-4dfb-9166",
"order_number": "123-987-456",
"payment_reference": "cc-visa-9076-cv3s5s",
"payment_type": "creditcard",
"amount": 35.99,
"currency": "GBP",
"paid_at": "2023-12-30T09:12:27Z"
}
}
}
在這個範例中,source
是事件的來源,detail
是事件的具體內容,metadata
是事件的後設資料,data
是事件的實際資料。
事件類別在無伺服器開發中的應用
在軟體工程中,事件的分類別一直是一個重要的討論話題。從商業角度來看,領域事件(Domain Events)是最重要的事件。然而,負責維護分散式系統的人可能會說,營運事件(Operational Events)同樣重要。在無伺服器開發中,瞭解不同類別的事件並將其應用於適當的情境是非常有益的。這些事件類別包括:
- 領域事件(Domain Events)
- 營運事件(Operational Events)
- AWS 事件(AWS Events)
- 內部事件(Internal Events)
- 本地事件(Local Events)
- 轉換事件(Transformed Events)
- 自定義事件(Custom Events)
事件類別與事件型別的區別
在前一節中提到的事件類別,是根據事件的源頭、邊界和所有權進行分類別的一種邏輯方法。這是對事件進行分類別的一種方式,但它可能會因團隊和組織而異。事件類別和事件型別這兩個術語經常被交替使用,但沒有明確的規範來解釋如何區分它們。事件的型別反映了其目的,並且明確地與事件相關聯。儘管事件主要是資料的封套,每個資料集代表系統中發生的某些事情,但如果您從純主義者轉變為實用主義者,您很快就會找到方法為您的事件新增更多意義。例如,您可以在後設資料部分新增一個欄位來指示事件型別。
以下是事件驅動架構中的一些常見事件型別:
- 命令(Command):發布者指示訂閱者執行某個動作的指令。
- 資料(Data):發布並忘記的資訊性事件。資料事件只是某些資料的攜帶者。
- 查詢(Query):發布者要求的資訊請求。與請求型別相似,但發布者正在請求資料,而不是服務。
- 請求(Request):對下游消費者的履行請求。例如,如果服務 A 處理訂單,它可能需要服務 B 將一些資料傳送到另一個系統,以便最終設定標誌或資料專案。服務 A 引發請求事件並在從服務 B 收到回應事件時更新其系統。
- 回應(Response):由玄貓發出的事件。
- 狀態(Status):攜帶某些活動狀態資訊的資訊性事件。例如,客戶更新動作失敗,第三方系統下線等。
- 任務(Task):用於協調多個任務作為更高層次任務的一部分的事件型別,由玄貓處理。當您有跨多個微服務的工作流程時,它很有用。
領域事件
領域事件代表著對業務有重大影響的事件,並由玄貓報告。根據 Martin Fowler 的說法,它是“捕捉了對領域有影響的有趣事情的記憶”。在企業中,領域事件在不同領域的系統之間流動,連線著不同系統或企業中的資料流,以描繪使用者在不同系統中的旅程。
以下是領域事件的一個典型範例,當收到付款時發出:
{
"detail": {
"metadata": {
"version": "1.0",
"created_at": "2023-12-30T09:12:27Z",
"trace_id": "skdj834sd3-j3ns-cmass23",
"domain": "ecommerce",
"subdomain": "orders",
"service": "payments",
"category": "domain_event",
"type": "data",
"name": "payment_received"
},
"data": {
"customer_id": "730e-4dfb-9166",
"order_number": "123-987-456",
"payment_reference": "cc-visa-9076-cv3s5s",
"payment_type": "creditcard",
"amount": 35.99,
"currency": "GBP",
"paid_at": "2023-12-30T09:12:27Z"
}
}
}
領域事件的主要區別在於它代表了在整個組織中有效的業務資料。領域事件通常被歸類別為業務機密,很少與外部系統分享。
營運事件
營運事件傳達應用程式的營運健康狀態、API 端點的延遲、微服務的佈署狀態等資訊。營運事件通常與業務功能區分開來,幫助繪製業務功能和系統行為之間的界限。
以下是營運事件的一個範例,指示服務的正常執行時間發生了變化:
{
"metadata": {
"version": "1.0",
"created_at": "2023-12-20T02:22:27Z",
"trace_id": "skdj834sd3-j3ns-cmass23",
"domain": "holiday-travel",
"subdomain": "flight-booking",
"service": "service-status-checker",
"category": "operational_event",
"type": "status",
"status": "down"
}
}
圖表翻譯:
flowchart TD A[領域事件] --> B[業務邏輯] B --> C[營運邏輯] C --> D[系統行為] D --> E[界限劃分]
圖表描述了領域事件、業務邏輯、營運邏輯、系統行為之間的關係,以及它們如何劃分界限。
內容解密:
領域事件和營運事件是兩種不同的事件類別,它們在無伺服器開發中扮演著重要角色。領域事件代表著對業務有重大影響的事件,而營運事件則傳達了應用程式的營運健康狀態和系統行為。瞭解這些事件類別和型別可以幫助開發人員設計出更好的無伺服器架構,並提高系統的可擴充套件性和可維護性。
事件驅動架構:AWS 事件的應用
在設計 serverless 微服務時,瞭解事件驅動架構的重要性不言而喻。AWS 事件是由 AWS 平臺產生的事件,與應用程式發出的事件有所不同。這些事件是由 AWS 服務產生的,例如當使用者上傳檔案到 S3 儲存桶時,就會觸發一個事件。
什麼是 AWS 事件?
AWS 事件是由 AWS 服務產生的事件,例如 S3、SQS、DynamoDB 等。這些事件可以用來觸發 Lambda 函式、API Gateway 等服務。AWS 事件可以分為兩類別:域事件和操作事件。域事件是由應用程式產生的,例如使用者登入或下單等。操作事件是由 AWS 服務產生的,例如 S3 上傳檔案或 SQS 收到訊息等。
AWS 事件的應用
AWS 事件可以用來觸發各種服務,例如 Lambda 函式、API Gateway 等。以下是一個例子,當使用者上傳檔案到 S3 儲存桶時,就會觸發一個事件。
{
"Records": [
{
"eventVersion": "2.0",
"eventSource": "aws:s3",
"awsRegion": "eu-west-1",
"eventTime": "2023-12-01T00:00:00+08:00",
"eventName": "ObjectCreated:Put",
"userIdentity": {
"principalId": "EXAMPLE"
},
"requestParameters": {
"sourceIPAddress": "127.0.0.1"
},
"responseElements": {
"x-amz-request-id": "EXAMPLE123456789",
"x-amz-id-2": "EXAMPLE123/5678abcdefghi/mnopqrsEFGH"
},
"s3": {
"s3SchemaVersion": "1.0",
"configurationId": "testConfigRule",
"bucket": {
"name": "festival-promotions",
"ownerIdentity": {
"principalId": "EXAMPLE"
},
"arn": "arn:aws:s3:::festival-promotions"
}
}
}
]
}
內容解密:
上述 JSON 物件描述了一個 S3 事件,當使用者上傳檔案到 festival-promotions
儲存桶時,就會觸發這個事件。事件包含了檔案上傳的詳細資訊,例如檔案名稱、儲存桶名稱、上傳時間等。這個事件可以用來觸發 Lambda 函式,進行檔案處理或其他操作。
圖表翻譯:
flowchart TD A[使用者上傳檔案] --> B[S3 事件] B --> C[Lambda 函式] C --> D[檔案處理]
圖表說明:
上述流程圖描述了使用者上傳檔案到 S3 儲存桶時,觸發 S3 事件,然後觸發 Lambda 函式,進行檔案處理。這個流程展示了 AWS 事件的應用,如何使用 AWS 服務來實作事件驅動架構。
事件驅動架構與微服務開發
事件驅動架構(Event-Driven Architecture,EDA)是一種軟體設計模式,允許應用程式之間透過事件進行溝通。這種架構在微服務開發中尤其重要,因為它可以幫助實作應用程式之間的鬆散耦合。
事件型別
事件可以分為幾種型別,包括:
- 自定義事件:這是指應用程式發出的任何事件,例如使用者註冊、訂單建立等。
- 內部事件:這是指在應用程式內部發生的事件,例如伺服器錯誤等。
- 轉換事件:這是指在事件傳遞過程中對事件進行轉換的事件,例如將事件從一個格式轉換為另一個格式。
事件驅動架構的優點
事件驅動架構有幾個優點,包括:
- 鬆散耦合:事件驅動架構可以幫助實作應用程式之間的鬆散耦合,這意味著應用程式之間不需要知道彼此的具體實作細節。
- 可擴充套件性:事件驅動架構可以幫助提高系統的可擴充套件性,因為新的應用程式可以輕鬆地加入到系統中。
- 容錯性:事件驅動架構可以幫助提高系統的容錯性,因為當一個應用程式出錯時,不會影響到其他應用程式。
事件生產者和事件釋出最佳實踐
事件生產者是指建立和釋出事件的應用程式。以下是幾個事件釋出最佳實踐:
- 事件生產者應該與消費者無關:這意味著事件生產者不應該假設消費者的具體實作細節。
- 每個事件應該攜帶明確的識別資訊:這包括了域、服務、函式等資訊。
- 域事件應該被視為資料合約:這意味著域事件應該遵守特定的模式和結構。
內容解密:
以上內容簡要介紹了事件驅動架構的基本概念、優點和最佳實踐。透過瞭解這些知識,開發人員可以更好地設計和實作微服務系統。同時,瞭解不同型別的事件和如何使用它們來提高系統的可擴充套件性和容錯性也是非常重要的。
圖表翻譯:
graph LR A[應用程式] -->|釋出事件|> B[事件匯流排] B -->|觸發事件|> C[其他應用程式] C -->|處理事件|> D[傳回結果] D -->|傳回結果|> A
這個圖表展示了應用程式如何透過事件匯流排釋出和接收事件,並如何觸發其他應用程式的處理。
從技術架構視角來看,定義清晰且一致的事件結構是建構穩健事件驅動架構的根本。本文深入探討了事件結構的組成要素(source
、detail
、metadata
)以及設計原則,並闡明瞭事件類別(領域事件、營運事件、AWS 事件等)和事件型別(命令、資料、查詢等)的區分和應用場景。分析顯示,清晰的事件結構設計能提升系統的互通性、可維護性和可擴充套件性,然而,實際應用中仍需考量不同事件型別的特性和處理策略,例如領域事件的保密性和營運事件的監控需求。技術團隊應制定明確的事件命名和版本控制規範,並確保事件資料的有效性與一致性,才能避免事件風暴的產生並充分發揮事件驅動架構的優勢。玄貓認為,隨著微服務和無伺服器架構的普及,事件驅動架構將成為未來分散式系統的主流設計模式,深入理解和掌握事件結構設計將是技術團隊的核心競爭力。