۱. مقدمه

شما میتوانید از Workflowها برای ایجاد گردشهای کاری بدون سرور استفاده کنید که مجموعهای از وظایف بدون سرور را به ترتیبی که شما تعریف میکنید، به هم پیوند میدهند. میتوانید قدرت APIهای Google Cloud، محصولات بدون سرور مانند Cloud Functions و Cloud Run و فراخوانیهای APIهای خارجی را برای ایجاد برنامههای بدون سرور انعطافپذیر ترکیب کنید.
گردشهای کاری نیازی به مدیریت زیرساخت ندارند و به طور یکپارچه با تقاضا، از جمله کاهش مقیاس به صفر، مقیاسپذیر هستند. با مدل قیمتگذاری پرداخت به ازای هر استفاده، شما فقط برای زمان اجرا هزینه پرداخت میکنید.
در این آزمایشگاه کد، شما یاد خواهید گرفت که چگونه سرویسهای مختلف گوگل کلود و APIهای HTTP خارجی را با Workflowها متصل کنید. به طور خاص، شما دو سرویس Cloud Functions عمومی، یک سرویس Cloud Run خصوصی و یک HTTP API عمومی خارجی را به یک Workflow متصل خواهید کرد.
آنچه یاد خواهید گرفت
- مبانی گردشهای کاری.
- نحوه اتصال توابع ابری عمومی با گردشهای کاری.
- نحوه اتصال سرویسهای خصوصی Cloud Run به Workflows.
- نحوه اتصال APIهای HTTP خارجی با Workflowها.
۲. تنظیمات و الزامات
تنظیم محیط خودتنظیم
- وارد Cloud Console شوید و یک پروژه جدید ایجاد کنید یا از یک پروژه موجود دوباره استفاده کنید. (اگر از قبل حساب Gmail یا G Suite ندارید، باید یکی ایجاد کنید .)
شناسه پروژه را به خاطر بسپارید، یک نام منحصر به فرد در تمام پروژههای Google Cloud (نام بالا قبلاً گرفته شده و برای شما کار نخواهد کرد، متاسفیم!). بعداً در این آزمایشگاه کد به آن PROJECT_ID گفته خواهد شد.
- در مرحله بعد، برای استفاده از منابع گوگل کلود، باید پرداخت را در Cloud Console فعال کنید .
اجرای این آزمایشگاه کد، اگر اصلاً هزینهای نداشته باشد، نباید هزینه زیادی داشته باشد. حتماً دستورالعملهای بخش «پاکسازی» را که به شما نحوه خاموش کردن منابع را آموزش میدهد، دنبال کنید تا پس از این آموزش، متحمل هزینه نشوید. کاربران جدید Google Cloud واجد شرایط برنامه آزمایشی رایگان ۳۰۰ دلاری هستند.
شروع پوسته ابری
اگرچه میتوان از راه دور و از طریق لپتاپ، گوگل کلود را مدیریت کرد، اما در این آزمایشگاه کد، از گوگل کلود شل ، یک محیط خط فرمان که در فضای ابری اجرا میشود، استفاده خواهید کرد.
از کنسول GCP روی آیکون Cloud Shell در نوار ابزار بالا سمت راست کلیک کنید:
آمادهسازی و اتصال به محیط فقط چند لحظه طول میکشد. وقتی تمام شد، باید چیزی شبیه به این را ببینید:
این ماشین مجازی مجهز به تمام ابزارهای توسعه مورد نیاز شماست. این ماشین یک دایرکتوری خانگی دائمی ۵ گیگابایتی ارائه میدهد و روی فضای ابری گوگل اجرا میشود که عملکرد شبکه و احراز هویت را تا حد زیادی بهبود میبخشد. تمام کارهای شما در این آزمایشگاه را میتوان به سادگی با یک مرورگر انجام داد.
۳. مرور کلی گردشهای کاری
مبانی
یک گردش کار از مجموعهای از مراحل تشکیل شده است که با استفاده از سینتکس مبتنی بر YAML گردشهای کار شرح داده شدهاند. این تعریف گردش کار است. برای توضیح دقیق سینتکس YAML گردشهای کار، به صفحه مرجع سینتکس مراجعه کنید.
وقتی یک گردش کار ایجاد میشود، مستقر میشود که گردش کار را برای اجرا آماده میکند. اجرا، یک اجرای واحد از منطق موجود در تعریف گردش کار است. همه اجراهای گردش کار مستقل هستند و محصول از تعداد زیادی اجراهای همزمان پشتیبانی میکند.
فعال کردن سرویسها
در این آزمایشگاه کد، شما توابع ابری و سرویسهای Cloud Run را با گردشهای کاری متصل خواهید کرد. همچنین در طول ساخت سرویسها از Cloud Build و Cloud Storage استفاده خواهید کرد.
فعال کردن تمام سرویسهای لازم:
gcloud services enable \ cloudfunctions.googleapis.com \ run.googleapis.com \ workflows.googleapis.com \ cloudbuild.googleapis.com \ storage.googleapis.com
در مرحله بعد، دو تابع ابری را در یک گردش کار به هم متصل خواهید کرد.
۴. اولین عملکرد ابری را مستقر کنید
تابع اول یک مولد اعداد تصادفی در پایتون است.
یک دایرکتوری برای کد تابع ایجاد کنید و به آن بروید:
mkdir ~/randomgen cd ~/randomgen
یک فایل main.py در دایرکتوری با محتوای زیر ایجاد کنید:
import random, json
from flask import jsonify
def randomgen(request):
randomNum = random.randint(1,100)
output = {"random":randomNum}
return jsonify(output)
وقتی یک درخواست HTTP دریافت میکند، این تابع یک عدد تصادفی بین ۱ تا ۱۰۰ تولید میکند و آن را در قالب JSON به فراخواننده برمیگرداند.
این تابع برای پردازش HTTP به Flask متکی است و ما باید آن را به عنوان یک وابستگی اضافه کنیم. وابستگیها در پایتون با pip مدیریت میشوند و در یک فایل متادیتا به نام requirements.txt بیان میشوند.
یک فایل requirements.txt در همان دایرکتوری با محتوای زیر ایجاد کنید:
flask>=1.0.2
تابع را با یک تریگر HTTP و با درخواستهای احراز هویت نشده مجاز با این دستور مستقر کنید:
gcloud functions deploy randomgen \
--runtime python312 \
--trigger-http \
--allow-unauthenticated
پس از استقرار تابع، میتوانید URL تابع را در قسمت ویژگی url که در کنسول نمایش داده میشود یا با دستور gcloud functions describe نمایش داده میشود، مشاهده کنید.
همچنین میتوانید با دستور curl زیر به آن URL تابع دسترسی پیدا کنید:
curl $(gcloud functions describe randomgen --format='value(url)')
این تابع برای گردش کار آماده است.
۵. دومین عملکرد ابری را مستقر کنید
تابع دوم یک ضربکننده است. ورودی دریافتی را در ۲ ضرب میکند.
یک دایرکتوری برای کد تابع ایجاد کنید و به آن بروید:
mkdir ~/multiply cd ~/multiply
یک فایل main.py در دایرکتوری با محتوای زیر ایجاد کنید:
import random, json
from flask import jsonify
def multiply(request):
request_json = request.get_json()
output = {"multiplied":2*request_json['input']}
return jsonify(output)
وقتی یک درخواست HTTP دریافت میکند، این تابع input را از بدنه JSON استخراج میکند، آن را در ۲ ضرب میکند و در قالب JSON به فراخواننده برمیگرداند.
همان فایل requirements.txt را در همان دایرکتوری با محتوای زیر ایجاد کنید:
flask>=1.0.2
تابع را با یک تریگر HTTP و با درخواستهای احراز هویت نشده مجاز با این دستور مستقر کنید:
gcloud functions deploy multiply \
--runtime python312 \
--trigger-http \
--allow-unauthenticated
پس از استقرار تابع، میتوانید با دستور curl زیر به آن URL تابع نیز دسترسی پیدا کنید:
curl $(gcloud functions describe multiply --format='value(url)') \
-X POST \
-H "content-type: application/json" \
-d '{"input": 5}'
این تابع برای گردش کار آماده است.
۶. دو تابع ابری را به هم متصل کنید
در اولین گردش کار، دو تابع را به هم متصل کنید.
یک فایل workflow.yaml با محتوای زیر ایجاد کنید.
- randomgenFunction:
call: http.get
args:
url: https://<region>-<project-id>.cloudfunctions.net/randomgen
result: randomgenResult
- multiplyFunction:
call: http.post
args:
url: https://<region>-<project-id>.cloudfunctions.net/multiply
body:
input: ${randomgenResult.body.random}
result: multiplyResult
- returnResult:
return: ${multiplyResult}
در این گردش کار، شما یک عدد تصادفی از تابع اول دریافت میکنید و آن را به تابع دوم ارسال میکنید. نتیجه، عدد تصادفی حاصلضرب است.
اولین گردش کار را مستقر کنید:
gcloud workflows deploy workflow --source=workflow.yaml
اجرای اولین گردش کار:
gcloud workflows execute workflow
پس از اجرای گردش کار، میتوانید نتیجه را با ارسال شناسه اجرا که در مرحله قبل داده شده است، مشاهده کنید:
gcloud workflows executions describe <your-execution-id> --workflow workflow
خروجی شامل result و state خواهد بود:
result: '{"body":{"multiplied":108},"code":200 ... }
...
state: SUCCEEDED
۷. اتصال یک HTTP API خارجی
در مرحله بعد، math.js را به عنوان یک سرویس خارجی در گردش کار متصل خواهید کرد.
در math.js ، میتوانید عبارات ریاضی را به این صورت ارزیابی کنید:
curl https://api.mathjs.org/v4/?'expr=log(56)'
این بار، شما از Cloud Console برای بهروزرسانی گردش کار ما استفاده خواهید کرد. Workflows در Google Cloud Console بیابید:

