توسيع نطاق مجموعات العاملين في Cloud Run تلقائيًا استنادًا إلى حجم قائمة انتظار Pub/Sub باستخدام CREMA

1. مقدمة

نظرة عامة

يوضّح لك هذا البرنامج التعليمي كيفية نشر مجموعة من العاملين (المستهلكين) في Cloud Run لمعالجة رسائل Pub/Sub، وتوسيع نطاق مثيلات المستهلكين تلقائيًا استنادًا إلى عمق قائمة الانتظار باستخدام التوسيع التلقائي للمقاييس الخارجية في Cloud Run (CREMA).

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

في هذا الدرس التطبيقي حول الترميز، ستتعلّم كيفية:

  • أنشئ موضوعًا واشتراكًا في Pub/Sub وادفع الرسائل إلى هذا الموضوع.
  • نشر مجموعة من العاملين (المستهلكين) في Cloud Run الذين يستهلكون الرسائل من Pub/Sub
  • يمكنك نشر مشروع CREMA على GitHub كخدمة Cloud Run لتوسيع مجموعة العاملين تلقائيًا استنادًا إلى عدد الرسائل في اشتراك Pub/Sub.
  • اختبِر إعدادات التوسيع التلقائي من خلال إنشاء حمل عن طريق تشغيل نص برمجي بلغة Python محليًا.

2. ضبط متغيرات البيئة

بما أنّه يتم استخدام العديد من متغيرات البيئة في جميع أنحاء هذا الدرس العملي، ننصحك بتنفيذ

set -u

التي ستنبّهك إذا حاولت استخدام متغيّر بيئة لم يتم ضبطه بعد. للتراجع عن هذا الإعداد، شغِّل set +u

أولاً، غيِّر المتغيّر التالي إلى رقم تعريف مشروعك.

export PROJECT_ID=<YOUR_PROJECT_ID>

ثم اضبطه كمشروع لهذا الدرس العملي.

gcloud config set project $PROJECT_ID

بعد ذلك، اضبط متغيّرات البيئة المستخدَمة في هذا الدرس التطبيقي.

export REGION=us-central1
export TOPIC_ID=crema-pubsub-topic
export SUBSCRIPTION_ID=crema-pubsub-sub
export CREMA_SA_NAME=crema-service-account
export CONSUMER_SA_NAME=consumer-service-account
export CONSUMER_WORKER_POOL_NAME=worker-pool-consumer
export CREMA_SERVICE_NAME=my-crema-service

إنشاء دليل لهذا الدرس التطبيقي حول الترميز

mkdir crema-pubsub-codelab
cd crema-pubsub-codelab

تفعيل واجهات برمجة التطبيقات

gcloud services enable \
        artifactregistry.googleapis.com \
        cloudbuild.googleapis.com \
        run.googleapis.com \
        parametermanager.googleapis.com

أخيرًا، تأكَّد من أنّ gcloud يستخدم أحدث إصدار.

gcloud components update

3- إعداد Pub/Sub

أنشئ الموضوع واشتراك السحب الذي ستعالجه مجموعة العمال. Bash

أنشئ الموضوع.

gcloud pubsub topics create $TOPIC_ID

أنشئ الاشتراك.

gcloud pubsub subscriptions create $SUBSCRIPTION_ID --topic=$TOPIC_ID

4. إدارة الهوية وإمكانية الوصول وحسابات الخدمة

يُنصح بإنشاء حساب خدمة لكل مورد من موارد Cloud Run. في هذا الدرس التطبيقي حول الترميز، ستنشئ ما يلي:

  • حساب الخدمة للمستهلك: هوية مجموعة العمال التي تعالج رسائل Pub/Sub.
  • ‫CREMA SA: هوية خدمة التحجيم التلقائي CREMA

إنشاء حسابات خدمة

أنشئ حساب الخدمة الخاص بالمستهلك في مجموعة العمّال:

gcloud iam service-accounts create $CONSUMER_SA_NAME \
  --display-name="PubSub Consumer Service Account"

أنشئ حساب خدمة CREMA في مجموعة العمّال:

gcloud iam service-accounts create $CREMA_SA_NAME \
  --display-name="CREMA Autoscaler Service Account"

منح الأذونات إلى Consumer SA

