EventBridge 特性介紹|以 IaC 的方式使用 EventBridge

阿里巴巴雲原生發表於2022-04-14

作者:王川(弗丁)

引言

EventBridge 作為構建 EDA 架構的基礎設施,通過一些核心概念和特性提供了靈活豐富的事件收集、處理和路由的能力。對於不少使用者來說,通過控制檯裡的便捷的引導來使用 EventBridge 應該是最快的上手方式。此外,也有很多使用者面臨著大量的雲產品的管理,使用控制檯管理每一個資源的方式變成了沉重的手工操作負擔。

為了解決這個問題,現在已經能夠通過 OpenAPI、terraform 等方式將 EventBridge 的能力方便快捷的帶給使用者。本文將重點介紹 EventBridge 和 IaC 的重點概念和特性,然後演示如何應用 IaC 理念自動化部署 EventBridge 來使用這些概念和特性。

EventBridge 概述

事件驅動架構

事件驅動架構是一種鬆耦合、分散式的驅動架構,收集到某應用產生的事件後實時對事件採取必要的處理,緊接著路由至下游系統,無需等待系統響應。使用事件匯流排 EventBridge 可以構建各種簡單或複雜的事件驅動架構,以標準化的 CloudEvents 1.0 協議連線雲產品和應用、應用和應用等。

事件驅動架構體系架構具備以下三個能力:
事件收集:負責收集各種應用發生的事件,如新建訂單,退換貨訂單等其他狀態變更;
事件處理:對事件進行脫敏處理,並對事件進行初步的過濾和篩選;
事件路由:分析事件內容並將事件路由分發至下游產品。
在這裡插入圖片描述

事件驅動架構具有以下優勢:

• 降低耦合:降低事件生產者和訂閱者的耦合性。事件生產者只需關注事件的發生,無需關注事件如何處理以及被分發給哪些訂閱者;任何一個環節出現故障,都不會影響其他業務正常執行;
非同步執行:事件驅動架構適用於非同步場景,即便是需求高峰期,收集各種來源的事件後保留在事件匯流排中,然後逐步分發傳遞事件,不會造成系統擁塞或資源過剩的情況;
可擴充套件性: 事件驅動架構中路由和過濾能力支援劃分服務,便於擴充套件和路由分發;
敏捷性: 事件驅動架構支援與各種阿里雲產品和應用整合,支援事件路由至任何系統服務,提供各種敏捷高效的部署方案。

使用 EventBridge 構建 EDA 架構

事件匯流排 EventBridge 是阿里雲提供的一款無伺服器事件匯流排服務。EventBridge 提供的幾個核心概念,可以滿足構建 EDA 架構的需要。
在這裡插入圖片描述

事件匯流排 EventBridge 支援以下事件源:

**• 阿里雲官方事件源
• 自定義事件源**

事件匯流排 EventBridge 的事件匯流排包括以下型別:

雲服務專用事件匯流排:一個無需建立且不可修改的內建事件匯流排,用於接收您的阿里雲官方事件源的事件;阿里雲官方事件源的事件只能釋出到雲服務專用匯流排;
自定義事件匯流排:需要您自行建立並管理的事件匯流排,用於接收自定義應用或存量訊息資料的事件;自定義應用或存量訊息資料的事件只能釋出到自定義匯流排。

在 EventBridge 中,一個事件規則包含以下內容:
• 事件模式:用於過濾事件並將事件路由到事件目標;
• 事件目標:包括事件的轉換和處理,負責消費事件。

EventBridge 提供了簡潔的事件模式匹配語法,同時具備靈活的事件轉換能力,後面將會通過演示來展示一些具體的例子。

此外,EventBridge 還提供了一些增強能力,這些能力使得 EDA 架構中流經的事件更加透明,具備了開箱即用的觀測和分析能力:

• 事件追蹤:可以檢視釋出到事件匯流排 EventBridge 的事件內容和處理軌跡;
• 事件分析:對釋出到事件匯流排的各種事件進行查詢分析處理和視覺化圖表展示,以便發現事件內在價值。
在這裡插入圖片描述