گردش کار خود را پیدا کنید و روی تب Definition کلیک کنید:

تعریف گردش کار را ویرایش کنید و فراخوانی math.js را در آن بگنجانید.
- randomgenFunction:
call: http.get
args:
url: https://<region>-<project-id>.cloudfunctions.net/randomgen
result: randomgenResult
- multiplyFunction:
call: http.post
args:
url: https://<region>-<project-id>.cloudfunctions.net/multiply
body:
input: ${randomgenResult.body.random}
result: multiplyResult
- logFunction:
call: http.get
args:
url: https://api.mathjs.org/v4/
query:
expr: ${"log(" + string(multiplyResult.body.multiplied) + ")"}
result: logResult
- returnResult:
return: ${logResult}
اکنون گردش کار، خروجی تابع multiply را به یک فراخوانی تابع log در math.js ارسال میکند.
رابط کاربری شما را برای ویرایش و استقرار گردش کار راهنمایی میکند. پس از استقرار، برای اجرای گردش کار Execute کلیک کنید. جزئیات اجرا را مشاهده خواهید کرد:

به کد وضعیت 200 و body حاوی خروجی تابع log توجه کنید.
شما همین الان یک سرویس خارجی را در گردش کار ما ادغام کردید، خیلی عالی!
۸. یک سرویس Cloud Run راهاندازی کنید
در بخش آخر، گردش کار را با فراخوانی یک سرویس خصوصی Cloud Run نهایی کنید. این بدان معناست که گردش کار برای فراخوانی سرویس Cloud Run نیاز به احراز هویت دارد.
سرویس Cloud Run مقدار math.floor مربوط به عدد ارسالی را برمیگرداند.
یک دایرکتوری برای کد سرویس ایجاد کنید و به آن بروید:
mkdir ~/floor cd ~/floor
یک فایل app.py در دایرکتوری با محتوای زیر ایجاد کنید:
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)))
Cloud Run کانتینرها را مستقر میکند، بنابراین به یک Dockerfile نیاز دارید و کانتینر شما باید به متغیر 0.0.0.0 و PORT env متصل شود، از این رو کد بالا را داریم.
وقتی یک درخواست HTTP دریافت میکند، این تابع input را از بدنه JSON استخراج میکند، math.floor را فراخوانی میکند و نتیجه را به فراخواننده برمیگرداند.
در همان دایرکتوری، 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
ساخت کانتینر:
export SERVICE_NAME=floor
gcloud builds submit --tag gcr.io/${GOOGLE_CLOUD_PROJECT}/${SERVICE_NAME}
پس از ساخت کانتینر، آن را در Cloud Run مستقر کنید. به پرچم no-allow-unauthenticated توجه کنید. این پرچم تضمین میکند که سرویس فقط فراخوانیهای احراز هویت شده را میپذیرد:
gcloud run deploy ${SERVICE_NAME} \
--image gcr.io/${GOOGLE_CLOUD_PROJECT}/${SERVICE_NAME} \
--platform managed \
--no-allow-unauthenticated
پس از استقرار، سرویس برای گردش کار آماده است.
۹. سرویس Cloud Run را وصل کنید
قبل از اینکه بتوانید Workflows را برای فراخوانی سرویس خصوصی Cloud Run پیکربندی کنید، باید یک حساب کاربری سرویس برای استفاده از Workflows ایجاد کنید:
export SERVICE_ACCOUNT=workflows-sa
gcloud iam service-accounts create ${SERVICE_ACCOUNT}
نقش run.invoker را به حساب سرویس اعطا کنید. این به حساب سرویس اجازه میدهد تا سرویسهای Cloud Run احراز هویت شده را فراخوانی کند:
gcloud projects add-iam-policy-binding ${GOOGLE_CLOUD_PROJECT} \
--member "serviceAccount:${SERVICE_ACCOUNT}@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com" \
--role "roles/run.invoker"
تعریف گردش کار در workflow.yaml را بهروزرسانی کنید تا سرویس Cloud Run را شامل شود. توجه کنید که چگونه فیلد auth نیز اضافه میکنید تا مطمئن شوید Workflows در فراخوانیهای خود به سرویس Cloud Run، توکن احراز هویت را ارسال میکند:
- randomgenFunction:
call: http.get
args:
url: https://<region>-<project-id>.cloudfunctions.net/randomgen
result: randomgenResult
- multiplyFunction:
call: http.post
args:
url: https://<region>-<project-id>.cloudfunctions.net/multiply
body:
input: ${randomgenResult.body.random}
result: multiplyResult
- logFunction:
call: http.get
args:
url: https://api.mathjs.org/v4/
query:
expr: ${"log(" + string(multiplyResult.body.multiplied) + ")"}
result: logResult
- floorFunction:
call: http.post
args:
url: https://floor-<random-hash>.run.app
auth:
type: OIDC
body:
input: ${logResult.body}
result: floorResult
- returnResult:
return: ${floorResult}
گردش کار را بهروزرسانی کنید. این بار service-account را وارد کنید:
gcloud workflows deploy workflow \
--source=workflow.yaml \
--service-account=${SERVICE_ACCOUNT}@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com
اجرای گردش کار:
gcloud workflows execute workflow
در عرض چند ثانیه، میتوانید نگاهی به اجرای گردش کار بیندازید تا نتیجه را ببینید:
gcloud workflows executions describe <your-execution-id> --workflow workflow
خروجی شامل یک result صحیح و state خواهد بود:
result: '{"body":"5","code":200 ... }
...
state: SUCCEEDED
۱۰. تبریک میگویم!
تبریک میگویم که آزمایشگاه کد را تمام کردی.
آنچه ما پوشش دادهایم
- مبانی گردشهای کاری.
- نحوه اتصال توابع ابری عمومی با گردشهای کاری.
- نحوه اتصال سرویسهای خصوصی Cloud Run به Workflows.
- نحوه اتصال APIهای HTTP خارجی با Workflowها.