مقدمة عن التنسيق بدون خادم باستخدام Workflows

1. مقدمة

c9b0cc839df0bb8f.png

يمكنك استخدام خطوات سير العمل لإنشاء خطوات سير عمل بدون خادم تربط سلسلة من المهام بدون خادم معًا بالترتيب الذي تحدّده. يمكنك الجمع بين قوة واجهات برمجة التطبيقات من Google Cloud ومنتجات الحوسبة بدون خادم، مثل Cloud Functions وCloud Run، وعمليات طلب البيانات من واجهات برمجة التطبيقات الخارجية لإنشاء تطبيقات مرنة للحوسبة بدون خادم.

لا تتطلّب عمليات سير العمل إدارة البنية الأساسية ويمكن توسيع نطاقها بسلاسة حسب الطلب، بما في ذلك تقليصها إلى الصفر. من خلال نموذج الدفع حسب الاستخدام، لا تدفع إلا مقابل وقت التنفيذ.

في هذا الدرس التطبيقي حول الترميز، ستتعرّف على كيفية ربط خدمات Google Cloud المختلفة وواجهات برمجة تطبيقات HTTP الخارجية بخدمة "مهام سير العمل". على وجه التحديد، ستربط خدمتين عامتين من Cloud Functions وخدمة خاصة من Cloud Run وواجهة برمجة تطبيقات HTTP عامة خارجية في سير عمل واحد.

أهداف الدورة التعليمية

  • أساسيات Workflows
  • كيفية ربط وظائف Cloud Functions العامة بخدمة "سير العمل"
  • كيفية ربط خدمات Cloud Run الخاصة بخدمة Workflows
  • كيفية ربط واجهات برمجة تطبيقات HTTP الخارجية بـ "مهام سير العمل"

2. الإعداد والمتطلبات

إعداد البيئة بالسرعة التي تناسبك

  1. سجِّل الدخول إلى Cloud Console وأنشِئ مشروعًا جديدًا أو أعِد استخدام مشروع حالي. (إذا لم يكن لديك حساب على Gmail أو G Suite، عليك إنشاء حساب).

H_hgylo4zxOllHaAbPKJ7VyqCKPDUnDhkr-BsBIFBsrB6TYSisg6LX-uqmMhh4sXUy_hoa2Qv87C2nFmkg-QAcCiZZp0qtpf6VPaNEEfP_iqt29KVLD-gklBWugQVeOWsFnJmNjHDwdcCPqfBIwNO4R-0fNQLUC4aYXOOZhKhjUnakFLZJGeziw2ikOxGjGkCHDwN5x5kCbPFB8fiOzZnX-GfuzQ8Ox-UU15BwHirkVPR_0RJwl0oXrhqZmMIvZMa_uwHugBJIdx5-bZ6Z8QjgLzVCxk93d6E2bbonzATKA4jFZReoQ-fORxZZLEi5C3D-ubnv6nL-eP-iyh7qAsWyq_nyzzuEoPFD1wFOFZOe4FWhPBJjUDncnTxTImT3Ts9TM54f4nPpsAp52O0y3Cb19IceAEgQ

تذكَّر رقم تعريف المشروع، وهو اسم فريد في جميع مشاريع Google Cloud (الاسم أعلاه مستخدَم حاليًا ولن يكون متاحًا لك، نأسف لذلك). سيتم الإشارة إليه لاحقًا في هذا الدرس التطبيقي حول الترميز باسم PROJECT_ID.

  1. بعد ذلك، عليك تفعيل الفوترة في Cloud Console من أجل استخدام موارد Google Cloud.

لن تكلفك تجربة هذا الدرس البرمجي الكثير من المال، إن وُجدت تكلفة على الإطلاق. احرص على اتّباع أي تعليمات في قسم "التنظيف" الذي ينصحك بكيفية إيقاف الموارد حتى لا يتم تحصيل رسوم منك بعد هذا البرنامج التعليمي. يمكن لمستخدمي Google Cloud الجدد الاستفادة من برنامج الفترة التجريبية المجانية بقيمة 300 دولار أمريكي.

بدء Cloud Shell

على الرغم من إمكانية تشغيل Google Cloud عن بُعد من الكمبيوتر المحمول، ستستخدم في هذا الدرس التطبيقي حول الترميز Google Cloud Shell، وهي بيئة سطر أوامر تعمل في السحابة الإلكترونية.

من وحدة تحكّم Google Cloud Platform، انقر على رمز Cloud Shell في شريط الأدوات العلوي الأيسر:

STgwiN06Y0s_gL7i9bTed8duc9tWOIaFw0z_4QOjc-jeOmuH2TBK8l4udei56CKPLoM_i1yEF6pn5Ga88eniJQoEh8cAiTH79gWUHJdKOw0oiBZfBpOdcEOl6p29i4mvPe_A6UMJBQ

لن يستغرق توفير البيئة والاتصال بها سوى بضع لحظات. عند الانتهاء، من المفترض أن يظهر لك ما يلي:

r6WRHJDzL-GdB5VDxMWa67_cQxRR_x_xCG5xdt9Nilfuwe9fTGAwM9XSZbNPWvDSFtrZ7DDecKqR5_pIq2IJJ9puAMkC3Kt4JbN9jfMX3gAwTNHNqFmqOJ-3iIX5HSePO4dNVZUkNA

يتم تحميل هذه الآلة الافتراضية مزوّدة بكل أدوات التطوير التي ستحتاج إليها. توفّر هذه الخدمة دليلًا منزليًا دائمًا بسعة 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:

7608a7991b33bbb0.png

ابحث عن سير العمل وانقر على علامة التبويب Definition:

f3c8c4d3ffa49b1b.png

عدِّل تعريف سير العمل وأدرِج طلبًا إلى 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 لتنفيذه. ستظهر لك تفاصيل التنفيذ:

b40c76ee43a1ce65.png

لاحظ رمز الحالة 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 الخارجية بـ "مهام سير العمل"