امنح أذونات لحساب الخدمة المستهلك لمجموعة العمال لسحب الرسائل من الاشتراك.

gcloud pubsub subscriptions add-iam-policy-binding $SUBSCRIPTION_ID \
  --member="serviceAccount:$CONSUMER_SA_NAME@$PROJECT_ID.iam.gserviceaccount.com" \
  --role="roles/pubsub.subscriber"

منح الأذونات إلى CREMA SA

يحتاج CREMA إلى أذونات لقراءة المَعلمات وتوسيع مجموعة العاملين ومراقبة مقاييس Pub/Sub.

  1. الوصول إلى "مدير المَعلمات" (أداة قراءة الإعدادات):
gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member="serviceAccount:$CREMA_SA_NAME@$PROJECT_ID.iam.gserviceaccount.com" \
  --role="roles/parametermanager.parameterViewer"
  1. توسيع نطاق مجموعة العمال (Cloud Run Developer):
gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member="serviceAccount:$CREMA_SA_NAME@$PROJECT_ID.iam.gserviceaccount.com" \
  --role="roles/run.developer"
  1. مراقبة Pub/Sub:

منح دور "مُشاهد المراقبة"

gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:$CREMA_SA_NAME@$PROJECT_ID.iam.gserviceaccount.com" \
--role="roles/monitoring.viewer"

إضافة سياسة إلى الاشتراك في خدمة CREMA SA للاطّلاع عليها

gcloud pubsub subscriptions add-iam-policy-binding $SUBSCRIPTION_ID \
  --member="serviceAccount:$CREMA_SA_NAME@$PROJECT_ID.iam.gserviceaccount.com" \
  --role="roles/pubsub.viewer"

يحتاج حساب الخدمة CREMA أيضًا إلى دور "مستخدم حساب الخدمة"، وهو مطلوب لتغيير أعداد المثيلات:

gcloud iam service-accounts add-iam-policy-binding \
    $CONSUMER_SA_NAME@$PROJECT_ID.iam.gserviceaccount.com \
    --member="serviceAccount:$CREMA_SA_NAME@$PROJECT_ID.iam.gserviceaccount.com" \
    --role="roles/iam.serviceAccountUser"

5- التحقّق من أذونات المشرف الفائق

قبل المتابعة مع درس البرمجة، تأكَّد من أنّ حساب الخدمة CREMA لديه الأدوار الصحيحة على مستوى المشروع.

gcloud projects get-iam-policy $PROJECT_ID \
  --flatten="bindings[].members" \
  --format="table(bindings.role)" \
  --filter="bindings.members:serviceAccount:$CREMA_SA_NAME@$PROJECT_ID.iam.gserviceaccount.com"

من المفترض أن يؤدي ذلك إلى ما يلي:

roles/monitoring.viewer
roles/parametermanager.parameterViewer
roles/run.developer

تأكَّد من أنّ اشتراك Pub/Sub يتضمّن سياسة تسمح لحساب الخدمة CREMA بعرضه.

gcloud pubsub subscriptions get-iam-policy $SUBSCRIPTION_ID \
  --flatten="bindings[].members" \
  --filter="bindings.members:serviceAccount:$CREMA_SA_NAME@$PROJECT_ID.iam.gserviceaccount.com" \
  --format="table(bindings.role)"

يجب أن يؤدي ذلك إلى

roles/pubsub.viewer

والتأكّد من أنّ حساب الخدمة CREMA لديه دور "مستخدم حساب الخدمة"

gcloud iam service-accounts get-iam-policy \
  $CONSUMER_SA_NAME@$PROJECT_ID.iam.gserviceaccount.com \
  --flatten="bindings[].members" \
  --filter="bindings.members:serviceAccount:$CREMA_SA_NAME@$PROJECT_ID.iam.gserviceaccount.com"

يجب أن يؤدي ذلك إلى ما يلي

bindings:
  members: serviceAccount:crema-service-account@<PROJECT_ID>.iam.gserviceaccount.com
  role: roles/iam.serviceAccountUser

ويتم منح حساب الخدمة Worker Pool Consumer دور المشترك في Pub/Sub