IaC 簡介

在介紹完事件匯流排 EventBridge 的相關基礎內容後,接下來一起了解下 IaC。在 DevOps 的實踐中,IaC 是非常重要的部分,通過將基礎設施程式碼化,版本化,便可以輕鬆的藉助版本控制工具來提供 single source of truth、協調多人合作的變更、實施嚴格的 review、藉助一些 CI/CD pipeline 工具(甚至 GitOps)來自動觸發部署。軟體系統的開發者僅付出很小的努力去描述需求,就可以在幾分鐘後得到所需的虛擬機器、網路等雲上的服務,極大的縮短了部署時間,同時還能夠保證多個環境的配置一致性,通過減少人為操作也降低了引入錯誤的概率。

IaC的程式碼實踐中一般有兩種方式,命令式和宣告式。

• 命令式:顧名思義,需要明確發出每一個動作的指令,描述的是 How,比如“建立一臺 xx 規格的 ECS”。程式碼需要對每一步動作的順序仔細編排,處理各種可能的錯誤,尤其要注意處理好每次變更對已經存在的資源的影響,否則稍有不慎就可能造成服務中斷。舉例來說,作為開發者可以通過自己熟悉的程式語言呼叫阿里雲的 OpenAPI 來管理資源,因為這些 API 是類似 Create、Describe、Delete 等操作,這就是一種命令式的 IaC 實踐。

• 宣告式: 意味著開發者僅描述自己的需求終態是什麼樣子,即描述 What,比如“一臺 xx 規格的 ECS”。熟悉 Kubernetes 的同學應該對這個概念很熟悉了。IaC 工具可以通過描述資源之間的依賴關係自動編排順序,如果有已經存在的資源,則比對期望的狀態和實際狀態的差異,並根據差異做出更新;如果不存在,需要進行建立。可以看出,宣告式對開發者非常友好,極大的降低了開發者的心智負擔。

IaC 帶來的優勢:
• 降低成本: 有效管理資源,並減少為此投入的人力;
提升效率:加快資源交付和軟體部署的速度;
風險控制
• 減少錯誤;
• 提高基礎架構一致性;
• 消除配置偏移

terraform 作為 IaC 領域的佼佼者,提供了強大的自動化管理基礎設施的能力。生態豐富,很多雲廠商都提供了官方外掛,阿里雲的大多數產品(包括 EventBridge)都對 terraform 做了很全面的支援,使得跨多雲部署基礎設施變得極其簡單。既然是 IaC,terraform 提供了自己的語言 HCL(hashicorp configuration language),HCL 具有類似 json 的簡潔的語法,通過宣告式的資源描述,可以讓開發者快速上手。

動手實踐

準備工作

• 安裝 terraform cli 工具,可以參見 https://www.terraform.io/cli 的內容。
• 建立一個 tf 檔案 terraform.tf,內容如下(需要替換<>內的值)

provider "alicloud" {
  access_key = "<your access key>"
  secret_key = "<your secret key>"
  region = "<region id>"
}

案例1:通過釘釘監控雲上資源變化

假設一個使用者使用了很多雲上的資源作為生產環境,需要感知線上資源的變更操作,一個可行的方案是利用 EventBridge 將來自於 ActionTrail 的審計事件投遞到使用者的釘釘。
首先根據釘釘官方文件建立一個機器人,記下 webhook url 和加簽的祕鑰,接下來會用到。
建立一個 tf 檔案 1_actiontrail2dingding.tf,內容如下(需要替換<>內的值)

