Workflows 教學課程 (第 1 代)


本教學課程說明如何使用 Workflows 連結一系列服務。您可以連結兩個公開 HTTP 服務 (使用 Cloud Run 函式)、外部 REST API 和私有 Cloud Run 服務,藉此建立彈性的無伺服器應用程式。

目標

在本教學課程中,您將使用 Google Cloud CLI 建立單一工作流程,並一次連結一項服務:

  1. 部署兩項 Cloud Run 函式服務:第一項函式會產生隨機數字,然後將該數字傳遞至第二項函式,由第二項函式將其相乘。
  2. 使用 Workflows 將這兩個 HTTP 函式連結在一起。 執行工作流程並傳回結果,然後將結果傳遞至外部 API。
  3. 使用 Workflows 連線至外部 HTTP API,針對指定數字傳回 log。執行工作流程並傳回結果,然後將結果傳遞至 Cloud Run 服務。
  4. 部署只允許經過驗證存取的 Cloud Run 服務。服務會傳回指定號碼的 math.floor
  5. 使用 Workflows 連線至 Cloud Run 服務、執行整個工作流程,並傳回最終結果。

下圖顯示程序總覽,以及最終工作流程的視覺化呈現:

工作流程視覺化

費用

在本文件中,您會使用 Google Cloud的下列計費元件:

如要根據預測用量估算費用,請使用 Pricing Calculator

初次使用 Google Cloud 的使用者可能符合免費試用資格。

事前準備

