Günlük resim: Laboratuvar 3: En yeni resimlerden bir kolaj oluşturun

1. Genel Bakış

Bu kod laboratuvarında, Cloud Scheduler tarafından düzenli aralıklarla tetiklenecek yeni bir Cloud Run hizmeti olan kolaj hizmeti oluşturacaksınız. Hizmet, yüklenen en son resimleri getirir ve bu resimlerden bir kolaj oluşturur: Cloud Firestore'da son resimlerin listesini bulur ve ardından gerçek resim dosyalarını Cloud Storage'dan indirir.

df20f5d0402b54b4.png

Neler öğreneceksiniz?

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

2. Kurulum ve Gereksinimler

Yönlendirmesiz ortam kurulumu

  1. Google Cloud Console'da oturum açın ve yeni bir proje oluşturun veya mevcut bir projeyi yeniden kullanın. Gmail veya Google Workspace hesabınız yoksa hesap oluşturmanız gerekir.

96a9c957bc475304.png

b9a10ebdf5b5a448.png

a1e3c01a38fa61c2.png

  • Proje adı, bu projenin katılımcıları için görünen addır. Google API'leri tarafından kullanılmayan bir karakter dizisidir ve istediğiniz zaman güncelleyebilirsiniz.
  • Proje kimliği, tüm Google Cloud projelerinde benzersiz olmalı ve sabittir (ayarlandıktan sonra değiştirilemez). Cloud Console, benzersiz bir dizeyi otomatik olarak oluşturur. Genellikle bu dizenin ne olduğuyla ilgilenmezsiniz. Çoğu codelab'de proje kimliğine (genellikle PROJECT_ID olarak tanımlanır) başvurmanız gerekir. Bu nedenle, beğenmezseniz başka bir rastgele kimlik oluşturabilir veya kendi kimliğinizi deneyip kullanılabilir olup olmadığını görebilirsiniz. Proje oluşturulduktan sonra bu değer "dondurulur".
  • Bazı API'lerin kullandığı üçüncü bir değer olan Proje Numarası da vardır. Bu üç değer hakkında daha fazla bilgiyi belgelerde bulabilirsiniz.
  1. Ardından, Cloud kaynaklarını/API'lerini kullanmak için Cloud Console'da faturalandırmayı etkinleştirmeniz gerekir. Bu codelab'i tamamlamak neredeyse hiç maliyetli değildir. Bu eğitimin ötesinde faturalandırma ücreti alınmaması için kaynakları kapatmak üzere codelab'in sonunda bulunan "temizleme" talimatlarını uygulayın. Google Cloud'un yeni kullanıcıları 300 ABD doları değerinde ücretsiz deneme programından yararlanabilir.

Cloud Shell'i başlatma

Google Cloud, dizüstü bilgisayarınızdan uzaktan çalıştırılabilir. Ancak bu codelab'de, Cloud'da çalışan bir komut satırı ortamı olan Google Cloud Shell'i kullanacaksınız.

GCP Console'da sağ üstteki araç çubuğunda Cloud Shell simgesini tıklayın:

bce75f34b2c53987.png

Ortamın temel hazırlığı ve bağlanması yalnızca birkaç dakikanızı alır. İşlem tamamlandığında aşağıdakine benzer bir sonuç görürsünüz:

f6ef2b5f13479f3a.png

Bu sanal makine, ihtiyaç duyacağınız tüm geliştirme araçlarını içerir. 5 GB boyutunda kalıcı bir ana dizin sunar ve Google Cloud üzerinde çalışır. Bu sayede ağ performansı ve kimlik doğrulama önemli ölçüde güçlenir. Bu laboratuvardaki çalışmalarınızın tamamını yalnızca bir tarayıcı kullanarak yapabilirsiniz.

3. API'leri etkinleştir

Cloud Run hizmetini düzenli aralıklarla tetiklemek için Cloud Scheduler'a ihtiyacınız vardır. Etkinleştirildiğinden emin olun:

gcloud services enable cloudscheduler.googleapis.com

İşlemin başarıyla tamamlandığını görmeniz gerekir:

Operation "operations/acf.5c5ef4f6-f734-455d-b2f0-ee70b5a17322" finished successfully.

4. Kodu klonlayın

Önceki kod laboratuvarında henüz yapmadıysanız kodu klonlayın:

git clone https://github.com/GoogleCloudPlatform/serverless-photosharing-workshop

Ardından, hizmeti içeren dizine gidebilirsiniz:

cd serverless-photosharing-workshop/services/collage/nodejs

Hizmet için aşağıdaki dosya düzenine sahip olursunuz:

services
 |
 ├── collage
      |
      ├── nodejs
           |
           ├── Dockerfile
           ├── index.js
           ├── package.json

Klasörde 3 dosya bulunur:

  • index.js, Node.js kodunu içerir.
  • package.json, kitaplık bağımlılıklarını tanımlar.
  • Dockerfile, container görüntüsünü tanımlar.

5. Kodu keşfetme

Bağımlılıklar

package.json dosyası, gerekli kitaplık bağımlılıklarını tanımlar:

{
  "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'daki resim dosyalarını okumak ve kaydetmek için Cloud Storage kitaplığını kullanırız. Daha önce depoladığımız resim meta verilerini getirmek için Cloud Firestore'a bağımlılık bildiriyoruz. Express, bir JavaScript / Node web çerçevesidir. Bluebird, sözleri işlemek için, imagemagick ise görüntüleri işlemek için kullanılan bir kitaplıktır.

Dockerfile

Dockerfile, uygulama için container görüntüsünü tanımlar:

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

Hafif bir Node 14 temel görüntüsü kullanıyoruz. Imagemagick kitaplığını yüklüyoruz. Ardından, kodumuzun ihtiyaç duyduğu NPM modüllerini yüklüyoruz ve npm start ile düğüm kodumuzu çalıştırıyoruz.

index.js

index.js kodumuzu daha yakından inceleyelim:

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');

Programımızın çalışması için gereken çeşitli bağımlılıklar vardır: Express, kullanacağımız Node web çerçevesi, ImageMagick görüntü işleme için kullanılan kitaplık, Bluebird JavaScript sözlerini işlemek için kullanılan kitaplık, Path dosyalar ve dizin yollarıyla ilgilenmek için kullanılır. Storage ve Firestore ise sırasıyla Google Cloud Storage (görüntü paketlerimiz) ve Cloud Firestore veri deposu ile çalışmak için kullanılır.

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);
    }
});

Yukarıda Node işleyicimizin yapısını görüyoruz: Uygulamamız HTTP GET isteklerine yanıt veriyor. Bir şeyler ters giderse diye hata işleme de yapıyoruz. Şimdi bu yapının içinde neler olduğuna bakalım.

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 {

    /* ... */

}

Kolaj hizmetimiz için en az dört resim (küçük resimleri oluşturulmuş) gerekir. Bu nedenle, önce 4 resim yüklediğinizden emin olun.

Kullanıcılarımız tarafından yüklenen en son 4 resmi, Cloud Firestore'da depolanan meta verilerden alıyoruz. Elde edilen koleksiyonun boş olup olmadığını kontrol ederiz ve ardından kodumuzun else dalında ilerleriz.

Dosya adlarının listesini oluşturalım:

snapshot.forEach(doc => {
    thumbnailFiles.push(doc.id);
});
console.log(`Picture file names: ${JSON.stringify(thumbnailFiles)}`);

Bu dosyaların her birini, dağıtım sırasında ayarladığımız bir ortam değişkeninden gelen ada sahip olan küçük resim paketinden indireceğiz:

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');

En son küçük resimler yüklendikten sonra, bu küçük resimlerden oluşan 4x4'lük bir ızgara oluşturmak için ImageMagick kitaplığını kullanacağız. Geri çağırma odaklı kodu async / await dostu koda dönüştürmek için Bluebird kitaplığını ve Promise uygulamasını kullanırız. Ardından, resim kolajı oluşturan Promise'in tamamlanmasını bekleriz:

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");

Kolaj resmi geçici klasörde yerel olarak diske kaydedildiğinden, şimdi bunu Cloud Storage'a yüklememiz ve ardından başarılı bir yanıt (durum kodu 2xx) döndürmemiz gerekiyor:

await thumbBucket.upload(collagePath);
console.log("Uploaded collage to Cloud Storage bucket ${process.env.BUCKET_THUMBNAILS}");

res.status(204).send("Collage created.");

Şimdi Node komut dosyamızın gelen istekleri dinlemesini sağlama zamanı:

const PORT = process.env.PORT || 8080;

app.listen(PORT, () => {
    console.log(`Started collage service on port ${PORT}`);
});

Kaynak dosyamızın sonunda, Express'in web uygulamamızı 8080 numaralı varsayılan bağlantı noktasında başlatması için talimatlar yer alıyor.

6. Yerel olarak test etme

Buluta dağıtmadan önce çalıştığından emin olmak için kodu yerel olarak test edin.

collage/nodejs klasöründe npm bağımlılıklarını yükleyin ve sunucuyu başlatın:

npm install; npm start

Her şey yolunda gittiyse sunucu 8080 numaralı bağlantı noktasında başlatılır:

Started collage service on port 8080