gcloud pubsub subscriptions get-iam-policy $SUBSCRIPTION_ID \
  --flatten="bindings[].members" \
  --filter="bindings.members:serviceAccount:$CONSUMER_SA_NAME@$PROJECT_ID.iam.gserviceaccount.com" \
  --format="table(bindings.role)"

يجب أن يؤدي ذلك إلى

ROLE
roles/pubsub.subscriber

6. إنشاء مجموعة العمّال المستهلكين ونشرها

أنشئ دليلاً لرمز المستهلك وأدخِله.

mkdir consumer
cd consumer
  1. إنشاء ملف consumer.py
import os
import time
from google.cloud import pubsub_v1
from concurrent.futures import TimeoutError

# Configuration
PROJECT_ID = os.environ.get('PROJECT_ID')
SUBSCRIPTION_ID = os.environ.get('SUBSCRIPTION_ID')

subscription_path = f"projects/{PROJECT_ID}/subscriptions/{SUBSCRIPTION_ID}"

print(f"Worker Pool instance starting. Watching {subscription_path}...")

subscriber = pubsub_v1.SubscriberClient()

def callback(message):
    try:
        data = message.data.decode("utf-8")
        print(f"Processing job: {data}")
        time.sleep(5)  # Simulate work
        print(f"Done {data}")
        message.ack()
    except Exception as e:
        print(f"Error processing message: {e}")
        message.nack()

streaming_pull_future = subscriber.subscribe(subscription_path, callback=callback)
print(f"Listening for messages on {subscription_path}...")

# Wrap subscriber in a 'with' block to automatically call close() when done.
with subscriber:
    try:
        # When `timeout` is not set, result() will block indefinitely,
        # unless an exception is encountered first.
        streaming_pull_future.result()
    except TimeoutError:
        streaming_pull_future.cancel()  # Trigger the shutdown.
        streaming_pull_future.result()  # Block until the shutdown is complete.
    except Exception as e:
        print(f"Streaming pull failed: {e}")
  1. إنشاء Dockerfile
FROM python:3.12-slim
RUN pip install google-cloud-pubsub
COPY consumer.py .
CMD ["python", "-u", "consumer.py"]
  1. نشر مجموعة العمّال المستهلكين

يوصي هذا الدرس التطبيقي البرمجي بنشر مجموعة العمال مع 0 مثيل للبدء، حتى تتمكّن من مشاهدة CREMA وهي توسّع مجموعة العمال عندما ترصد رسائل Pub/Sub في الاشتراك.

gcloud beta run worker-pools deploy $CONSUMER_WORKER_POOL_NAME \
  --source . \
  --region $REGION \
  --service-account="$CONSUMER_SA_NAME@$PROJECT_ID.iam.gserviceaccount.com" \
  --instances=0 \
  --set-env-vars PROJECT_ID=$PROJECT_ID,SUBSCRIPTION_ID=$SUBSCRIPTION_ID

7. ضبط CREMA

  1. انتقِل مجددًا إلى الدليل الجذري لمشروعك.
cd ..
  1. إنشاء ملف الإعداد أنشئ ملفًا باسم crema-config.yaml
apiVersion: crema/v1
kind: CremaConfig
spec:
  pollingInterval: 30
  triggerAuthentications:
    - metadata:
        name: adc-trigger-auth
      spec:
        podIdentity:
          provider: gcp
  scaledObjects:
    - spec:
        scaleTargetRef:
          name: projects/PROJECT_ID_PLACEHOLDER/locations/REGION_PLACEHOLDER/workerpools/CONSUMER_WORKER_POOL_NAME_PLACEHOLDER
        triggers:
          - type: gcp-pubsub
            metadata:
              subscriptionName: "SUBSCRIPTION_ID_PLACEHOLDER"
              # Target number of undelivered messages per worker instance
              value: "10"
              mode: "SubscriptionSize"
            authenticationRef:
              name: adc-trigger-auth
  1. استبدال المتغيرات
sed -i "s/PROJECT_ID_PLACEHOLDER/$PROJECT_ID/g" crema-config.yaml
sed -i "s/REGION_PLACEHOLDER/$REGION/g" crema-config.yaml
sed -i "s/CONSUMER_WORKER_POOL_NAME_PLACEHOLDER/$CONSUMER_WORKER_POOL_NAME/g" crema-config.yaml
sed -i "s/SUBSCRIPTION_ID_PLACEHOLDER/$SUBSCRIPTION_ID/g" crema-config.yaml
  1. تأكَّد من صحة رقم crema-config.yaml
