1. نظرة عامة
في هذا الدرس التطبيقي حول الترميز، يمكنك إنشاء خدمة Cloud Run، وهي خدمة مجمّعة جديدة سيتم تشغيلها بواسطة Cloud Scheduler على فترات زمنية منتظمة. تجلب الخدمة أحدث الصور التي تم تحميلها وتنشئ صورًا مجمّعة من تلك الصور: تعثر على قائمة الصور الحديثة في Cloud Firestore، ثم تنزِّل ملفات الصور الفعلية من Cloud Storage.
المُعطيات
- Cloud Run
- Cloud Scheduler
- تخزين في السحابة الإلكترونية
- Cloud Firestore
2. الإعداد والمتطلبات
إعداد بيئة ذاتية
- سجِّل الدخول إلى Google Cloud Console وأنشئ مشروعًا جديدًا أو أعِد استخدام مشروع حالي. إذا لم يكن لديك حساب على Gmail أو Google Workspace، عليك إنشاء حساب.
- اسم المشروع هو الاسم المعروض للمشاركين في هذا المشروع. وهي عبارة عن سلسلة أحرف لا تستخدمها Google APIs، ويمكنك تحديثها في أي وقت.
- يجب أن يكون رقم تعريف المشروع فريدًا في جميع مشاريع Google Cloud وغير قابل للتغيير (لا يمكن تغييره بعد ضبطه). تنشئ Cloud Console سلسلة فريدة تلقائيًا. فعادةً لا تهتم بما هو. في معظم الدروس التطبيقية حول الترميز، يجب الرجوع إلى رقم تعريف المشروع (والذي يتم تحديده عادةً على أنّه
PROJECT_ID
). لذلك، إذا لم يعجبك، يمكنك إنشاء رقم تعريف عشوائي آخر، أو يمكنك تجربة رقم تعريف المشروع الخاص بك ومعرفة ما إذا كان متاحًا. بعد أن يصبح "مجمّد" بعد إنشاء المشروع. - هناك قيمة ثالثة، وهي رقم المشروع الذي تستخدمه بعض واجهات برمجة التطبيقات. اطّلِع على مزيد من المعلومات حول هذه القيم الثلاث في المستندات.
- بعد ذلك، عليك تفعيل الفوترة في Cloud Console لاستخدام الموارد/واجهات برمجة التطبيقات في Cloud. إنّ تنفيذ هذا الدرس التطبيقي حول الترميز لن يكون مكلفًا أو مكلفًا على الإطلاق. لإيقاف تشغيل الموارد حتى لا تتحمل الفوترة بعد أكثر من هذا البرنامج التعليمي، اتبع أي عملية "تنظيف". التعليمات الموجودة في نهاية الدرس التطبيقي حول الترميز. يكون مستخدمو Google Cloud الجدد مؤهَّلون للانضمام إلى برنامج فترة تجريبية مجانية بقيمة 300 دولار أمريكي.
بدء Cloud Shell
مع أنّه يمكن إدارة Google Cloud عن بُعد من الكمبيوتر المحمول، ستستخدم في هذا الدرس التطبيقي Google Cloud Shell، وهي بيئة سطر أوامر يتم تشغيلها في السحابة الإلكترونية.
من وحدة تحكّم Google Cloud Platform، انقر على رمز Cloud Shell في شريط الأدوات العلوي الأيسر:
من المفترَض أن تستغرق عملية إدارة الحسابات والاتصال بالبيئة بضع لحظات فقط. عند الانتهاء، من المفترض أن يظهر لك شيء مثل هذا:
يتم تحميل هذه الآلة الافتراضية مزوّدة بكل أدوات التطوير التي ستحتاج إليها. وتوفّر هذه الشبكة دليلاً رئيسيًا دائمًا بسعة 5 غيغابايت وتعمل على Google Cloud، ما يحسّن بشكل كبير من أداء الشبكة والمصادقة. يمكنك تنفيذ كل أعمالك في هذا التمرين من خلال متصفح.
3- تفعيل واجهات برمجة التطبيقات
ستحتاج إلى "أداة جدولة المهام في السحابة الإلكترونية" لتشغيل خدمة "تشغيل في السحابة الإلكترونية" على فترات زمنية منتظمة. تأكّد من أنّه مفعَّل:
gcloud services enable cloudscheduler.googleapis.com
من المفترض أن يتم الانتهاء من العملية بنجاح:
Operation "operations/acf.5c5ef4f6-f734-455d-b2f0-ee70b5a17322" finished successfully.
4. استنساخ الرمز
استنسِخ الرمز إذا لم يسبق لك إجراء ذلك في التمرين المعملي السابق للرموز:
git clone https://github.com/GoogleCloudPlatform/serverless-photosharing-workshop
يمكنك بعد ذلك الانتقال إلى الدليل الذي يحتوي على الخدمة:
cd serverless-photosharing-workshop/services/collage/nodejs
وسيكون لديك تنسيق الملفات التالي للخدمة:
services | ├── collage | ├── nodejs | ├── Dockerfile ├── index.js ├── package.json
داخل المجلد، لديك 3 ملفات:
- يحتوي
index.js
على رمز Node.js. - يحدد
package.json
تبعيات المكتبة - تحدِّد السمة
Dockerfile
صورة الحاوية.
5- استكشاف الرمز البرمجي
التبعيات
يحدّد ملف package.json
ملحقات المكتبة المطلوبة:
{
"name": "collage_service",
"version": "0.0.1",
"main": "index.js",
"scripts": {
"start": "node index.js"
},
"dependencies": {
"bluebird": "^3.7.2",
"express": "^4.17.1",
"imagemagick": "^0.1.3",
"@google-cloud/firestore": "^4.9.9",
"@google-cloud/storage": "^5.8.3"
}
}
ونعتمد على مكتبة Cloud Storage لقراءة ملفات الصور وحفظها في Cloud Storage. أعلنّا عن اعتمادية على Cloud Firestore لاسترجاع البيانات الوصفية للصور التي خزّنناها سابقًا. Express هو إطار عمل ويب لـ JavaScript أو عُقدة. يتم استخدام Bluebird لمعالجة الوعود، أما Imagemagick فهو مكتبة لمعالجة الصور.
ملف شامل
تحدِّد السمة Dockerfile
صورة الحاوية للتطبيق:
FROM node:14-slim
# installing Imagemagick
RUN set -ex; \
apt-get -y update; \
apt-get -y install imagemagick; \
rm -rf /var/lib/apt/lists/*
WORKDIR /picadaily/services/collage
COPY package*.json ./
RUN npm install --production
COPY . .
CMD [ "npm", "start" ]
نستخدم صورة أساسية للعقدة 14 خفيفة. نحن بصدد تثبيت مكتبة imagemagick. ثم نثبّت وحدات NPM التي تحتاجها التعليمة البرمجية، ونشغل رمز العقدة مع npm start.
index.js
لنلقِ نظرة عن كثب على رمز index.js
:
const express = require('express');
const imageMagick = require('imagemagick');
const Promise = require("bluebird");
const path = require('path');
const {Storage} = require('@google-cloud/storage');
const Firestore = require('@google-cloud/firestore');
نحتاج إلى الاعتماديات المختلفة اللازمة لتشغيل برنامجنا: Express هو إطار عمل Node Web الذي سنستخدمه، وImageMagick مكتبة لإجراء معالجة الصور، وBluebird عبارة عن مكتبة للتعامل مع وعود JavaScript، واستخدام Path للتعامل مع الملفات والأدلة، في حين تُستخدم مساحة التخزين وFirestore على التوالي مع Google Cloud Storage (مجموعات الصور الخاصة بنا) ومخزن بيانات Cloud Firestore.
const app = express();
app.get('/', async (req, res) => {
try {
console.log('Collage request');
/* ... */
} catch (err) {
console.log(`Error: creating the collage: ${err}`);
console.error(err);
res.status(500).send(err);
}
});
أعلاه، لدينا بنية معالج العُقد: يستجيب تطبيقنا لطلبات HTTP GET. ونعالج بعض الأخطاء في حال حدوث أي خطأ. دعونا الآن نلقي نظرة على ما بداخل هذا الهيكل.
const thumbnailFiles = [];
const pictureStore = new Firestore().collection('pictures');
const snapshot = await pictureStore
.where('thumbnail', '==', true)
.orderBy('created', 'desc')
.limit(4).get();
if (snapshot.empty) {
console.log('Empty collection, no collage to make');
res.status(204).send("No collage created.");
} else {
/* ... */
}
ستحتاج خدمة الصور المجمَّعة إلى أربع صور على الأقل (تم إنشاء الصور المصغّرة الخاصة بها)، لذا احرص على تحميل 4 صور أولاً.
نسترد آخر 4 صور حمّلها المستخدمون، من البيانات الوصفية المخزنة في Cloud Firerstore. ونتحقّق مما إذا كانت المجموعة الناتجة فارغة أم لا، ثم ننتقل إلى الخطوة التالية في الفرع الآخر من رمزنا.
لنجمع قائمة بأسماء الملفات:
snapshot.forEach(doc => {
thumbnailFiles.push(doc.id);
});
console.log(`Picture file names: ${JSON.stringify(thumbnailFiles)}`);
سننزِّل كل ملف من هذه الملفات من حزمة الصور المصغّرة التي يأتي اسمها من متغيّر بيئة تم ضبطه في وقت النشر:
const thumbBucket = storage.bucket(process.env.BUCKET_THUMBNAILS);
await Promise.all(thumbnailFiles.map(async fileName => {
const filePath = path.resolve('/tmp', fileName);
await thumbBucket.file(fileName).download({
destination: filePath
});
}));
console.log('Downloaded all thumbnails');
بعد تحميل أحدث الصور المصغّرة، سنستخدم مكتبة ImageMagick لإنشاء شبكة بحجم 4×4 من هذه الصور المصغّرة. نستخدِم مكتبة Bluebird وتطبيق Promise لتحويل الرمز المستند إلى معاودة الاتصال إلى رمز متوافق مع async
/ await
، ثم ننتظر الوعد المتمثل في إنشاء صورة مجمّعة:
const collagePath = path.resolve('/tmp', 'collage.png');
const thumbnailPaths = thumbnailFiles.map(f => path.resolve('/tmp', f));
const convert = Promise.promisify(im.convert);
await convert([
'(', ...thumbnailPaths.slice(0, 2), '+append', ')',
'(', ...thumbnailPaths.slice(2), '+append', ')',
'-size', '400x400', 'xc:none', '-background', 'none', '-append',
collagePath]);
console.log("Created local collage picture");
نظرًا لأنه قد تم حفظ الصورة المجمَّعة على القرص محليًا في المجلد المؤقت، نحتاج الآن إلى تحميلها على Cloud Storage، ثم عرض استجابة ناجحة (رمز الحالة 2xx):
await thumbBucket.upload(collagePath);
console.log("Uploaded collage to Cloud Storage bucket ${process.env.BUCKET_THUMBNAILS}");
res.status(204).send("Collage created.");
حان الوقت الآن لجعل نص Node Script يستمع للطلبات الواردة:
const PORT = process.env.PORT || 8080;
app.listen(PORT, () => {
console.log(`Started collage service on port ${PORT}`);
});
وفي نهاية الملف المصدر، لدينا تعليمات لجعل Express يبدأ فعلاً تطبيق الويب على المنفذ الافتراضي 8080.
6- الاختبار محليًا
اختبِر الرمز البرمجي محليًا للتأكّد من عمله قبل نشره على السحابة الإلكترونية.
في المجلد collage/nodejs
، ثبِّت اعتماديات npm وابدأ تشغيل الخادم:
npm install; npm start
إذا سارت الأمور على ما يرام، من المفترض أن يبدأ تشغيل الخادم على المنفذ 8080:
Started collage service on port 8080
استخدِم CTRL-C
للخروج.
7. الإنشاء والنشر في Cloud Run
قبل النشر على Cloud Run، اضبط منطقة Cloud Run على إحدى المناطق والنظام الأساسي المتوافقَين على managed
:
gcloud config set run/region europe-west1 gcloud config set run/platform managed
يمكنك التحقّق من أنّه تم ضبط الإعدادات:
gcloud config list ... [run] platform = managed region = europe-west1
بدلاً من إنشاء صورة الحاوية ونشرها باستخدام Cloud Build يدويًا، يمكنك أيضًا الاعتماد على Cloud Run لإنشاء صورة الحاوية نيابةً عنك باستخدام Google Cloud Buildpacks.
شغِّل الأمر التالي لإنشاء صورة الحاوية:
BUCKET_THUMBNAILS=thumbnails-$GOOGLE_CLOUD_PROJECT SERVICE_NAME=collage-service gcloud run deploy $SERVICE_NAME \ --source . \ --no-allow-unauthenticated \ --update-env-vars BUCKET_THUMBNAILS=$BUCKET_THUMBNAILS
دوِّن العلامة –-source
. هذا هو النشر المستند إلى المصدر في Cloud Run. في حال توفّر Dockerfile
في دليل رموز المصدر، يتم إنشاء رمز المصدر الذي تم تحميله باستخدام Dockerfile
ذلك. في حال عدم توفّر Dockerfile
في دليل رموز المصدر، ترصد حِزمة الإصدار من Google Cloud تلقائيًا اللغة التي تستخدمها وتسترجع العناصر الاعتمادية للرمز لإنشاء صورة حاوية جاهزة للاستخدام، وذلك باستخدام صورة أساسية آمنة تديرها Google. يؤدي هذا إلى وضع علامة على Cloud Run لاستخدام Google Cloud Buildpacks لإنشاء صورة الحاوية المحدّدة في Dockerfile
.
يُرجى العلم أيضًا أنّ النشر المستند إلى المصدر يستخدم artifact Registry لتخزين الحاويات المُنشأة. Artifact Registry هو إصدار حديث من Google Container Registry. سيطلب واجهة سطر الأوامر تفعيل واجهة برمجة التطبيقات إذا لم تكن مفعَّلة في المشروع، وسينشئ مستودعًا بالاسم cloud-run-source-deploy
في المنطقة التي تنشر فيها.
تجعل العلامة --no-allow-unauthenticated
خدمة تشغيل السحابة الإلكترونية خدمة داخلية لا يتم تشغيلها إلا من خلال حسابات خدمة محدَّدة.
8. إعداد أداة جدولة المهام في السحابة الإلكترونية
الآن وبعد أن أصبحت خدمة Cloud Run جاهزة وتم نشرها، حان الوقت لإنشاء جدول زمني منتظم لاستدعاء الخدمة كل دقيقة.
إنشاء حساب خدمة:
SERVICE_ACCOUNT=collage-scheduler-sa gcloud iam service-accounts create $SERVICE_ACCOUNT \ --display-name "Collage Scheduler Service Account"
يمكنك منح إذن لحساب الخدمة لاستدعاء خدمة Cloud Run:
gcloud run services add-iam-policy-binding $SERVICE_NAME \ --member=serviceAccount:$SERVICE_ACCOUNT@$GOOGLE_CLOUD_PROJECT.iam.gserviceaccount.com \ --role=roles/run.invoker
إنشاء مهمة في Cloud Scheduler لتنفيذها كل دقيقة:
SERVICE_URL=$(gcloud run services describe $SERVICE_NAME --format 'value(status.url)') gcloud scheduler jobs create http $SERVICE_NAME-job --schedule "* * * * *" \ --http-method=GET \ --location=europe-west1 \ --uri=$SERVICE_URL \ --oidc-service-account-email=$SERVICE_ACCOUNT@$GOOGLE_CLOUD_PROJECT.iam.gserviceaccount.com \ --oidc-token-audience=$SERVICE_URL
يمكنك الانتقال إلى قسم Cloud Scheduler في Cloud Console لمعرفة أنه تم إعداده ويشير إلى عنوان URL لخدمة Cloud Run:
9. اختبار الخدمة
لاختبار عمل الإعداد، ابحث في حزمة thumbnails
عن الصورة المجمَّعة (التي تُعرف باسم collage.png
). يمكنك أيضًا التحقّق من سجلّات الخدمة من خلال اتّباع الخطوات التالية:
10. إخلاء مساحة تخزين (اختياري)
إذا كنت لا تريد مواصلة الدروس التطبيقية الأخرى ضمن هذه السلسلة، يمكنك إخلاء بعض الموارد من أجل توفير التكاليف والتحلّي بصفات المواطنين الصالحين في السحابة الإلكترونية بشكل عام. يمكنك تنظيف الموارد بشكل فردي على النحو التالي.
حذف الخدمة:
gcloud run services delete $SERVICE_NAME -q
حذف مهمة أداة جدولة المهام في السحابة الإلكترونية:
gcloud scheduler jobs delete $SERVICE_NAME-job -q
بدلاً من ذلك، يمكنك حذف المشروع بالكامل:
gcloud projects delete $GOOGLE_CLOUD_PROJECT
11. تهانينا!
تهانينا! لقد أنشأتَ خدمة مُجدوَلة: بفضل Cloud Scheduler، الذي ينقل رسالة كل دقيقة حول موضوع Pub/Sub، تم استدعاء خدمة الصورة المجمّعة في Cloud Run ويمكنها إلحاق الصور معًا لإنشاء الصورة الناتجة.
المواضيع التي تناولناها
- Cloud Run
- Cloud Scheduler
- تخزين في السحابة الإلكترونية
- Cloud Firestore