لمحة عن هذا الدرس التطبيقي حول الترميز
1. مقدمة
نظرة عامة
وظائف Cloud Run هي خدمة Functions-as-a-Service من Google Cloud المستندة إلى Cloud Run وEventarc، ما يمنحك مزيدًا من التحكّم المتقدّم في الأداء وقابلية التوسّع، ومزيدًا من التحكّم في وقت تشغيل الدوالّ وعوامل التفعيل من أكثر من 90 مصدر حدث.
سيرشدك هذا الدليل التعليمي إلى إنشاء وظائف Cloud Run تستجيب لطلبات HTTP ويتم تشغيلها من خلال رسائل Pub/Sub وسجلّات تدقيق Cloud.
يستخدم هذا الدرس التطبيقي أيضًا تحديثات الصور الأساسية التلقائية لعمليات نشر الدوالّ من خلال تحديد صورة أساسية باستخدام العلامة --base-image
. تتيح التحديثات التلقائية للصورة الأساسية في Cloud Run لشركة Google إجراء تصحيحات أمان لنظام التشغيل ومكونات وقت تشغيل اللغة في الصورة الأساسية تلقائيًا. لست بحاجة إلى إعادة إنشاء خدمتك أو إعادة نشرها لتتمكّن من تعديل الصورة الأساسية. لمزيد من المعلومات، يمكنك الاطّلاع على التعديلات التلقائية على الصور الأساسية.
إذا كنت تفضّل عدم استخدام التعديلات التلقائية للصور الأساسية، يمكنك إزالة العلامة --base-image
من الأمثلة الموضّحة في هذا الدليل التعليمي.
المُعطيات
- نظرة عامة على دوالّ Cloud Run وكيفية استخدام التعديلات التلقائية للصورة الأساسية
- كيفية كتابة دالة تستجيب لطلبات HTTP
- كيفية كتابة دالة تستجيب لرسائل Pub/Sub
- كيفية كتابة دالة تستجيب لأحداث Cloud Storage
- كيفية تقسيم عدد الزيارات بين نسختَين
- كيفية التخلص من عمليات التشغيل على البارد باستخدام الحد الأدنى من النُسخ
2. الإعداد والمتطلبات
إنشاء مجلد رئيسي
أنشئ مجلدًا رئيسيًا لجميع الأمثلة.
mkdir crf-codelab cd crf-codelab
إعداد متغيّرات البيئة
اضبط متغيّرات البيئة التي سيتم استخدامها في هذا الدرس التطبيقي حول الترميز.
gcloud config set project <YOUR-PROJECT-ID> REGION=<YOUR_REGION> PROJECT_ID=$(gcloud config get-value project)
تفعيل واجهات برمجة التطبيقات
فعِّل جميع الخدمات اللازمة:
gcloud services enable \ artifactregistry.googleapis.com \ cloudbuild.googleapis.com \ eventarc.googleapis.com \ run.googleapis.com \ logging.googleapis.com \ pubsub.googleapis.com
3. دالة HTTP
بالنسبة إلى الدالة الأولى، لننشئ دالة Node.js مُعتمَدة تستجيب لطلبات HTTP. لنستخدم أيضًا مهلة 10 دقائق لإظهار كيف يمكن أن تحصل الدالة على وقت إضافي للردّ على طلبات HTTP.
إنشاء
أنشِئ مجلدًا للتطبيق وانتقِل إليه:
mkdir hello-http cd hello-http
أنشئ ملف index.js
يستجيب لطلبات HTTP:
const functions = require('@google-cloud/functions-framework'); functions.http('helloWorld', (req, res) => { res.status(200).send('HTTP with Node.js in Cloud Run functions!'); });
أنشئ ملف package.json
لتحديد التبعيات:
{ "name": "nodejs-run-functions-codelab", "version": "0.0.1", "main": "index.js", "dependencies": { "@google-cloud/functions-framework": "^2.0.0" } }
النشر
نشر الدالة:
gcloud run deploy nodejs-run-function \ --source . \ --function helloWorld \ --base-image nodejs22 \ --region $REGION \ --timeout 600 \ --no-allow-unauthenticated
يستخدم هذا الأمر حِزم الإنشاء لتحويل رمز الدالة البرمجي المصدر إلى صورة حاوية جاهزة للنشر.
ملاحظات:
- تُستخدَم العلامة
--source
لإخبار Cloud Run بإنشاء الدالة في خدمة مستندة إلى حاوية قابلة للتشغيل. - يتم استخدام العلامة
--function
(new) لضبط نقطة دخول الخدمة الجديدة لتكون توقيع الدالة الذي تريد استدعائه. - تُحدِّد العلامة
--base-image
(جديد) بيئة الصورة الأساسية لوظيفتك، مثلnodejs22
أوpython312
أوgo123
أوjava21
أوdotnet8
أوruby33
أوphp83
. لمعرفة مزيد من التفاصيل عن الصور الأساسية والحِزم المضمّنة في كل صورة، يُرجى الاطّلاع على الصور الأساسية لأنظمة التشغيل. - (اختياري) تسمح العلامة
--timeout
للدالة بتحديد مهلة أطول للاستجابة لطلبات HTTP. في هذا المثال، يتم استخدام 600 ثانية لعرض وقت استجابة يبلغ 10 دقائق. - (اختياري) الرمز
--no-allow-unauthenticated
لمنع إمكانية استدعاء الدالة بشكل علني
الاختبار
اختبِر الدالة باستخدام الأوامر التالية:
# get the Service URL SERVICE_URL="$(gcloud run services describe nodejs-run-function --region $REGION --format 'value(status.url)')" # invoke the service curl -H "Authorization: bearer $(gcloud auth print-identity-token)" -X GET $SERVICE_URL
من المفترض أن تظهر لك الرسالة HTTP with Node.js in Cloud Run functions!
كردّ على طلبك.
4. وظيفة Pub/Sub
بالنسبة إلى الدالة الثانية، لننشئ دالة Python يتم تفعيلها من خلال رسالة Pub/Sub منشورة في موضوع معيّن.
إعداد رموز مصادقة Pub/Sub
إذا فعّلت حساب خدمة Pub/Sub في 8 نيسان (أبريل) 2021 أو قبله، امنح الدور iam.serviceAccountTokenCreator
لحساب خدمة Pub/Sub:
PROJECT_NUMBER=$(gcloud projects list --filter="project_id:$PROJECT_ID" --format='value(project_number)') gcloud projects add-iam-policy-binding $PROJECT_ID \ --member serviceAccount:service-$PROJECT_NUMBER@gcp-sa-pubsub.iam.gserviceaccount.com \ --role roles/iam.serviceAccountTokenCreator
إنشاء
أنشئ موضوعًا على Pub/Sub لاستخدامه في العيّنة:
TOPIC=cloud-run-functions-pubsub-topic gcloud pubsub topics create $TOPIC
أنشِئ مجلدًا للتطبيق وانتقِل إليه:
mkdir ../hello-pubsub cd ../hello-pubsub
أنشِئ ملفًا بتنسيق main.py
يسجِّل رسالة تحتوي على معرّف CloudEvent:
import functions_framework @functions_framework.cloud_event def hello_pubsub(cloud_event): print('Pub/Sub with Python in Cloud Run functions! Id: ' + cloud_event['id'])
أنشئ ملف requirements.txt
يتضمّن المحتوى التالي لتحديد التبعيات:
functions-framework==3.*
النشر
نشر الدالة:
gcloud run deploy python-pubsub-function \ --source . \ --function hello_pubsub \ --base-image python313 \ --region $REGION \ --no-allow-unauthenticated
استرِد رقم المشروع الذي سيتم استخدامه لهوية حساب الخدمة.
PROJECT_NUMBER=$(gcloud projects list --filter="project_id:$PROJECT_ID" --format='value(project_number)')
إنشاء مشغِّل
gcloud eventarc triggers create python-pubsub-function-trigger \ --location=$REGION \ --destination-run-service=python-pubsub-function \ --destination-run-region=$REGION \ --event-filters="type=google.cloud.pubsub.topic.v1.messagePublished" \ --transport-topic=projects/$PROJECT_ID/topics/$TOPIC \ --service-account=$PROJECT_NUMBER-compute@developer.gserviceaccount.com
الاختبار
اختبِر الدالة من خلال إرسال رسالة إلى الموضوع:
gcloud pubsub topics publish $TOPIC --message="Hello World"
من المفترض أن يظهر لك حدث CloudEvent المستلَم في السجلات:
gcloud run services logs read python-pubsub-function --region $REGION --limit=10
5. دالة تخزين في السحابة الإلكترونية
بالنسبة إلى الدالة التالية، لننشئ دالة Node.js تستجيب للأحداث الواردة من حزمة Cloud Storage.
إعداد
لاستخدام وظائف Cloud Storage، عليك منح دور pubsub.publisher
IAM لحساب خدمة Cloud Storage:
SERVICE_ACCOUNT=$(gsutil kms serviceaccount -p $PROJECT_NUMBER) gcloud projects add-iam-policy-binding $PROJECT_ID \ --member serviceAccount:$SERVICE_ACCOUNT \ --role roles/pubsub.publisher
إنشاء
أنشِئ مجلدًا للتطبيق وانتقِل إليه:
mkdir ../hello-storage cd ../hello-storage
أنشئ ملف index.js
يستجيب ببساطة لأحداث Cloud Storage:
const functions = require('@google-cloud/functions-framework'); functions.cloudEvent('helloStorage', (cloudevent) => { console.log('Cloud Storage event with Node.js in Cloud Run functions!'); console.log(cloudevent); });
أنشئ ملف package.json
لتحديد التبعيات:
{ "name": "nodejs-crf-cloud-storage", "version": "0.0.1", "main": "index.js", "dependencies": { "@google-cloud/functions-framework": "^2.0.0" } }
النشر
أولاً، أنشئ حزمة في Cloud Storage (أو استخدِم حزمة حالية لديك):
export BUCKET_NAME="gcf-storage-$PROJECT_ID" export BUCKET="gs://gcf-storage-$PROJECT_ID" gsutil mb -l $REGION $BUCKET
نشر الدالة:
gcloud run deploy nodejs-crf-cloud-storage \ --source . \ --base-image nodejs22 \ --function helloStorage \ --region $REGION \ --no-allow-unauthenticated
بعد نشر الدالة، يمكنك الاطّلاع عليها ضمن قسم Cloud Run في Cloud Console.
الآن، أنشئ عبارة تشغيل Eventarc.
BUCKET_REGION=$REGION gcloud eventarc triggers create nodejs-crf-cloud-storage-trigger \ --location=$BUCKET_REGION \ --destination-run-service=nodejs-crf-cloud-storage \ --destination-run-region=$REGION \ --event-filters="type=google.cloud.storage.object.v1.finalized" \ --event-filters="bucket=$BUCKET_NAME" \ --service-account=$PROJECT_NUMBER-compute@developer.gserviceaccount.com
الاختبار
اختبِر الدالة من خلال تحميل ملف إلى الحزمة:
echo "Hello World" > random.txt gsutil cp random.txt $BUCKET/random.txt
من المفترض أن يظهر لك حدث CloudEvent المستلَم في السجلات:
gcloud run services logs read nodejs-crf-cloud-storage --region $REGION --limit=10
6. تقسيم عدد الزيارات
تتيح دوالّ Cloud Run إنشاء نُسخ متعددة من دوالّك، وتقسيم الزيارات بين النُسخ المختلفة، وإعادة دوالّك إلى إصدار سابق.
في هذه الخطوة، ستنشر نسختَين من دالة ثم تقسم الزيارات بينهما بنسبة 50% إلى 50%.
إنشاء
أنشِئ مجلدًا للتطبيق وانتقِل إليه:
mkdir ../traffic-splitting cd ../traffic-splitting
أنشئ ملف main.py
يتضمّن دالة Python تقرأ متغيّر بيئة اللون وتردّ بـ Hello World
بلون الخلفية هذا:
import os color = os.environ.get('COLOR') def hello_world(request): return f'<body style="background-color:{color}"><h1>Hello World!</h1></body>'
أنشئ ملف requirements.txt
يتضمّن المحتوى التالي لتحديد التبعيات:
functions-framework==3.*
النشر
يمكنك نشر النسخة الأولى من الدالة التي تتضمّن خلفية برتقالية:
COLOR=orange gcloud run deploy hello-world-colors \ --source . \ --base-image python313 \ --function hello_world \ --region $REGION \ --allow-unauthenticated \ --update-env-vars COLOR=$COLOR
في هذه المرحلة، إذا اختبرت الدالة من خلال عرض عامل تشغيل HTTP (ناتج عنوان URL لأمر النشر أعلاه) في المتصفّح، من المفترض أن يظهر لك الرمز Hello World
على خلفية برتقالية:
يمكنك نشر النسخة الثانية بخلفية صفراء:
COLOR=yellow gcloud run deploy hello-world-colors \ --source . \ --base-image python313 \ --function hello_world \ --region $REGION \ --allow-unauthenticated \ --update-env-vars COLOR=$COLOR
بما أنّ هذه هي النسخة الأخيرة، إذا اختبرت الدالة، من المفترض أن يظهر لك الرمز Hello World
مع خلفية صفراء:
تقسيم عدد الزيارات بنسبة 50/50
لتقسيم عدد الزيارات بين الإصدارَين البرتقالي والأصفر، عليك العثور على أرقام تعريف الإصدارات لخدمات Cloud Run. في ما يلي الأمر للاطّلاع على أرقام تعريف المراجعات:
gcloud run revisions list --service hello-world-colors \ --region $REGION --format 'value(REVISION)'
من المفترض أن يظهر لك الإخراج على النحو التالي:
hello-world-colors-00001-man hello-world-colors-00002-wok
الآن، عليك تقسيم عدد الزيارات بين هاتين المراجعتَين على النحو التالي (عدِّل X-XXX
وفقًا لأسماء المراجعات):
gcloud run services update-traffic hello-world-colors \ --region $REGION \ --to-revisions hello-world-colors-0000X-XXX=50,hello-world-colors-0000X-XXX=50
الاختبار
اختبِر الدالة من خلال الانتقال إلى عنوان URL المتاح للجميع. من المفترض أن تظهر لك النسخة البرتقالية في نصف الوقت، والنسخة الصفراء في النصف الآخر:
اطّلِع على عمليات التراجع والطرح التدريجي ونقل الزيارات لمزيد من المعلومات.
7. الحد الأدنى لعدد النُسخ
في دوالّ Cloud Run، يمكنك تحديد الحد الأدنى لعدد نُسخ الدوالّ التي يجب إبقاؤها جاهزة لعرض الطلبات. ويُعدّ ذلك مفيدًا في الحدّ من عدد عمليات التشغيل على البارد.
في هذه الخطوة، ستنشر دالة ذات عملية إعداد بطيئة. ستلاحظ مشكلة "التشغيل المجرّد". بعد ذلك، عليك نشر الدالة مع ضبط الحد الأدنى لقيمة المثيل على 1 للتخلص من وقت التشغيل على البارد.
إنشاء
أنشئ مجلدًا للتطبيق وانتقِل إليه:
mkdir ../min-instances cd ../min-instances
أنشئ ملفًا بتنسيق main.go
. تحتوي خدمة Go هذه على دالة init
تتوقف عن العمل لمدة 10 ثوانٍ لمحاكاة عملية إعداد طويلة. تتضمّن أيضًا دالة HelloWorld
تستجيب لطلبات HTTP:
package p import ( "fmt" "net/http" "time" ) func init() { time.Sleep(10 * time.Second) } func HelloWorld(w http.ResponseWriter, r *http.Request) { fmt.Fprint(w, "Slow HTTP Go in Cloud Run functions!") }
النشر
يمكنك نشر النسخة الأولى من الدالة باستخدام القيمة التلقائية للحد الأدنى لعدد المثيلات وهي صفر:
gcloud run deploy go-slow-function \ --source . \ --base-image go123 \ --function HelloWorld \ --region $REGION \ --no-allow-unauthenticated
اختبِر الدالة باستخدام هذا الأمر:
# get the Service URL SERVICE_URL="$(gcloud run services describe go-slow-function --region $REGION --format 'value(status.url)')" # invoke the service curl -H "Authorization: bearer $(gcloud auth print-identity-token)" -X GET $SERVICE_URL
ستلاحظ تأخيرًا لمدة 10 ثوانٍ (بدء التشغيل البارد) في المكالمة الأولى، ثم ستظهر الرسالة. من المفترض أن تظهر المكالمات اللاحقة على الفور.
ضبط الحد الأدنى لعدد النُسخ
للتخلص من بدء التشغيل البارد في الطلب الأول، أعِد نشر الدالة مع ضبط العلامة --min-instances
على 1 على النحو التالي:
gcloud run deploy go-slow-function \ --source . \ --base-image go123 \ --function HelloWorld \ --region $REGION \ --no-allow-unauthenticated \ --min-instances 1
الاختبار
اختبِر الدالة مرة أخرى:
curl -H "Authorization: bearer $(gcloud auth print-identity-token)" -X GET $SERVICE_URL
من المفترض ألا يظهر لك تأخّر 10 ثوانٍ بعد الآن في الطلب الأول. تم حلّ مشكلة "البدء البارد" في أول عملية استدعاء (بعد فترة طويلة بدونها) بفضل الحد الأدنى من النُسخ.
اطّلِع على استخدام الحد الأدنى من النُسخ للحصول على مزيد من المعلومات.
8. تهانينا!
تهانينا على إكمال دورة codelab.
المواضيع التي تناولناها
- نظرة عامة على دوالّ Cloud Run وكيفية استخدام التعديلات التلقائية للصورة الأساسية
- كيفية كتابة دالة تستجيب لطلبات HTTP
- كيفية كتابة دالة تستجيب لرسائل Pub/Sub
- كيفية كتابة دالة تستجيب لأحداث Cloud Storage
- كيفية تقسيم عدد الزيارات بين نسختَين
- كيفية التخلص من عمليات التشغيل على البارد باستخدام الحد الأدنى من النُسخ