if grep -q "_PLACEHOLDER" crema-config.yaml; then
  echo "❌ ERROR: Validations failed. '_PLACEHOLDER' was found in crema-config.yaml."
  echo "Please check your environment variables and run the 'sed' commands again."
else
  echo "✅ Config check passed: No placeholders found."
fi
  1. التحميل إلى "أداة إدارة المَعلمات"

ضبط متغيرات بيئة إضافية في "أداة إدارة المعلَمات"

export PARAMETER_ID=crema-config
export PARAMETER_REGION=global
export PARAMETER_VERSION=1

إنشاء مورد المَعلمة

gcloud parametermanager parameters create $PARAMETER_ID \
  --location=$PARAMETER_REGION \
  --parameter-format=YAML

إنشاء الإصدار 1 من المَعلمة

gcloud parametermanager parameters versions create $PARAMETER_VERSION \
  --parameter=crema-config \
  --project=$PROJECT_ID \
  --location=$PARAMETER_REGION \
  --payload-data-from-file=crema-config.yaml

التأكّد من إضافة المَعلمة بنجاح

gcloud parametermanager parameters versions list \
  --parameter=$PARAMETER_ID \
  --location=$PARAMETER_REGION

من المفترض أن يظهر لك محتوى مثل

projects/<YOUR_PROJECT_ID>/locations/global/parameters/crema-config/versions/1

8. نشر خدمة CREMA

في هذا القسم، ستنفّذ خدمة توسيع نطاق CREMA تلقائيًا. ستستخدم الصورة المتاحة للجميع.

  1. ضبط متغيرات البيئة اللازمة لأداة CREMA
CREMA_CONFIG_PARAM_VERSION=projects/$PROJECT_ID/locations/$PARAMETER_REGION/parameters/$PARAMETER_ID/versions/$PARAMETER_VERSION
  1. التحقّق من مسار اسم الإصدار
echo $CREMA_CONFIG_PARAM_VERSION

يجب أن يبدو على النحو التالي

projects/<YOUR_PROJECT>/locations/global/parameters/crema-config/versions/1
  1. ضبط متغير البيئة لصورة CREMA
IMAGE=us-central1-docker.pkg.dev/cloud-run-oss-images/crema-v1/autoscaler:1.0
  1. ونشر خدمة CREMA

يُرجى العِلم أنّ الصورة الأساسية مطلوبة.

gcloud beta run deploy $CREMA_SERVICE_NAME \
  --image=$IMAGE \
  --region=${REGION} \
  --service-account="${CREMA_SA_NAME}@${PROJECT_ID}.iam.gserviceaccount.com" \
  --no-allow-unauthenticated \
  --no-cpu-throttling \
  --labels=created-by=crema \
  --base-image=us-central1-docker.pkg.dev/serverless-runtimes/google-24/runtimes/java25 \
  --set-env-vars="CREMA_CONFIG=${CREMA_CONFIG_PARAM_VERSION},OUTPUT_SCALER_METRICS=True,ENABLE_CLOUD_LOGGING=True"

9- اختبار التحميل

  1. إنشاء نص برمجي ينشر الرسائل إلى موضوع Pub/Sub
touch load-pubsub.sh
  1. أضِف الرمز التالي إلى ملف load-pubsub.sh
#!/bin/bash
TOPIC_ID=${TOPIC_ID} 
PROJECT_ID=${PROJECT_ID}
NUM_MESSAGES=100

echo "Publishing $NUM_MESSAGES messages to topic $TOPIC_ID..."

for i in $(seq 1 $NUM_MESSAGES); do
  gcloud pubsub topics publish $TOPIC_ID --message="job-$i" --project=$PROJECT_ID &
  if (( $i % 10 == 0 )); then
    wait
    echo "Published $i messages..."
  fi
done
wait
echo "Done. All messages published."
  1. إجراء اختبار التحميل