貴機構定義的安全性限制,可能會導致您無法完成下列步驟。如需疑難排解資訊,請參閱「在受限的 Google Cloud 環境中開發應用程式」。

  1. Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
  2. Install the Google Cloud CLI.

  3. 如果您使用外部識別資訊提供者 (IdP),請先 使用聯合身分登入 gcloud CLI

  4. 如要初始化 gcloud CLI,請執行下列指令:

    gcloud init
  5. Create or select a Google Cloud project.

    • Create a Google Cloud project:

      gcloud projects create PROJECT_ID

      Replace PROJECT_ID with a name for the Google Cloud project you are creating.

    • Select the Google Cloud project that you created:

      gcloud config set project PROJECT_ID

      Replace PROJECT_ID with your Google Cloud project name.

  6. Verify that billing is enabled for your Google Cloud project.

  7. Enable the Artifact Registry, Cloud Build, Cloud Run functions, Cloud Run, Cloud Storage, and Workflows APIs:

    gcloud services enable artifactregistry.googleapis.com cloudbuild.googleapis.com cloudfunctions.googleapis.com run.googleapis.com storage.googleapis.com workflows.googleapis.com
  8. Install the Google Cloud CLI.

  9. 如果您使用外部識別資訊提供者 (IdP),請先 使用聯合身分登入 gcloud CLI

  10. 如要初始化 gcloud CLI,請執行下列指令:

    gcloud init
  11. Create or select a Google Cloud project.

    • Create a Google Cloud project:

      gcloud projects create PROJECT_ID

      Replace PROJECT_ID with a name for the Google Cloud project you are creating.

    • Select the Google Cloud project that you created:

      gcloud config set project PROJECT_ID

      Replace PROJECT_ID with your Google Cloud project name.

  12. Verify that billing is enabled for your Google Cloud project.

  13. Enable the Artifact Registry, Cloud Build, Cloud Run functions, Cloud Run, Cloud Storage, and Workflows APIs:

    gcloud services enable artifactregistry.googleapis.com cloudbuild.googleapis.com cloudfunctions.googleapis.com run.googleapis.com storage.googleapis.com workflows.googleapis.com
  14. 更新 Google Cloud CLI 元件:
    gcloud components update
  15. 如果您在 Cloud Shell 中執行指令,系統會自動驗證 gcloud CLI;否則,請使用您的帳戶登入:
    gcloud auth login
  16. 建立 Workflows 專用的服務帳戶:

    export SERVICE_ACCOUNT=workflows-sa
    gcloud iam service-accounts create ${SERVICE_ACCOUNT}

  17. 如要允許服務帳戶呼叫已通過驗證的 Cloud Run 服務,請將 run.invoker 角色授予 Workflows 服務帳戶:

    gcloud projects add-iam-policy-binding PROJECT_ID \
        --member "serviceAccount:${SERVICE_ACCOUNT}@PROJECT_ID.iam.gserviceaccount.com" \
        --role "roles/run.invoker"

    PROJECT_ID 替換為您的 Google Cloud 專案 ID。

  18. 設定本教學課程中使用的預設位置:
    gcloud config set project PROJECT_ID
    export REGION=REGION
    gcloud config set functions/region ${REGION}
    gcloud config set run/region ${REGION}
    gcloud config set workflows/location ${REGION}

    REGION 替換為您選擇的支援 Workflows 位置

  19. 部署第一個 Cloud Run functions 服務

    收到 HTTP 要求後,這個 HTTP 函式會產生介於 1 到 100 之間的隨機數字,然後以 JSON 格式傳回該數字。

    1. 建立名為 randomgen 的目錄,然後切換至該目錄:

      mkdir ~/randomgen
      cd ~/randomgen
    2. 建立名為 main.py 的文字檔,其中包含下列 Python 程式碼:

      import functions_framework
      import random
      from flask import jsonify
      
      
      @functions_framework.http
      def randomgen(request):
          randomNum = random.randint(1, 100)
          output = {"random": randomNum}
          return jsonify(output)
    3. 如要支援 Flask 的 HTTP 處理依附元件,請為 pip 套件管理員建立文字檔。將檔案命名為 requirements.txt,並加入下列內容:

      flask>=1.0.2
      functions-framework==3.0.0
    4. 使用 HTTP 觸發條件部署函式,並允許未經驗證的存取權:

      gcloud functions deploy randomgen \
          --runtime python37 \
          --trigger-http \
          --allow-unauthenticated

    部署函式可能需要幾分鐘的時間。或者,您也可以在 Google Cloud 控制台使用 Cloud Run 函式介面部署函式。

    1. 部署函式後,您可以確認 httpsTrigger.url 屬性:

      gcloud functions describe randomgen
    2. 您可以使用下列 curl 指令試用函式:

      curl $(gcloud functions describe randomgen --format='value(httpsTrigger.url)')

      系統會隨機產生並傳回一個數字。

    部署第二個 Cloud Run 函式服務

    收到 HTTP 要求後,這項 HTTP 函式會從 JSON 主體中擷取 input,然後乘以 2,並以 JSON 格式傳回結果。

    1. 建立名為 multiply 的目錄,然後切換至該目錄:

      mkdir ~/multiply
      cd ~/multiply
    2. 建立名為 main.py 的文字檔,其中包含下列 Python 程式碼:

      import functions_framework
      from flask import jsonify
      
      
      @functions_framework.http
      def multiply(request):
          request_json = request.get_json()
          output = {"multiplied": 2 * request_json['input']}
          return jsonify(output)
    3. 如要支援 Flask 的 HTTP 處理依附元件,請為 pip 套件管理員建立文字檔。將檔案命名為 requirements.txt,並加入下列內容:

      flask>=1.0.2
      functions-framework==3.0.0
    4. 使用 HTTP 觸發條件部署函式,並允許未經驗證的存取權:

      gcloud functions deploy multiply \
          --runtime python37 \
          --trigger-http \
          --allow-unauthenticated

    部署函式可能需要幾分鐘的時間。或者,您也可以在 Google Cloud 控制台使用 Cloud Run 函式介面部署函式。

    1. 部署函式後,您可以確認 httpsTrigger.url 屬性:

      gcloud functions describe multiply
    2. 您可以使用下列 curl 指令試用函式:

      curl $(gcloud functions describe multiply --format='value(httpsTrigger.url)') \
          -X POST \
          -H "content-type: application/json" \
          -d '{"input": 5}'

      系統應會傳回數字 10。

    在工作流程中連結這兩項 Cloud Run 函式服務

    工作流程是由一系列步驟組成,這些步驟使用 Workflows 語法描述,且可採用 YAML 或 JSON 格式編寫。這是工作流程的定義。如需詳細說明,請參閱「語法參考資料」頁面。

    1. 返回主目錄:

      cd ~
    2. 建立名為 workflow.yaml 的文字檔,並在當中加入下列內容:

      - randomgen_function:
          call: http.get
          args:
              url: https://REGION-PROJECT_ID.cloudfunctions.net/randomgen
          result: randomgen_result
      - multiply_function:
          call: http.post
          args:
              url: https://REGION-PROJECT_ID.cloudfunctions.net/multiply
              body:
                  input: ${randomgen_result.body.random}
          result: multiply_result
      - return_result:
          return: ${multiply_result}
      

      這會將兩個 HTTP 函式連結在一起,並傳回最終結果。

    3. 建立工作流程後,您可以部署工作流程,讓工作流程準備好執行。

      gcloud workflows deploy WORKFLOW_NAME --source=workflow.yaml

      WORKFLOW_NAME 替換為工作流程的名稱。

    4. 執行工作流程:

      gcloud workflows run WORKFLOW_NAME

      執行作業是指單次執行工作流程定義中包含的邏輯。所有工作流程執行作業都是獨立的,而且工作流程可快速調度資源,因此能同時執行大量作業。

      工作流程執行完畢後,輸出內容應如下所示:

      result: '{"body":{"multiplied":120},"code":200,"headers":{"Alt-Svc":"h3-29=\":443\";
      ...
      startTime: '2021-05-05T14:17:39.135251700Z'
      state: SUCCEEDED
      ...
      

    在工作流程中連結公開 REST 服務

    更新現有工作流程,並連結可評估數學運算的公開 REST API (math.js)。例如:curl https://api.mathjs.org/v4/?'expr=log(56)'

    請注意,由於您已部署工作流程,因此也可以透過 Google Cloud 控制台的「Workflows」頁面編輯工作流程。

    1. 編輯工作流程的來源檔案,並將其替換為下列內容:

      - randomgen_function:
          call: http.get
          args:
              url: https://REGION-PROJECT_ID.cloudfunctions.net/randomgen
          result: randomgen_result
      - multiply_function:
          call: http.post
          args:
              url: https://REGION-PROJECT_ID.cloudfunctions.net/multiply
              body:
                  input: ${randomgen_result.body.random}
          result: multiply_result
      - log_function:
          call: http.get
          args:
              url: https://api.mathjs.org/v4/
              query:
                  expr: ${"log(" + string(multiply_result.body.multiplied) + ")"}
          result: log_result
      - return_result:
          return: ${log_result}
      

      這會將外部 REST 服務連結至 Cloud Run 函式服務,並傳回最終結果。

    2. 部署修改後的工作流程:

      gcloud workflows deploy WORKFLOW_NAME --source=workflow.yaml

    部署 Cloud Run 服務

    部署 Cloud Run 服務,在收到 HTTP 要求後,從 JSON 內文擷取 input,計算其 math.floor,然後傳回結果。

    1. 建立名為 floor 的目錄,然後切換至該目錄:

      mkdir ~/floor
      cd ~/floor
    2. 建立名為 app.py 的文字檔,並在其中加入下列 Python 程式碼:

      import json
      import logging
      import os
      import math
      
      from flask import Flask, request
      
      app = Flask(__name__)
      
      
      @app.route('/', methods=['POST'])
      def handle_post():
          content = json.loads(request.data)
          input = float(content['input'])
          return f"{math.floor(input)}", 200
      
      
      if __name__ != '__main__':
          # Redirect Flask logs to Gunicorn logs
          gunicorn_logger = logging.getLogger('gunicorn.error')
          app.logger.handlers = gunicorn_logger.handlers
          app.logger.setLevel(gunicorn_logger.level)
          app.logger.info('Service started...')
      else:
          app.run(debug=True, host='0.0.0.0', port=int(os.environ.get('PORT', 8080)))

    3. 在同一個目錄中建立 Dockerfile,並加入以下內容:

      # Use an official lightweight Python image.
      # https://hub.docker.com/_/python
      FROM python:3.7-slim
      
      # Install production dependencies.
      RUN pip install Flask gunicorn
      
      # Copy local code to the container image.
      WORKDIR /app
      COPY . .
      
      # Run the web service on container startup. Here we use the gunicorn
      # webserver, with one worker process and 8 threads.
      # For environments with multiple CPU cores, increase the number of workers
      # to be equal to the cores available.
      CMD exec gunicorn --bind 0.0.0.0:8080 --workers 1 --threads 8 app:app

    4. 建立 Artifact Registry 標準存放區,用於儲存 Docker 容器映像檔:

      gcloud artifacts repositories create REPOSITORY \
          --repository-format=docker \
          --location=${REGION}

      REPOSITORY 替換成存放區的專屬名稱。

    5. 建構容器映像檔:

      export SERVICE_NAME=floor
      gcloud builds submit --tag ${REGION}-docker.pkg.dev/PROJECT_ID/REPOSITORY/${SERVICE_NAME}
    6. 將容器映像檔部署至 Cloud Run,確保只接受已驗證的呼叫:

      gcloud run deploy ${SERVICE_NAME} \
          --image ${REGION}-docker.pkg.dev/PROJECT_ID/REPOSITORY/${SERVICE_NAME}:latest \
          --platform managed \
          --no-allow-unauthenticated

    看到服務網址時,表示部署作業已完成。更新工作流程定義時,您需要指定該網址。

    在工作流程中連結 Cloud Run 服務

    更新現有工作流程,並指定 Cloud Run 服務的網址。

    1. 編輯工作流程的來源檔案,並將其替換為下列內容:

      - randomgen_function:
          call: http.get
          args:
              url: https://REGION-PROJECT_ID.cloudfunctions.net/randomgen
          result: randomgen_result
      - multiply_function:
          call: http.post
          args:
              url: https://REGION-PROJECT_ID.cloudfunctions.net/multiply
              body:
                  input: ${randomgen_result.body.random}
          result: multiply_result
      - log_function:
          call: http.get
          args:
              url: https://api.mathjs.org/v4/
              query:
                  expr: ${"log(" + string(multiply_result.body.multiplied) + ")"}
          result: log_result
      - floor_function:
          call: http.post
          args:
              url: CLOUD_RUN_SERVICE_URL
              auth:
                  type: OIDC
              body:
                  input: ${log_result.body}
          result: floor_result
      - create_output_map:
          assign:
            - outputMap:
                randomResult: ${randomgen_result}
                multiplyResult: ${multiply_result}
                logResult: ${log_result}
                floorResult: ${floor_result}
      - return_output:
          return: ${outputMap}
      

      CLOUD_RUN_SERVICE_URL 替換為 Cloud Run 服務網址。

      這會連結工作流程中的 Cloud Run 服務。請注意,auth 鍵可確保驗證符記會傳遞至 Cloud Run 服務的呼叫中。詳情請參閱「從工作流程提出經過驗證的要求」。

    2. 部署修改後的工作流程:

      gcloud workflows deploy WORKFLOW_NAME \
          --source=workflow.yaml
    3. 執行最終工作流程:

      gcloud workflows run WORKFLOW_NAME

      輸出應會如下所示:

      result: '{"Floor":{"body":"4","code":200
        ...
        "Log":{"body":"4.02535169073515","code":200
        ...
        "Multiply":{"body":{"multiplied":56},"code":200
        ...
        "Random":{"body":{"random":28},"code":200
        ...
      startTime: '2023-11-13T21:22:56.782669001Z'
      state: SUCCEEDED
      

    恭喜!您已部署並執行工作流程,將一系列服務連結在一起。

    如要使用運算式、條件式跳轉、Base64 編碼或解碼、子工作流程等功能建立更複雜的工作流程,請參閱工作流程語法參考資料標準程式庫總覽

    清除所用資源

    如果您是為了這個教學課程建立新專案,請刪除專案。如果您使用現有專案,並想保留專案,但不要加入本教學課程新增的變更,請刪除為本教學課程建立的資源

    刪除專案

    如要避免付費,最簡單的方法就是刪除您為了本教學課程所建立的專案。

    如要刪除專案:

    1. In the Google Cloud console, go to the Manage resources page.

      Go to Manage resources

    2. In the project list, select the project that you want to delete, and then click Delete.
    3. In the dialog, type the project ID, and then click Shut down to delete the project.

    刪除教學課程資源

    後續步驟