跳到內容

使用 Automatiko 的工作流程作為函數流

發佈於:2021-12-17, 修訂於:2024-01-17

使用 Automatiko 的工作流程作為函數流

作者:Maciej Swiderski,OpenEnterprise 的軟體工程師

許多組織開始將無伺服器視為一種建構可以利用雲端的業務邏輯的方法。乍看之下,要完全依賴代表獨立邏輯片段的函數並不是一件容易的事。存在失去全局視圖的風險,因此無法完全控制日常運作。

在考慮無伺服器、函數和事件時,Knative 提供了一個很好的基礎。Knative Eventing 特別出色,這要歸功於它與 Cloud Events 的整合以及各種代理程式實作,這些實作從事件傳遞的角度提供了不同的特性。

同時,各種格式的工作流程已被視為表達業務邏輯的好方法,可以讓人理解全局。結合工作流程和 Knative Eventing 是本文的主要主題。

工作流程作為函數流

工作流程的歷史可以追溯到服務導向架構 (SOA) 時代,當時引入了 BPEL 和 BPMN 等標準。各種供應商開始建構以工作流程概念為中心的平台,通常稱為流程管理套件或業務流程管理 (BPM)。

這些平台通常是大型的集中式伺服器,旨在以標準化的方式協調所有其他系統。結果證明這太複雜而無法帶來價值,並且在許多情況下被稱為傳統 BPM,它已經過時了,儘管這些平台今天仍在使用。

較新的方法使工作流程完全分散,因此工作流程的每個活動都作為單獨的容器執行。

這將我們帶到工作流程作為函數流的概念,該概念允許使用者盡可能完整地建立業務邏輯模型。使用者可以從頭到尾定義業務用例,並利用 Knative 等無伺服器平台的功能。這意味著在執行階段,工作流程邏輯將作為一組函數執行,這些函數是:

  • 自包含 - 專注於業務邏輯的「一個」方面
  • 獨立 - 它們依賴於給定的數據來執行定義的邏輯並返回輸出,而不管它們是處理相同的實例還是不同的實例
  • 隨時可調用 - 可以隨時調用,這意味著它們不必總是從工作流程的開頭開始,因為它們只是根據關聯屬性(Cloud Event type 屬性)對傳入的事件做出反應
  • 可擴展 - 因為函數可以輕鬆地向上和向下擴展以適應需求

工作流程作為函數流 工作流程作為函數流

Automatiko 專案交付了此概念的實作,該實作利用 Knative Eventing、Cloud Events 和工作流程定義來提供一種將服務建構成完整的業務用例,但將其作為函數流執行,該函數流由工作流程定義控制,但由發佈的事件調用。

Automatiko 支援以下類型的工作流程

將工作流程切片為函數

函數是根據執行可以變更工作流程狀態和資料的活動來建構的。然後,這些活動將代表特定的業務邏輯片段,這些邏輯片段將封裝為函數。

執行活動可以

  • 是單個活動
  • 包含其他活動來控制邏輯
  • 與其他執行活動組合以形成延續

函數會根據工作流程或活動名稱自動命名,或由使用者使用自訂屬性明確命名。

然後,每個函數都成為一個專用的進入點,該進入點

  • 具有基於工作流程資料建立的輸入
  • 可以產生一個或多個輸出
  • 具有與函數關聯的 Knative 觸發器

將工作流程切片為函數 將工作流程切片為函數

輸入和輸出作為 Cloud Events

從工作流程衍生出函數後,它們將始終具有一個事件作為輸入,並且可以產生一個或多個事件作為輸出。工作流程中定義的邏輯和特定工作流程實例的實際資料內容會驅動產生的事件數量。

無論事件是輸入還是輸出

  • 它都是基於工作流程中定義的資料物件建立的
  • 它會根據執行內容自動填寫
  • 它使用 type 屬性作為連結到函數的連結
  • 它使用 source 屬性作為正在執行的函數的識別碼,包括用於關聯目的的工作流程實例的唯一識別碼

輸入和輸出作為事件 輸入和輸出作為事件

函數始終透過 Knative Eventing 代理程式交換事件。它們永遠不會直接呼叫彼此,這確保了它們完全解耦並且是事件驅動的。這允許更大的可擴展性,因為每個函數呼叫都可以由服務的另一個副本處理。

部署

需要剖析工作流程定義、將其切片為函數和事件,並將其打包到可部署單元中的繁重工作是在建置時完成的。

Automatiko 專案實作了這個概念。它是一個基於 Java 的實作,利用 GraalVM 編譯為原生可執行檔,該可執行檔在執行階段具有較小的記憶體佔用空間和閃電般的快速啟動時間。

使用 Automatiko 的工作流程作為函數流會編譯成單個服務,因此編譯成包含所有函數的單個容器映像。每個函數都可以在服務的任何副本上隨時調用。

同時,在建置期間,會產生一個 Knative 清單檔案,以簡化部署到叢集。Knative 清單檔案包含

  • Knative 服務服務
  • 一個用於注入代理程式位置的接收器繫結
  • 從工作流程建立的每個函數的觸發器