chmod +x load-pubsub.sh
./load-pubsub.sh
  1. انتظِر من 3 إلى 4 دقائق أثناء مراقبة عملية تغيير الحجم. اطّلِع على سجلّات CREMA لترى اقتراحاتها بشأن الآلات الافتراضية استنادًا إلى إعداد authenticationRef الجديد.
gcloud logging read "resource.type=cloud_run_revision AND resource.labels.service_name=$CREMA_SERVICE_NAME AND textPayload:SCALER" \
  --limit=20 \
  --format="value(textPayload)" \
  --freshness=5m
  1. مراقبة المعالجة: اطّلِع على سجلّات المستهلك لمعرفة ما إذا كانت قيد التشغيل.
gcloud beta run worker-pools logs tail $CONSUMER_WORKER_POOL_NAME --region=$REGION

من المفترض أن تظهر لك سجلّات مشابهة لما يلي:

Done job-100

10. تحديد المشاكل وحلّها

أولاً، عليك تحديد ما إذا كانت المشكلة في إعدادات خدمة CREMA أو في إعدادات مستهلك PubSub.

اضبط أداة توسيع نطاق مستهلك PubSub التلقائية على 1 بدلاً من 0. إذا بدأت على الفور في معالجة رسائل pubsub، فهذا يعني أنّ هناك مشكلة في CREMA. إذا لم تتم معالجة رسائل pubsub، يعني ذلك أنّ هناك مشكلة في مستهلك pubsub.

11. تهانينا!

تهانينا على إكمال هذا الدرس العملي.

ننصحك بمراجعة مستندات Cloud Run.

المواضيع التي تناولناها

  • كيفية إنشاء موضوع واشتراك في Pub/Sub وإرسال الرسائل إلى هذا الموضوع
  • كيفية نشر مجموعة من العاملين (المستهلكين) في Cloud Run الذين يستهلكون الرسائل من Pub/Sub
  • كيفية نشر مشروع CREMA على GitHub كخدمة Cloud Run لتوسيع مجموعة العاملين تلقائيًا استنادًا إلى عدد الرسائل في اشتراك Pub/Sub
  • كيفية اختبار إعدادات التوسيع التلقائي من خلال إنشاء حمل عن طريق تشغيل نص برمجي بلغة Python محليًا

12. تَنظيم

لتجنُّب تحمّل رسوم في حسابك على Google Cloud مقابل الموارد المستخدَمة في هذا البرنامج التعليمي، يمكنك إما حذف الموارد التي أنشأتها في هذا البرنامج أو حذف المشروع بأكمله.

حذف المراجع المستخدَمة في هذا الدرس البرمجي

  1. حذف خدمة CREMA في Cloud Run
gcloud run services delete $CREMA_SERVICE_NAME --region=$REGION --quiet
  1. حذف مستهلك مجموعة العاملين في Cloud Run
gcloud beta run worker-pools delete $CONSUMER_WORKER_POOL_NAME --region=$REGION --quiet
  1. حذف الاشتراك والموضوع في Pub/Sub
gcloud pubsub subscriptions delete $SUBSCRIPTION_ID --quiet
gcloud pubsub topics delete $TOPIC_ID --quiet
  1. حذف إعداد "مدير المَعلمات"

حذف الإصدار داخل المَعلمة

gcloud parametermanager parameters versions delete $PARAMETER_VERSION \
  --parameter=$PARAMETER_ID \
  --location=$PARAMETER_REGION \
  --quiet

الآن، احذف المَعلمة الفارغة.

gcloud parametermanager parameters delete $PARAMETER_ID \
  --location=$PARAMETER_REGION \
  --quiet
  1. حذف حسابات الخدمة
gcloud iam service-accounts delete "$CREMA_SA_NAME@$PROJECT_ID.iam.gserviceaccount.com" --quiet
gcloud iam service-accounts delete "$CONSUMER_SA_NAME@$PROJECT_ID.iam.gserviceaccount.com" --quiet

أو حذف المشروع بأكمله

لحذف المشروع بأكمله، انتقِل إلى إدارة المراجع، واختَر المشروع الذي أنشأته في الخطوة 2، ثم انقر على "حذف". إذا حذفت المشروع، عليك تغيير المشاريع في Cloud SDK. يمكنك الاطّلاع على قائمة بجميع المشاريع المتاحة من خلال تنفيذ gcloud projects list.