दैनिक आधार पर चित्र बनाना: लैब 3—सबसे हाल की तस्वीरों का कोलाज बनाएं

1. खास जानकारी

इस कोडलैब में, आपको एक नई Cloud Run सेवा बनानी है. यह कोलाज सेवा, Cloud Scheduler से नियमित अंतराल पर ट्रिगर होगी. यह सेवा, अपलोड की गई नई फ़ोटो को फ़ेच करती है और उनसे एक कोलाज बनाती है: यह Cloud Firestore में हाल ही की फ़ोटो की सूची ढूंढती है. इसके बाद, Cloud Storage से फ़ोटो की फ़ाइलें डाउनलोड करती है.

df20f5d0402b54b4.png

आपको क्या सीखने को मिलेगा

  • Cloud Run
  • Cloud Scheduler
  • Cloud Storage
  • Cloud Firestore

2. सेटअप और ज़रूरी शर्तें

अपने हिसाब से एनवायरमेंट सेट अप करना

  1. Google Cloud Console में साइन इन करें और नया प्रोजेक्ट बनाएं या किसी मौजूदा प्रोजेक्ट का फिर से इस्तेमाल करें. अगर आपके पास पहले से कोई Gmail या Google Workspace खाता नहीं है, तो आपको एक खाता बनाना होगा.

96a9c957bc475304.png

b9a10ebdf5b5a448.png

a1e3c01a38fa61c2.png

  • प्रोजेक्ट का नाम, इस प्रोजेक्ट में हिस्सा लेने वाले लोगों के लिए डिसप्ले नेम होता है. यह एक कैरेक्टर स्ट्रिंग है, जिसका इस्तेमाल Google API नहीं करते. इसे किसी भी समय अपडेट किया जा सकता है.
  • प्रोजेक्ट आईडी, सभी Google Cloud प्रोजेक्ट के लिए यूनीक होना चाहिए. साथ ही, इसे बदला नहीं जा सकता. Cloud Console, एक यूनीक स्ट्रिंग अपने-आप जनरेट करता है. आम तौर पर, आपको इससे कोई फ़र्क़ नहीं पड़ता कि यह क्या है. ज़्यादातर कोडलैब में, आपको प्रोजेक्ट आईडी का रेफ़रंस देना होगा. इसे आम तौर पर PROJECT_ID के तौर पर पहचाना जाता है. इसलिए, अगर आपको यह पसंद नहीं है, तो कोई दूसरा रैंडम आईडी जनरेट करें. इसके अलावा, अपने हिसाब से कोई आईडी बनाकर देखें कि वह उपलब्ध है या नहीं. इसके बाद, प्रोजेक्ट बनाने के बाद इसे "फ़्रीज़" कर दिया जाता है.
  • तीसरी वैल्यू, प्रोजेक्ट नंबर होती है. इसका इस्तेमाल कुछ एपीआई करते हैं. इन तीनों वैल्यू के बारे में ज़्यादा जानने के लिए, दस्तावेज़ देखें.
  1. इसके बाद, आपको Cloud Console में बिलिंग चालू करनी होगी, ताकि Cloud संसाधनों/एपीआई का इस्तेमाल किया जा सके. इस कोडलैब को पूरा करने में ज़्यादा खर्च नहीं आएगा. संसाधन बंद करने के लिए, कोडलैब के आखिर में दिए गए "बंद करें" निर्देशों का पालन करें, ताकि इस ट्यूटोरियल के बाद आपको बिलिंग न करनी पड़े. Google Cloud के नए उपयोगकर्ताओं को, मुफ़्त में आज़माने के लिए 300 डॉलर का क्रेडिट मिलता है.

Cloud Shell शुरू करें

Google Cloud को अपने लैपटॉप से रिमोटली ऐक्सेस किया जा सकता है. हालांकि, इस कोडलैब में Google Cloud Shell का इस्तेमाल किया जाएगा. यह क्लाउड में चलने वाला कमांड लाइन एनवायरमेंट है.

GCP Console में, सबसे ऊपर दाईं ओर मौजूद टूलबार पर मौजूद Cloud Shell आइकॉन पर क्लिक करें:

bce75f34b2c53987.png

इसे चालू करने और एनवायरमेंट से कनेक्ट करने में सिर्फ़ कुछ सेकंड लगेंगे. यह प्रोसेस पूरी होने के बाद, आपको कुछ ऐसा दिखेगा:

f6ef2b5f13479f3a.png

इस वर्चुअल मशीन में, डेवलपमेंट के लिए ज़रूरी सभी टूल पहले से मौजूद हैं. यह 5 जीबी की होम डायरेक्ट्री उपलब्ध कराता है. साथ ही, यह Google Cloud पर काम करता है. इससे नेटवर्क की परफ़ॉर्मेंस और पुष्टि करने की प्रोसेस बेहतर होती है. इस लैब में मौजूद सभी टास्क को सिर्फ़ ब्राउज़र की मदद से पूरा किया जा सकता है.

3. एपीआई चालू करें

आपको Cloud Run सेवा को नियमित अंतराल पर ट्रिगर करने के लिए, Cloud Scheduler की ज़रूरत होगी. पक्का करें कि यह सुविधा चालू हो:

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