這是在建置後直接擁有完全可執行服務的起點。它可以進一步修改,以適應叢集中 Knative 的特定配置。

使用者註冊範例

此範例顯示了一個簡單的使用者註冊,該註冊執行各種檢查並在 Swagger PetStore 服務中註冊使用者。

您可以在 Automatiko 文件中看到有關此範例的更多資訊。

這個範例提供兩種版本,取決於用來建立工作流程定義的 DSL。

將工作流程切割成函式 BPMN

將工作流程切割成函式 Serverless Workflow Spec

若要親自嘗試此範例,請複製此範例專案的其中一個版本。

複製專案後,請在複製的儲存庫中執行以下指令來建置應用程式。

mvn clean package -Pcontainer-native

此指令會使用 GraalVM 建置的原生可執行檔來建置包含服務的容器。建置過程可能需要一些時間。

將建置的容器推送到登錄檔

建置容器映像後,將其推送到您的 Knative 叢集可以從中提取的外部登錄檔。

部署到 Knative 叢集

  1. 建立 Knative 事件代理,例如使用以下指令。

    kubectl apply -f - << EOF
    apiVersion: eventing.knative.dev/v1
    kind: broker
    metadata:
     name: default
     namespace: knative-eventing
    EOF
    

    完整的部署檔案會在建置過程中產生,可以在 target/functions/user-registration-{version}.yaml 中找到。若要部署它,請執行以下指令。

    kubectl apply -f target/functions/user-registration-{version}.yaml
    

    這將佈建完整的服務和所有 Knative Eventing 觸發器。此外,它還會建立 sink binding,使服務成為事件來源,以便能夠從函式執行中發布事件。

  2. 您可以選擇性地部署 cloudevents-player,它會顯示所有通過代理的事件,使用以下指令。

    kubectl apply -n knative-eventing -f - << EOF
    apiVersion: serving.knative.dev/v1
    kind: Service
    metadata:
      name: cloudevents-player
    spec:
      template:
        metadata:
          annotations:
            autoscaling.knative.dev/minScale: "1"
        spec:
          containers:
            - image: quay.io/ruben/cloudevents-player:latest
              env:
                - name: PLAYER_MODE
                  value: KNATIVE
                - name: PLAYER_BROKER
                  value: default
    ---
    apiVersion: eventing.knative.dev/v1
    kind: Trigger
    metadata:
      name: cloudevents-player
      annotations:
        knative-eventing-injection: enabled
    spec:
      broker: default
      subscriber:
        ref:
          apiVersion: serving.knative.dev/v1
          kind: Service
          name: cloudevents-player
    EOF
    
  3. 使用以下指令取得預設代理的 URL。

    kubectl get broker default
    
  4. 向代理發送請求以啟動使用者註冊。

    curl -v "http://broker-ingress.knative-eventing.svc.cluster.local/knative-eventing/default" \
    -X POST \
    -H "Ce-Id: 1234" \
    -H "Ce-Specversion: 1.0" \
    -H "Ce-Type: io.automatiko.examples.userRegistration" \
    -H "Ce-Source: curl" \
    -H "Content-Type: application/json" \
    -d '{"user" : {"email" : "mike.strong@email.com",  "firstName" : "mike",  "lastName" : "strong"}}'
    

    這將通過 Knative 代理交換的一系列事件,並調用工作流程中定義的函式。它還使用 Swagger Petstore REST API,因此如果使用者註冊成功,它將在 Swagger Petstore 中顯示為新使用者。

    注意

    Swagger Petstore 沒有可靠的儲存,因此可能需要發出一些 get 請求才能在那裡看到它。

清除

若要清除,請執行以下指令。

kubectl delete -f target/functions/user-registration-1.0.0.yaml

將服務建置為 Google Cloud Run 的容器映像

為了能夠將相同的服務用於 Google Cloud Run,還需要額外兩個步驟。

  1. 將依賴項新增至 pom.xml

    <dependency>
      <groupId>io.automatiko.extras</groupId>
      <artifactId>automatiko-gcp-pubsub-sink</artifactId>
    </dependency>
    
  2. 將兩個屬性新增至 src/main/resources/application.properties 檔案。

    quarkus.automatiko.target-deployment=gcp-pubsub
    quarkus.google.cloud.project-id=CHANGE_ME
    

    注意

    請記得將 CHANGE_ME 變更為您的 Google Cloud 專案的實際專案 ID。

  3. 使用以下 maven 指令建置應用程式。

    mvnw clean package -Pcontainer-native
    

    此指令會使用 GraalVM 建置的原生可執行檔來建置包含服務的容器。建置過程可能需要一些時間。

將建置的容器推送到 Google Cloud Container 登錄檔

建置容器映像後,將其推送到 Google Cloud Container 登錄檔,Google Cloud Run 可以從中提取。

使用 PubSub 部署到 Google Cloud Run

建置和推送完成後,會在建置過程中產生完整的腳本,可以在 target/scripts 中找到。若要部署它,請登入 Google Cloud Console(或使用已安裝 gcloud 的終端機),您可以在其中使用 gcloud 工具,並從 deploy-user-registration-gcp-cloudrun-{version}.txt 發出所有指令。