# 案例1:通過釘釘監控雲上資源變化
# 目標:
# - 熟悉部署使用EventBridge的default匯流排
# - 熟悉EventBridge的事件模式匹配
# - 熟悉EventBridge的事件轉換配置
# 宣告一個default匯流排上的規則
resource "alicloud_event_bridge_rule" "audit_notify" {
  # default匯流排預設存在,所以這裡可以直接使用
  event_bus_name = "default"
  rule_name      = "audit_notify"
  description    = "demo"
  # 通過字尾匹配的方式過濾來自所有云產品事件源的ActionTrail:ApiCall事件
  # 其他更多模式匹配的介紹可以查閱文件:https://help.aliyun.com/document_detail/181432.html
  filter_pattern = jsonencode(
    {
      "type" : [
        {
          "suffix" : ":ActionTrail:ApiCall"
        }
      ]
    }
  )
  targets {
    target_id = "test-target"
    endpoint  = "<your dingtalk bot webhook url>"
    # type的取值可以查閱文件:https://registry.terraform.io/providers/aliyun/alicloud/latest/docs/resources/event_bridge_rule#type
    type      = "acs.dingtalk"
    # 每個事件目標都有一組對應的param_list,具體可以查閱文件:https://help.aliyun.com/document_detail/185887.html
    # 每一個param的form關係到事件轉換的配置,可以查閱文件:https://help.aliyun.com/document_detail/181429.html
    param_list {
      resource_key = "URL"
      form         = "CONSTANT"
      value        = "<your dingtalk bot webhook url>"
    }
    param_list {
      resource_key = "SecretKey"
      form         = "CONSTANT"
      value        = "<your dingtalk bot secret key>"
    }
    # 這裡展示了TEMPLATE型別的事件轉換描述
    # value是使用jsonpath引用事件內容的字典,template則是模板內容,EventBridge最終會根據這兩者結合事件本身渲染出這個引數的值
    param_list {
      resource_key = "Body"
      form         = "TEMPLATE"
      value        = jsonencode(
        {
          "source": "$.source",
          "type": "$.type"
          "region": "$.data.acsRegion",
          "accountId" : "$.data.userIdentity.accountId",
          "eventName" : "$.data.eventName",
        }
      )
      template = jsonencode(
        {
          "msgtype" : "text",
          "text" : {
            "content": "來自 $${source} 的 $${type} 審計事件:$${accountId} 在 $${region} 執行了 $${eventName} 操作"
          }
        }
      )
    }
  }
}

在命令列視窗依次執行命令:

• 初始化 terraform init
• 預覽變更 terraform plan
• 應用變更 terraform apply
在這裡插入圖片描述

在雲產品控制檯進行操作,這裡以 KMS 為例

在這裡插入圖片描述

釘釘上收到訊息通知
在這裡插入圖片描述

在 EventBridge 控制檯檢視事件軌跡
在這裡插入圖片描述

案例 2:自定義匯流排觸發 FunctionCompute

假設一個使用者的應用會產生一些事件,其中一個鏈路是通過 FunctionCompute 對這些事件進行彈性的處理。那麼就可以通過 EventBridge 的自定義事件源和函式計算事件目標來實現這個方案。

建立一個模擬對事件進行處理的 python 指令碼檔案 src/index.py,內容如下:

# -*- coding: utf-8 -*-
import logging
def handler(event, context):
  logger = logging.getLogger()
  logger.info('evt: ' + str(event))
  return str(event)

建立一個 tf 檔案 2_trigger_function.tf,內容如下(需要替換<>內的值)

