Pic-a-daily: Лабораторная работа 3. Создайте коллаж из самых последних фотографий.

Pic-a-daily:
Лабораторная работа 3. Создайте коллаж из последних фотографий.

О практической работе

subjectПоследнее обновление: янв. 31, 2023
account_circleАвторы: Guillaume Laforge, Mete Atamel

1. Обзор

В этой лаборатории кода вы создадите новую службу Cloud Run, службу коллажей, которая будет запускаться Cloud Scheduler через регулярные промежутки времени. Сервис извлекает последние загруженные изображения и создает коллаж из этих изображений: он находит список последних изображений в Cloud Firestore, а затем загружает сами файлы изображений из Cloud Storage.

df20f5d0402b54b4.png

Что вы узнаете

  • Облачный бег
  • Облачный планировщик
  • Облачное хранилище
  • Облачный пожарный магазин

2. Настройка и требования

Самостоятельная настройка среды

  1. Войдите в Google Cloud Console и создайте новый проект или повторно используйте существующий. Если у вас еще нет учетной записи Gmail или Google Workspace, вам необходимо ее создать .

96a9c957bc475304.png

b9a10ebdf5b5a448.png

a1e3c01a38fa61c2.png

  • Имя проекта — это отображаемое имя для участников этого проекта. Это строка символов, не используемая API Google, и вы можете обновить ее в любое время.
  • Идентификатор проекта должен быть уникальным для всех проектов Google Cloud и неизменяемым (нельзя изменить после его установки). Cloud Console автоматически генерирует уникальную строку; обычно тебя не волнует, что это такое. В большинстве лабораторий кода вам потребуется указать идентификатор проекта (обычно он обозначается как PROJECT_ID ), поэтому, если он вам не нравится, создайте другой случайный идентификатор или попробуйте свой собственный и посмотрите, доступен ли он. Затем он «замораживается» после создания проекта.
  • Существует третье значение — номер проекта , который используют некоторые API. Подробнее обо всех трех этих значениях читайте в документации .
  1. Затем вам необходимо включить выставление счетов в Cloud Console, чтобы использовать облачные ресурсы/API. Прохождение этой лаборатории кода не должно стоить много, если вообще стоит. Чтобы отключить ресурсы и не платить за выставление счетов за пределами этого руководства, следуйте инструкциям по «очистке», которые можно найти в конце лаборатории кода. Новые пользователи Google Cloud имеют право на участие в программе бесплатной пробной версии стоимостью 300 долларов США .

Запустить Cloud Shell

Хотя Google Cloud можно управлять удаленно с вашего ноутбука, в этой лаборатории вы будете использовать Google Cloud Shell , среду командной строки, работающую в облаке.

В консоли GCP щелкните значок Cloud Shell на верхней правой панели инструментов:

bce75f34b2c53987.png

Подготовка и подключение к среде займет всего несколько минут. Когда все будет готово, вы должны увидеть что-то вроде этого:

f6ef2b5f13479f3a.png

Эта виртуальная машина оснащена всеми необходимыми инструментами разработки. Он предлагает постоянный домашний каталог объемом 5 ГБ и работает в Google Cloud, что значительно повышает производительность сети и аутентификацию. Всю работу в этой лабораторной работе можно выполнять с помощью простого браузера.

3. Включить API

Вам понадобится облачный планировщик, чтобы регулярно запускать службу Cloud Run. Убедитесь, что он включен:

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/Node. 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" ]

Мы используем легкий базовый образ 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);
   
}
});

Выше у нас есть структура нашего обработчика Node: наше приложение отвечает на запросы 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. Мы проверяем, пуста ли полученная коллекция или нет, а затем продолжаем дальше в ветке 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, чтобы создать сетку 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-скрипт прослушивать входящие запросы:

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 .

Также обратите внимание, что развертывание на основе исходного кода использует реестр артефактов для хранения собранных контейнеров. Реестр артефактов — это современная версия Реестра контейнеров Google. CLI предложит включить API, если он еще не включен в проекте, и создаст репозиторий с именем cloud-run-source-deploy в регионе, в котором вы развертываете.

Флаг --no-allow-unauthenticated делает службу Cloud Run внутренней службой, которая будет запускаться только определенными учетными записями службы.

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

Создайте задание облачного планировщика, которое будет выполняться каждую минуту:

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:

35119e28c1da53f3.png

9. Протестируйте сервис

Чтобы проверить, работает ли настройка, проверьте в области thumbnails изображение коллажа (называемое collage.png ). Вы также можете проверить логи сервиса:

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 вызывается и может объединять изображения для создания итогового изображения.

Что мы рассмотрели

  • Облачный бег
  • Облачный планировщик
  • Облачное хранилище
  • Облачный пожарный магазин

Следующие шаги