फ़ोल्डर में, ये तीन फ़ाइलें हैं:

  • 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 / Node वेब फ़्रेमवर्क है. Bluebird का इस्तेमाल प्रॉमिस को मैनेज करने के लिए किया जाता है. वहीं, imagemagick एक लाइब्रेरी है, जिसका इस्तेमाल इमेज में बदलाव करने के लिए किया जाता है.

Dockerfile

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" ]

हम Node 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 वेब फ़्रेमवर्क है, जिसका हम इस्तेमाल करेंगे. ImageMagick, इमेज में बदलाव करने के लिए लाइब्रेरी है. Bluebird, JavaScript प्रॉमिस को मैनेज करने के लिए लाइब्रेरी है. Path का इस्तेमाल, फ़ाइलों और डायरेक्ट्री के पाथ को मैनेज करने के लिए किया जाता है. इसके बाद, Storage और 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);
    }
});

ऊपर, हमने अपने नोड हैंडलर का स्ट्रक्चर दिया है: हमारा ऐप्लिकेशन, एचटीटीपी 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 {

    /* ... */

}

कोलाज बनाने की हमारी सेवा के लिए, कम से कम चार ऐसी फ़ोटो की ज़रूरत होगी जिनके थंबनेल जनरेट किए जा चुके हैं. इसलिए, पक्का करें कि आपने पहले चार फ़ोटो अपलोड कर ली हों.

हम Cloud Firestore में सेव किए गए मेटाडेटा से, उपयोगकर्ताओं की ओर से अपलोड की गई चार नई तस्वीरें पाते हैं. हम यह देखते हैं कि नतीजा देने वाला कलेक्शन खाली है या नहीं. इसके बाद, हम अपने कोड की else ब्रांच में आगे बढ़ते हैं.

आइए, फ़ाइल के नामों की सूची इकट्ठा करें:

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 लाइब्रेरी का इस्तेमाल करके, उन थंबनेल की 4x4 ग्रिड बनाएंगे. हम Bluebird लाइब्रेरी और उसके Promise implementation का इस्तेमाल करके, कॉलबैक-ड्रिवन कोड को 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 स्क्रिप्ट को आने वाले अनुरोधों को सुनने के लिए तैयार करने का समय है:

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 पर भरोसा किया जा सकता है. 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 buildpacks अपने-आप उस भाषा का पता लगाता है जिसका इस्तेमाल किया जा रहा है. साथ ही, कोड की डिपेंडेंसी फ़ेच करता है, ताकि प्रोडक्शन के लिए तैयार कंटेनर इमेज बनाई जा सके. इसके लिए, Google की ओर से मैनेज की गई सुरक्षित बेस इमेज का इस्तेमाल किया जाता है. इससे Cloud Run को यह सूचना मिलती है कि Dockerfile में तय की गई कंटेनर इमेज बनाने के लिए, Google Cloud Buildpacks का इस्तेमाल किया जाए.

यह भी ध्यान दें कि सोर्स के आधार पर डिप्लॉयमेंट करने के लिए, Artifact Registry का इस्तेमाल किया जाता है. इससे बिल्ड किए गए कंटेनर सेव किए जाते हैं. Artifact Registry, Google Container Registry का नया वर्शन है. अगर प्रोजेक्ट में एपीआई पहले से चालू नहीं है, तो सीएलआई इसे चालू करने के लिए कहेगा. साथ ही, यह उस इलाके में cloud-run-source-deploy नाम की एक रिपॉज़िटरी बनाएगा जहां आपको डिप्लॉय करना है.

--no-allow-unauthenticated फ़्लैग, Cloud Run सेवा को एक इंटरनल सेवा बनाता है. इसे सिर्फ़ कुछ सेवा खाते ट्रिगर कर पाएंगे.

8. Cloud Scheduler सेट अप करना

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 Console में Cloud Scheduler सेक्शन पर जाकर देखा जा सकता है कि यह सेट अप है और Cloud Run सेवा के यूआरएल पर रीडायरेक्ट कर रहा है:

35119e28c1da53f3.png

9. सेवा को आज़माना

यह जांच करने के लिए कि सेटअप काम कर रहा है या नहीं, कोलाज इमेज (जिसे collage.png कहा जाता है) के लिए thumbnails बकेट में जाकर देखें. सेवा के लॉग भी देखे जा सकते हैं:

93922335a384be2e.png

10. डेटा साफ़ करना (ज़रूरी नहीं)

अगर आपको सीरीज़ में शामिल अन्य लैब का इस्तेमाल नहीं करना है, तो संसाधनों को बंद करें. इससे लागत कम करने में मदद मिलेगी. साथ ही, यह क्लाउड का इस्तेमाल करने का एक अच्छा तरीका है. यहां दिए गए तरीके से, संसाधनों को अलग-अलग करके हटाया जा सकता है.

सेवा मिटाएं:

gcloud run services delete $SERVICE_NAME -q

Cloud Scheduler जॉब मिटाने के लिए:

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 Storage
  • Cloud Firestore

अगले चरण