# 案例2:自定義匯流排觸發FunctionCompute
# 目標:
# - 熟悉部署使用EventBridge的自定義匯流排
# - 熟悉"自定義應用"事件源配置
# - 熟悉“FunctionCompute”事件目標配置
# 由於使用者自己產生的事件需要投遞到自定義匯流排,這裡宣告一個叫demo_event_bus的自定義匯流排
resource "alicloud_event_bridge_event_bus" "demo_event_bus" {
  event_bus_name = "demo_event_bus"
  description    = "demo"
}
# 宣告一個在demo_event_bus匯流排上的自定義事件源,用於通過sdk或者控制檯向EventBridge投遞事件
resource "alicloud_event_bridge_event_source" "demo_event_source" {
  event_bus_name         = alicloud_event_bridge_event_bus.demo_event_bus.event_bus_name
  event_source_name      = "demo_event_source"
  description            = "demo"
  linked_external_source = false
}
# 宣告一個叫fc_service的函式計算服務,publish=true意味著會立即部署上傳的函式程式碼。
resource "alicloud_fc_service" "fc_service" {
  name        = "eb-fc-service"
  description = "demo"
  publish     = true
}
# 將前面準備的python指令碼檔案打包成zip用於部署到函式計算
data "archive_file" "code" {
  type        = "zip"
  source_file = "${path.module}/src/index.py"
  output_path = "${path.module}/code.zip"
}
# 宣告一個fc_service服務中的函式,其中filename引用了上面描述的zip包,會將這個程式碼包上傳。
resource "alicloud_fc_function" "fc_function" {
  service     = alicloud_fc_service.fc_service.name
  name        = "eb-fc-function"
  description = "demo"
  filename    = data.archive_file.code.output_path
  memory_size = "128"
  runtime     = "python3"
  handler     = "index.handler"
}
# 宣告一個在demo_event_bus匯流排上的規則
resource "alicloud_event_bridge_rule" "demo_rule" {
  event_bus_name = alicloud_event_bridge_event_bus.demo_event_bus.event_bus_name
  rule_name      = "demo_rule"
  description    = "demo"
  # 通過匹配source過濾來自於前面建立的自定義事件源的事件
  filter_pattern = jsonencode(
    {
      "source" : ["${alicloud_event_bridge_event_source.demo_event_source.id}"]
    }
  )
  targets {
    target_id = "demo-fc-target"
    # type的取值可以查閱文件:https://registry.terraform.io/providers/aliyun/alicloud/latest/docs/resources/event_bridge_rule#type
    type      = "acs.fc.function"
    endpoint  = "acs:fc:<region id>:<your account id>:services/${alicloud_fc_service.fc_service.name}.LATEST/functions/${alicloud_fc_function.fc_function.name}"
    param_list {
      resource_key = "serviceName"
      form         = "CONSTANT"
      value        = alicloud_fc_service.fc_service.name
    }
    param_list {
      resource_key = "functionName"
      form         = "CONSTANT"
      value        = alicloud_fc_function.fc_function.name
    }
    param_list {
      resource_key = "Qualifier"
      form         = "CONSTANT"
      value        = "LATEST"
    }
    # 注意form=ORIGINAL意味著每次投遞事件都會將事件的原始內容作為這個引數的值
    param_list {
      resource_key = "Body"
      form         = "ORIGINAL"
    }
  }
}

在命令列視窗依次執行命令

• 初始化 terraform init
• 預覽變更 terraform plan
• 應用變更 terraform apply
在這裡插入圖片描述

在控制檯模擬自定義事件源釋出事件

在這裡插入圖片描述

在 FunctionCompute 的控制檯頁面檢視函式呼叫日誌
在這裡插入圖片描述

在 EventBridge 控制檯檢視事件軌跡

在這裡插入圖片描述

總結

EventBridge 作為構建 EDA 架構的基礎設施,通過一些核心概念和特性提供了靈活豐富的事件收集、處理和路由的能力,並支援通過 OpenAPI、terraform 等方式將這些能力方便快捷的帶給使用者。本文介紹了 EventBridge 和 IaC 的重點概念和特性,然後演示瞭如何應用 IaC 理念自動化部署 EventBridge 來使用這些概念和特性。

期待大家可以發掘更多利用 EventBridge 快速搭建 EDA 架構的 idea,並使用 terraform 快捷的將這些 idea 變為現實。

相關連結

[1] 阿里雲 terraform 文件
https://help.aliyun.com/produ...

[2] terraform registry 文件
https://registry.terraform.io...

[3] 釘釘官方文件
https://open.dingtalk.com/doc...

想要了解更多 EventBridge 相關資訊,掃描下方二維碼加入釘釘群~

在這裡插入圖片描述

點選此處,即可觀看文章對應的視訊~

相關文章