Çıkmak için CTRL-C öğesini kullanın.

7. Cloud Run'da derleme ve dağıtım

Cloud Run'a dağıtmadan önce Cloud Run bölgesini desteklenen bölgelerden biri olarak ve platformu managed olarak ayarlayın:

gcloud config set run/region europe-west1
gcloud config set run/platform managed

Yapılandırmanın ayarlandığını şu şekilde kontrol edebilirsiniz:

gcloud config list

...
[run]
platform = managed
region = europe-west1

Cloud Build'i kullanarak container görüntüsünü manuel olarak oluşturup yayınlamak yerine, Google Cloud Buildpacks'i kullanarak container görüntüsünü sizin için oluşturması konusunda Cloud Run'a da güvenebilirsiniz.

Kapsayıcı görüntüsünü oluşturmak için aşağıdaki komutu çalıştırın:

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 işaretine dikkat edin. Bu, Cloud Run'daki kaynak tabanlı dağıtımdır . Kaynak kodu dizininde Dockerfile varsa yüklenen kaynak kodu bu Dockerfile kullanılarak oluşturulur. Kaynak kodu dizininde Dockerfile yoksa Google Cloud buildpack'leri, kullandığınız dili otomatik olarak algılar ve Google tarafından yönetilen güvenli bir temel görüntü kullanarak üretime hazır bir kapsayıcı görüntüsü oluşturmak için kodun bağımlılıklarını getirir. Bu işaret, Cloud Run'ın Dockerfile içinde tanımlanan container görüntüsünü oluşturmak için Google Cloud Buildpack'lerini kullanmasını sağlar.

Kaynak tabanlı dağıtımın, oluşturulan kapsayıcıları depolamak için Artifact Registry'yi kullandığını da unutmayın. Artifact Registry, Google Container Registry'nin modern bir sürümüdür. KSA, API projede henüz etkinleştirilmemişse etkinleştirmenizi ister ve dağıtım yaptığınız bölgede cloud-run-source-deploy adlı bir depo oluşturur.

--no-allow-unauthenticated işareti, Cloud Run hizmetini yalnızca belirli hizmet hesapları tarafından tetiklenecek bir dahili hizmet haline getirir.

8. Cloud Scheduler'ı ayarlama

Cloud Run hizmeti hazır ve dağıtılmış durumda. Şimdi hizmeti her dakika çağırmak için düzenli bir plan oluşturma zamanı.

Hizmet hesabı oluşturun:

SERVICE_ACCOUNT=collage-scheduler-sa
gcloud iam service-accounts create $SERVICE_ACCOUNT \
   --display-name "Collage Scheduler Service Account"

Hizmet hesabına Cloud Run hizmetini çağırma izni verin:

gcloud run services add-iam-policy-binding $SERVICE_NAME \
   --member=serviceAccount:$SERVICE_ACCOUNT@$GOOGLE_CLOUD_PROJECT.iam.gserviceaccount.com \
   --role=roles/run.invoker

Her 1 dakikada bir yürütülecek bir Cloud Scheduler işi oluşturun:

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

Kurulduğunu ve Cloud Run hizmeti URL'sine yönlendirildiğini görmek için Cloud Console'daki Cloud Scheduler bölümüne gidebilirsiniz:

35119e28c1da53f3.png

9. Hizmeti test etme

Kurulumun çalışıp çalışmadığını test etmek için kolaj resminin (collage.png olarak adlandırılır) thumbnails paketinde olup olmadığını kontrol edin. Ayrıca hizmetin günlüklerini de kontrol edebilirsiniz:

93922335a384be2e.png

10. Temizleme (isteğe bağlı)

Serideki diğer laboratuvarlara devam etmeyi düşünmüyorsanız maliyetleri düşürmek ve genel olarak iyi bir bulut kullanıcısı olmak için kaynakları temizleyebilirsiniz. Kaynakları tek tek aşağıdaki şekilde temizleyebilirsiniz.

Hizmeti silme:

gcloud run services delete $SERVICE_NAME -q

Cloud Scheduler işini silin:

gcloud scheduler jobs delete $SERVICE_NAME-job -q

Alternatif olarak, projenin tamamını silebilirsiniz:

gcloud projects delete $GOOGLE_CLOUD_PROJECT

11. Tebrikler!

Tebrikler! Planlanmış bir hizmet oluşturdunuz: Cloud Scheduler, Pub/Sub konusuna her dakika bir mesaj gönderdiğinden Cloud Run kolaj hizmetiniz çağrılır ve resimleri birleştirerek sonuçtaki resmi oluşturabilir.

İşlediğimiz konular

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

Sonraki Adımlar