1. مقدمة

يمكنك استخدام خطوات سير العمل لإنشاء خطوات سير عمل بدون خادم تربط سلسلة من المهام بدون خادم معًا بالترتيب الذي تحدّده. يمكنك الجمع بين قوة واجهات برمجة التطبيقات من Google Cloud ومنتجات الحوسبة بدون خادم، مثل Cloud Functions وCloud Run، وعمليات طلب البيانات من واجهات برمجة التطبيقات الخارجية لإنشاء تطبيقات مرنة للحوسبة بدون خادم.
لا تتطلّب عمليات سير العمل إدارة البنية الأساسية ويمكن توسيع نطاقها بسلاسة حسب الطلب، بما في ذلك تقليصها إلى الصفر. من خلال نموذج الدفع حسب الاستخدام، لا تدفع إلا مقابل وقت التنفيذ.
في هذا الدرس التطبيقي حول الترميز، ستتعرّف على كيفية ربط خدمات Google Cloud المختلفة وواجهات برمجة تطبيقات HTTP الخارجية بخدمة "مهام سير العمل". على وجه التحديد، ستربط خدمتين عامتين من Cloud Functions وخدمة خاصة من Cloud Run وواجهة برمجة تطبيقات HTTP عامة خارجية في سير عمل واحد.
أهداف الدورة التعليمية
- أساسيات Workflows
- كيفية ربط وظائف Cloud Functions العامة بخدمة "سير العمل"
- كيفية ربط خدمات Cloud Run الخاصة بخدمة Workflows
- كيفية ربط واجهات برمجة تطبيقات HTTP الخارجية بـ "مهام سير العمل"
2. الإعداد والمتطلبات
إعداد البيئة بالسرعة التي تناسبك
- سجِّل الدخول إلى Cloud Console وأنشِئ مشروعًا جديدًا أو أعِد استخدام مشروع حالي. (إذا لم يكن لديك حساب على Gmail أو G Suite، عليك إنشاء حساب).
تذكَّر رقم تعريف المشروع، وهو اسم فريد في جميع مشاريع Google Cloud (الاسم أعلاه مستخدَم حاليًا ولن يكون متاحًا لك، نأسف لذلك). سيتم الإشارة إليه لاحقًا في هذا الدرس التطبيقي حول الترميز باسم PROJECT_ID.
- بعد ذلك، عليك تفعيل الفوترة في Cloud Console من أجل استخدام موارد Google Cloud.
لن تكلفك تجربة هذا الدرس البرمجي الكثير من المال، إن وُجدت تكلفة على الإطلاق. احرص على اتّباع أي تعليمات في قسم "التنظيف" الذي ينصحك بكيفية إيقاف الموارد حتى لا يتم تحصيل رسوم منك بعد هذا البرنامج التعليمي. يمكن لمستخدمي Google Cloud الجدد الاستفادة من برنامج الفترة التجريبية المجانية بقيمة 300 دولار أمريكي.
بدء Cloud Shell
على الرغم من إمكانية تشغيل Google Cloud عن بُعد من الكمبيوتر المحمول، ستستخدم في هذا الدرس التطبيقي حول الترميز Google Cloud Shell، وهي بيئة سطر أوامر تعمل في السحابة الإلكترونية.
من وحدة تحكّم Google Cloud Platform، انقر على رمز Cloud Shell في شريط الأدوات العلوي الأيسر:
لن يستغرق توفير البيئة والاتصال بها سوى بضع لحظات. عند الانتهاء، من المفترض أن يظهر لك ما يلي:
يتم تحميل هذه الآلة الافتراضية مزوّدة بكل أدوات التطوير التي ستحتاج إليها. توفّر هذه الخدمة دليلًا منزليًا دائمًا بسعة 5 غيغابايت، وتعمل على Google Cloud، ما يؤدي إلى تحسين أداء الشبكة والمصادقة بشكل كبير. يمكن إكمال جميع المهام في هذا التمرين المعملي باستخدام متصفّح فقط.
3- نظرة عامة على مهام سير العمل
الأساسيات
يتألف سير العمل من سلسلة من الخطوات الموضّحة باستخدام بنية Workflows المستندة إلى YAML. هذا هو تعريف سير العمل. للحصول على شرح مفصّل لبنية YAML في Workflows، يُرجى الاطّلاع على صفحة مرجع البنية.
عند إنشاء سير عمل، يتم نشره، ما يجعله جاهزًا للتنفيذ. التنفيذ هو تشغيل واحد للمنطق الوارد في تعريف سير العمل. تكون جميع عمليات تنفيذ سير العمل مستقلة، ويتيح المنتج عددًا كبيرًا من عمليات التنفيذ المتزامنة.
تفعيل الخدمات
في هذا الدرس التطبيقي حول الترميز، ستربط خدمات Cloud Functions وCloud Run بخدمة Workflows. ستستخدم أيضًا Cloud Build وCloud Storage أثناء إنشاء الخدمات.
فعِّل جميع الخدمات اللازمة:
gcloud services enable \ cloudfunctions.googleapis.com \ run.googleapis.com \ workflows.googleapis.com \ cloudbuild.googleapis.com \ storage.googleapis.com
في الخطوة التالية، ستربط دالتَين من Cloud Functions معًا في سير عمل.
4. نشر أول دالة Cloud
الدالة الأولى هي منشئ أرقام عشوائية في Python.
أنشئ مجلدًا لرمز الدالة وانتقِل إليه:
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، فإنّها تنشئ رقمًا عشوائيًا بين 1 و100 وتعرضه بتنسيق JSON للمتصل.
تعتمد الدالة على Flask لمعالجة HTTP، وعلينا إضافتها كعنصر تابع. تتم إدارة التبعيات في Python باستخدام 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.
يمكنك أيضًا الانتقال إلى عنوان URL الخاص بالدالة باستخدام الأمر curl التالي:
curl $(gcloud functions describe randomgen --format='value(url)')
الدالة جاهزة لسير العمل.
5- نشر دالة Cloud Function الثانية
الدالة الثانية هي مضاعِف. يتم ضرب القيمة المُدخلة في 2.
أنشئ مجلدًا لرمز الدالة وانتقِل إليه:
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، وتضربها في 2، ثم تُرجعها بتنسيق JSON إلى المتصل.
أنشئ ملف requirements.txt نفسه في الدليل نفسه مع المحتوى التالي:
flask>=1.0.2
نفِّذ الدالة باستخدام مشغّل HTTP مع السماح بالطلبات غير المصادق عليها باستخدام الأمر التالي:
gcloud functions deploy multiply \
--runtime python312 \
--trigger-http \
--allow-unauthenticated
بعد نشر الدالة، يمكنك أيضًا الانتقال إلى عنوان URL الخاص بالدالة باستخدام الأمر curl التالي:
curl $(gcloud functions describe multiply --format='value(url)') \
-X POST \
-H "content-type: application/json" \
-d '{"input": 5}'
الدالة جاهزة لسير العمل.
6. ربط دالتَين من Cloud Functions
في سير العمل الأول، اربط الدالتَين معًا.
أنشئ ملف 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
7. ربط واجهة برمجة تطبيقات HTTP خارجية
بعد ذلك، ستربط 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}
يقدّم سير العمل الآن ناتج دالة الضرب إلى استدعاء دالة السجلّ في math.js.
ستساعدك واجهة المستخدِم في تعديل سير العمل ونشره. بعد نشر سير العمل، انقر على Execute لتنفيذه. ستظهر لك تفاصيل التنفيذ:

لاحظ رمز الحالة 200 وbody مع ناتج دالة السجلّ.
لقد أضفت للتو خدمة خارجية إلى سير عملنا، هذا رائع!
8. نشر خدمة 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، ومن هنا يأتي الرمز البرمجي أعلاه.
عندما تتلقّى هذه الدالة طلب 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
بعد نشر الخدمة، تصبح جاهزة لسير العمل.
9. ربط خدمة Cloud Run
قبل أن تتمكّن من ضبط "مهام سير العمل" لطلب خدمة Cloud Run الخاصة، عليك إنشاء حساب خدمة لتستخدمه "مهام سير العمل":
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}
عدِّل سير العمل. يتم تمرير هذا الوقت في حساب الخدمة:
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
10. تهانينا!
تهانينا على إكمال درس البرمجة.
المواضيع التي تناولناها
- أساسيات Workflows
- كيفية ربط وظائف Cloud Functions العامة بخدمة "سير العمل"
- كيفية ربط خدمات Cloud Run الخاصة بخدمة Workflows
- كيفية ربط واجهات برمجة تطبيقات HTTP الخارجية بـ "مهام سير العمل"