Pic-a-daily: Лабораторная работа 3. Создайте коллаж из последних фотографий.
О практической работе
1. Обзор
В этой лаборатории кода вы создадите новую службу Cloud Run, службу коллажей, которая будет запускаться Cloud Scheduler через регулярные промежутки времени. Сервис извлекает последние загруженные изображения и создает коллаж из этих изображений: он находит список последних изображений в Cloud Firestore, а затем загружает сами файлы изображений из Cloud Storage.
Что вы узнаете
- Облачный бег
- Облачный планировщик
- Облачное хранилище
- Облачный пожарный магазин
2. Настройка и требования
Самостоятельная настройка среды
- Войдите в Google Cloud Console и создайте новый проект или повторно используйте существующий. Если у вас еще нет учетной записи Gmail или Google Workspace, вам необходимо ее создать .
- Имя проекта — это отображаемое имя для участников этого проекта. Это строка символов, не используемая API Google, и вы можете обновить ее в любое время.
- Идентификатор проекта должен быть уникальным для всех проектов Google Cloud и неизменяемым (нельзя изменить после его установки). Cloud Console автоматически генерирует уникальную строку; обычно тебя не волнует, что это такое. В большинстве лабораторий кода вам потребуется указать идентификатор проекта (обычно он обозначается как
PROJECT_ID
), поэтому, если он вам не нравится, создайте другой случайный идентификатор или попробуйте свой собственный и посмотрите, доступен ли он. Затем он «замораживается» после создания проекта. - Существует третье значение — номер проекта , который используют некоторые API. Подробнее обо всех трех этих значениях читайте в документации .
- Затем вам необходимо включить выставление счетов в Cloud Console, чтобы использовать облачные ресурсы/API. Прохождение этой лаборатории кода не должно стоить много, если вообще стоит. Чтобы отключить ресурсы и не платить за выставление счетов за пределами этого руководства, следуйте инструкциям по «очистке», которые можно найти в конце лаборатории кода. Новые пользователи Google Cloud имеют право на участие в программе бесплатной пробной версии стоимостью 300 долларов США .
Запустить Cloud Shell
Хотя Google Cloud можно управлять удаленно с вашего ноутбука, в этой лаборатории вы будете использовать Google Cloud Shell , среду командной строки, работающую в облаке.
В консоли GCP щелкните значок Cloud Shell на верхней правой панели инструментов:
Подготовка и подключение к среде займет всего несколько минут. Когда все будет готово, вы должны увидеть что-то вроде этого:
Эта виртуальная машина оснащена всеми необходимыми инструментами разработки. Он предлагает постоянный домашний каталог объемом 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:
9. Протестируйте сервис
Чтобы проверить, работает ли настройка, проверьте в области thumbnails
изображение коллажа (называемое collage.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 вызывается и может объединять изображения для создания итогового изображения.
Что мы рассмотрели
- Облачный бег
- Облачный планировщик
- Облачное хранилище
- Облачный пожарный магазин