腳本內容將類似於以下內容。

gcloud pubsub topics create io.automatiko.examples.userRegistration.registrationfailed --project=CHANGE_ME
gcloud pubsub topics create io.automatiko.examples.userRegistration.notifyservererror --project=CHANGE_ME
gcloud pubsub topics create io.automatiko.examples.userRegistration.userregistered --project=CHANGE_ME
gcloud pubsub topics create io.automatiko.examples.userRegistration.notifyregistered --project=CHANGE_ME
gcloud pubsub topics create io.automatiko.examples.userRegistration.registeruser --project=CHANGE_ME
gcloud pubsub topics create io.automatiko.examples.userRegistration.invaliddata --project=CHANGE_ME
gcloud pubsub topics create io.automatiko.examples.userRegistration.generateusernameandpassword --project=CHANGE_ME
gcloud pubsub topics create io.automatiko.examples.userRegistration.alreadyregistered --project=CHANGE_ME
gcloud pubsub topics create io.automatiko.examples.userRegistration.getuser --project=CHANGE_ME
gcloud pubsub topics create io.automatiko.examples.userRegistration --project=CHANGE_ME

gcloud eventarc triggers create notifyservererror --event-filters="type=google.cloud.pubsub.topic.v1.messagePublished" --destination-run-service=user-registration-gcp-cloudrun --destination-run-path=/ --transport-topic=io.automatiko.examples.userRegistration.notifyservererror --location=us-central1
gcloud eventarc triggers create notifyregistered --event-filters="type=google.cloud.pubsub.topic.v1.messagePublished" --destination-run-service=user-registration-gcp-cloudrun --destination-run-path=/ --transport-topic=io.automatiko.examples.userRegistration.notifyregistered --location=us-central1
gcloud eventarc triggers create registeruser --event-filters="type=google.cloud.pubsub.topic.v1.messagePublished" --destination-run-service=user-registration-gcp-cloudrun --destination-run-path=/ --transport-topic=io.automatiko.examples.userRegistration.registeruser --location=us-central1
gcloud eventarc triggers create generateusernameandpassword --event-filters="type=google.cloud.pubsub.topic.v1.messagePublished" --destination-run-service=user-registration-gcp-cloudrun --destination-run-path=/ --transport-topic=io.automatiko.examples.userRegistration.generateusernameandpassword --location=us-central1
gcloud eventarc triggers create getuser --event-filters="type=google.cloud.pubsub.topic.v1.messagePublished" --destination-run-service=user-registration-gcp-cloudrun --destination-run-path=/ --transport-topic=io.automatiko.examples.userRegistration.getuser --location=us-central1
gcloud eventarc triggers create userregistration --event-filters="type=google.cloud.pubsub.topic.v1.messagePublished" --destination-run-service=user-registration-gcp-cloudrun --destination-run-path=/ --transport-topic=io.automatiko.examples.userRegistration --location=us-central1

gcloud run deploy user-registration-gcp-cloudrun --platform=managed --image=gcr.io/CHANGE_ME/user/user-registration-gcp-cloudrun:1.0.0 --region=us-central1

注意

CHANGE_ME 將會在建置期間被替換為 src/main/resources/application.properties 中設定的 Google Cloud 專案 ID。

這會佈建所有需要的組件,例如

  • PubSub 主題
  • Eventarc 觸發器
  • 服務部署

在 Google Cloud Run 上執行服務

部署服務後,您可以發布第一則訊息。例如,使用 Google Console 和以下 io.automatiko.examples.userRegistration 主題。

{"user" : {"email" : "mike.strong@email.com",  "firstName" : "mike",  "lastName" : "strong"}}

這會透過 Google Cloud PubSub 主題交換的一系列事件,並調用工作流程中定義的函式。

總結

作為函式流程的工作流程,實作了無伺服器使用情況的常見情境,其中個別函式構建了完整的商業案例。它允許您使用工作流程來設計完整的商業邏輯,然後根據工作流程定義所定義的實際邏輯,將其切割成組合成函式流程的函式。然而,每個函式都可以隨時調用,使工作流程充當藍圖,可以從任何地方開始,並根據已定義的函式流程繼續執行。

作為函式流程的工作流程利用 Knative Eventing 作為通訊的骨幹來啟用

  • 可擴展性,因為每個函式都是通過使用 Knative 代理來調用。
  • 所有資料交換都使用 Cloud Events 完成。
  • 關於工作流程定義實例應從哪個點開始的靈活性。
  • 使用「傾聽自己」原則,避免長時間運行的操作影響整體效能。

同時,它在部署上很簡單,因為它依賴單一服務和自動定義的觸發器來與 Knative 代理整合。

連結/參考資料

作為函式流程的工作流程已在 Knative 社群聚會上展示,因此如果您對更多詳細資訊感興趣,請查看

IMAGE_ALT

我們使用分析和 Cookie 來了解網站流量。您使用我們網站的相關資訊會與 Google 分享,用於此目的。了解更多。