1. Przegląd
W poprzednich ćwiczeniach utworzyliśmy wersję aplikacji Pic-a-daily opartą na zdarzeniach, która korzystała z funkcji Cloud Function wywoływanej przez Google Cloud Storage na potrzeby usługi analizy obrazów, kontenera Cloud Run wywoływanego przez GCS za pomocą Pub/Sub na potrzeby usługi miniatur oraz Eventarc do wywoływania usługi Image Garbage Collector w Cloud Run. Była też usługa Collage wywoływana przez Cloud Scheduler:

W tym module utworzysz zorkiestrowaną wersję aplikacji. Zamiast różnych typów zdarzeń przepływających przez system użyjesz przepływów pracy do orkiestracji i wywoływania usług w ten sposób:

Czego się nauczysz
- App Engine
- Cloud Firestore
- Cloud Functions
- Cloud Run
- Przepływy pracy
2. Konfiguracja i wymagania
Samodzielne konfigurowanie środowiska
- Zaloguj się w konsoli Google Cloud i utwórz nowy projekt lub użyj istniejącego. (Jeśli nie masz jeszcze konta Gmail lub Google Workspace, musisz je utworzyć).



Zapamiętaj identyfikator projektu, czyli unikalną nazwę we wszystkich projektach Google Cloud (podana powyżej nazwa jest już zajęta i nie będzie działać w Twoim przypadku). W dalszej części tego laboratorium będzie on nazywany PROJECT_ID.
- Następnie musisz włączyć rozliczenia w konsoli Cloud, aby korzystać z zasobów Google Cloud.
Ukończenie tego laboratorium nie powinno wiązać się z dużymi kosztami, a nawet z żadnymi. Wykonaj instrukcje z sekcji „Czyszczenie”, w której znajdziesz informacje o tym, jak wyłączyć zasoby, aby uniknąć naliczenia opłat po zakończeniu tego samouczka. Nowi użytkownicy Google Cloud mogą skorzystać z bezpłatnego okresu próbnego, w którym mają do dyspozycji środki w wysokości 300 USD.
Uruchamianie Cloud Shell
Z Google Cloud można korzystać zdalnie na laptopie, ale w tym module praktycznym będziesz używać Google Cloud Shell, czyli środowiska wiersza poleceń działającego w chmurze.
W konsoli GCP kliknij ikonę Cloud Shell na pasku narzędzi w prawym górnym rogu:

Uzyskanie dostępu do środowiska i połączenie się z nim powinno zająć tylko kilka chwil. Po zakończeniu powinno wyświetlić się coś takiego:

Ta maszyna wirtualna zawiera wszystkie potrzebne narzędzia dla programistów. Zawiera również stały katalog domowy o pojemności 5 GB i działa w Google Cloud, co znacznie zwiększa wydajność sieci i usprawnia proces uwierzytelniania. Wszystkie zadania w tym module możesz wykonać w przeglądarce.
3. Wprowadzenie do Workflows

Możesz używać Workflows do tworzenia bezserwerowych przepływów pracy, które łączą szereg bezserwerowych zadań w określonej przez Ciebie kolejności. Możesz wykorzystywać interfejsy API Google Cloud, usługi bezserwerowe takie jak Cloud Functions i Cloud Run oraz wywołania zewnętrznych interfejsów API, aby tworzyć elastyczne aplikacje bezserwerowe.
Zgodnie z oczekiwaniami od narzędzia do orkiestracji, przepływy pracy umożliwiają zdefiniowanie przepływu logiki biznesowej w języku definicji przepływu pracy opartym na YAML/JSON oraz udostępniają interfejs Workflows Execution API i interfejs przepływów pracy, które umożliwiają wywoływanie tych przepływów.
To nie tylko narzędzie do orkiestracji. Ma wbudowane i konfigurowalne funkcje:
- Elastyczne ponawianie i obsługa błędów między krokami zapewniają niezawodne wykonywanie kroków.
- Analiza JSON i przekazywanie zmiennych między krokami, aby uniknąć kodu łączącego.
- Formuły wyrażeń dotyczące decyzji umożliwiają warunkowe wykonywanie kroków.
- Podprzepływy pracy do modułowych i wielokrotnego użytku przepływów pracy.
- Obsługa usług zewnętrznych umożliwia koordynowanie usług spoza Google Cloud.
- Obsługa uwierzytelniania w usługach Google Cloud i usługach zewnętrznych w celu bezpiecznego wykonywania kroków.
- Łączniki do usług Google Cloud, takich jak Pub/Sub, Firestore, Tasks i Secret Manager, które ułatwiają integrację.
Workflows to w pełni zarządzany produkt bezserwerowy. Nie musisz konfigurować ani skalować serwerów, a płacisz tylko za to, z czego korzystasz.
4. Włącz interfejsy API
W tym module połączysz usługi Cloud Functions i Cloud Run z Workflows. Będziesz też używać App Engine, Cloud Build, Vision API i innych usług.
W Cloud Shell sprawdź, czy wszystkie niezbędne usługi są włączone:
gcloud services enable \ appengine.googleapis.com \ cloudbuild.googleapis.com \ cloudfunctions.googleapis.com \ compute.googleapis.com \ firestore.googleapis.com \ run.googleapis.com \ vision.googleapis.com \ workflows.googleapis.com \
Po pewnym czasie operacja powinna się zakończyć:
Operation "operations/acf.5c5ef4f6-f734-455d-b2f0-ee70b5a17322" finished successfully.
5. Pobierz kod
Jeśli nie masz jeszcze kodu z poprzednich modułów, pobierz go:
git clone https://github.com/GoogleCloudPlatform/serverless-photosharing-workshop
Będziesz mieć następującą strukturę folderów, która jest istotna w tym module:
frontend | workflows | ├── functions ├── |── trigger-workflow ├── |── vision-data-transform ├── services ├── |── collage ├── |── thumbnails ├── workflows.yaml
Są to odpowiednie foldery:
frontendzawiera frontend App Engine, który ponownie wykorzystamy z ćwiczenia 4.functionszawiera funkcje Cloud Functions utworzone na potrzeby procesu.serviceszawiera usługi Cloud Run zmodyfikowane na potrzeby przepływu pracy.workflows.yamlto plik definicji przepływu pracy.
6. Przeglądanie pliku YAML przepływów pracy
Plik workflows.yaml definiuje przepływ pracy w serii kroków. Przyjrzyjmy się temu, aby lepiej to zrozumieć.
Na początku procesu przekazywane są pewne parametry. Zostaną one przekazane przez 2 funkcje Cloud Functions, które aktywują przepływy pracy. Do tych funkcji wrócimy później, ale tak wygląda początek przepływu pracy:

W YAML-u możesz zobaczyć, że te parametry są przypisane do zmiennych w kroku init, takich jak nazwy plików i zasobników wywołujących zdarzenie oraz adresy URL niektórych usług Cloud Functions i Cloud Run, które będą wywoływane przez Workflows:
main:
params: [args]
steps:
- init:
assign:
- file: ${args.file}
- bucket: ${args.bucket}
- gsUri: ${"gs://" + bucket + "/" + file}
- projectId: ${sys.get_env("GOOGLE_CLOUD_PROJECT_ID")}
- urls: ${args.urls}
Następnie przepływy pracy sprawdzają typ zdarzenia. Obsługiwane są 2 typy zdarzeń: object.finalize (emitowane, gdy plik jest zapisywany w zasobniku Cloud Storage) i object.delete (emitowane, gdy plik jest usuwany). W innych przypadkach zostanie zgłoszony wyjątek „event not supported” (wydarzenie nie jest obsługiwane).

Oto krok w definicji przepływu pracy YAML, w którym sprawdzamy typ zdarzenia związanego z przechowywaniem plików:
- eventTypeSwitch:
switch:
- condition: ${args.eventType == "google.storage.object.finalize"}
next: imageAnalysisCall
- condition: ${args.eventType == "google.storage.object.delete"}
next: pictureGarbageCollectionGCS
- eventTypeNotSupported:
raise: ${"eventType " + args.eventType + " is not supported"}
next: end
Zwróć uwagę, jak przepływy pracy obsługują instrukcje switch i obsługę wyjątków, w tym instrukcję switch i jej różne warunki oraz instrukcję raise, która zgłasza błąd, gdy zdarzenie nie jest rozpoznawane.
Teraz przyjrzyjmy się imageAnalysisCall. Jest to seria wywołań z Workflows, które wywołują interfejs Vision API w celu analizy obrazu, przekształcenia danych odpowiedzi interfejsu Vision API w celu posortowania etykiet rozpoznanych obiektów, wybrania dominujących kolorów, sprawdzenia, czy obraz jest bezpieczny do wyświetlenia, a następnie zapisania metadanych w Cloud Firestore.
Pamiętaj, że wszystko odbywa się w przepływach pracy z wyjątkiem funkcji Cloud Functions Vision Transform (którą wdrożymy później):

Tak wyglądają kroki w YAML:
- imageAnalysisCall:
call: http.post
args:
url: https://vision.googleapis.com/v1/images:annotate
headers:
Content-Type: application/json
auth:
type: OAuth2
body:
requests:
- image:
source:
gcsImageUri: ${gsUri}
features:
- type: LABEL_DETECTION
- type: SAFE_SEARCH_DETECTION
- type: IMAGE_PROPERTIES
result: imageAnalysisResponse
- transformImageAnalysisData:
call: http.post
args:
url: ${urls.VISION_DATA_TRANSFORM_URL}
auth:
type: OIDC
body: ${imageAnalysisResponse.body}
result: imageMetadata
- checkSafety:
switch:
- condition: ${imageMetadata.body.safe == true}
next: storeMetadata
next: end
- storeMetadata:
call: http.request
args:
url: ${"https://firestore.googleapis.com/v1/projects/" + projectId + "/databases/(default)/documents/pictures/" + file + "?updateMask.fieldPaths=color&updateMask.fieldPaths=labels&updateMask.fieldPaths=created"}
auth:
type: OAuth2
method: PATCH
body:
name: ${"projects/" + projectId + "/databases/(default)/documents/pictures/" + file}
fields:
color:
stringValue: ${imageMetadata.body.color}
created:
timestampValue: ${imageMetadata.body.created}
labels:
arrayValue:
values: ${imageMetadata.body.labels}
result: storeMetadataResponse
Po przeanalizowaniu obrazu kolejne 2 kroki to utworzenie miniatury obrazu i kolażu najnowszych zdjęć. W tym celu wdrażamy 2 usługi Cloud Run i wykonujemy do nich wywołania w krokach thumbnailCall i collageCall:

Kroki w YAML:
- thumbnailCall:
call: http.post
args:
url: ${urls.THUMBNAILS_URL}
auth:
type: OIDC
body:
gcsImageUri: ${gsUri}
result: thumbnailResponse
- collageCall:
call: http.get
args:
url: ${urls.COLLAGE_URL}
auth:
type: OIDC
result: collageResponse
Ten etap wykonania kończy się zwróceniem kodów stanu z każdej usługi w kroku finalizeCompleted:
- finalizeCompleted:
return:
imageAnalysis: ${imageAnalysisResponse.code}
storeMetadata: ${storeMetadataResponse.code}
thumbnail: ${thumbnailResponse.code}
collage: ${collageResponse.code}
Drugi przypadek wykonania to usunięcie pliku z głównego zasobnika pamięci, który zawiera wersje zdjęć w wysokiej rozdzielczości. W tej gałęzi chcemy usunąć miniaturę obrazu z zasobnika zawierającego miniatury i usunąć jej metadane z Firestore. Obie te czynności są wykonywane za pomocą wywołań HTTP z usługi Workflows:

Kroki w YAML:
- pictureGarbageCollectionGCS:
try:
call: http.request
args:
url: ${"https://storage.googleapis.com/storage/v1/b/thumbnails-" + projectId + "/o/" + file}
auth:
type: OAuth2
method: DELETE
result: gcsDeletionResult
except:
as: e
steps:
- dummyResultInOutVar:
assign:
- gcsDeletionResult:
code: 200
body: "Workaround for empty body response"
- pictureGarbageCollectionFirestore:
call: http.request
args:
url: ${"https://firestore.googleapis.com/v1/projects/" + projectId + "/databases/(default)/documents/pictures/" + file}
auth:
type: OAuth2
method: DELETE
result: firestoreDeletionResult
Usuwanie rozgałęzienia kończy się zwróceniem wyników lub kodów z każdego kroku:
- deleteCompleted:
return:
gcsDeletion: ${gcsDeletionResult}
firestoreDeletion: ${firestoreDeletionResult.code}
W kolejnych krokach utworzymy wszystkie zewnętrzne zależności przepływów pracy: zasobniki, funkcje Cloud Functions, usługi Cloud Run i bazę danych Firestore.
7. Tworzenie zasobników
Potrzebujesz 2 zasobników na obrazy: 1 do zapisywania oryginalnych obrazów w wysokiej rozdzielczości i 1 do zapisywania miniatur obrazów.
Utwórz publiczny zasobnik regionalny (w tym przypadku w Europie) z jednolitym dostępem dla użytkowników, aby mogli przesyłać do niego zdjęcia, korzystając z narzędzia gsutil:
export BUCKET_PICTURES=uploaded-pictures-${GOOGLE_CLOUD_PROJECT}
gsutil mb -l EU gs://${BUCKET_PICTURES}
gsutil uniformbucketlevelaccess set on gs://${BUCKET_PICTURES}
gsutil iam ch allUsers:objectViewer gs://${BUCKET_PICTURES}
Utwórz kolejny publiczny zasobnik regionalny na miniatury:
export BUCKET_THUMBNAILS=thumbnails-${GOOGLE_CLOUD_PROJECT}
gsutil mb -l EU gs://${BUCKET_THUMBNAILS}
gsutil uniformbucketlevelaccess set on gs://${BUCKET_THUMBNAILS}
gsutil iam ch allUsers:objectViewer gs://${BUCKET_THUMBNAILS}
Aby sprawdzić, czy zasobniki zostały utworzone i są publiczne, otwórz sekcję Cloud Storage w konsoli Cloud:

8. Przekształcanie danych Vision (funkcja w Cloud Functions)
Plik Workflows.yaml zaczyna się od kroków init, eventTypeSwitch, eventTypeNotSupported. Dzięki temu zdarzenia pochodzące z zasobników są kierowane do odpowiednich kroków.
W przypadku zdarzenia object.finalize krok imageAnalysisCall wywołuje interfejs Vision API, aby wyodrębnić metadane utworzonego obrazu. Wszystkie te czynności wykonuje się w sekcji Procesy:

Następnie musimy przekształcić dane zwrócone przez interfejs Vision API, zanim będziemy mogli zapisać je w Firestore. W szczególności musimy:
- Wyświetl listę etykiet zwróconych dla obrazu.
- Pobierz dominujący kolor obrazu.
- Sprawdź, czy obraz jest bezpieczny.
Odbywa się to w kodzie funkcji Cloud Function, a usługa Workflows po prostu wywołuje tę funkcję:

Poznaj kod
Funkcja w Cloud Functions jest wywoływana jako vision-data-transform. Pełny kod znajdziesz w pliku index.js. Jak widać, jedynym celem tej funkcji jest przekształcenie formatu JSON na JSON, aby wygodnie przechowywać metadane obrazu w Firestore.
Wdrażanie w Cloud Functions
Przejdź do folderu:
cd workflows/functions/vision-data-transform/nodejs
Ustaw wybrany region:
export REGION=europe-west1
gcloud config set functions/region ${REGION}
Wdróż funkcję za pomocą tego polecenia:
export SERVICE_NAME=vision-data-transform
gcloud functions deploy ${SERVICE_NAME} \
--source=. \
--runtime nodejs10 \
--entry-point=vision_data_transform \
--trigger-http \
--allow-unauthenticated
Po wdrożeniu funkcji krok transformImageAnalysisData w przepływach pracy będzie mógł wywoływać tę funkcję w celu przekształcania danych interfejsu Vision API.
9. Przygotowywanie bazy danych
Następnie w przepływach pracy sprawdzana jest bezpieczeństwo obrazu na podstawie danych obrazu, a potem informacje o zdjęciu zwrócone przez interfejs Vision API są zapisywane w bazie danych Cloud Firestore, czyli szybkiej, w pełni zarządzanej, bezserwerowej, chmurowej bazie danych dokumentów NoSQL:

Obie te czynności są wykonywane w usłudze Workflows, ale aby działały, musisz utworzyć bazę danych Firestore do przechowywania metadanych.
Najpierw utwórz aplikację App Engine w regionie, w którym chcesz mieć bazę danych Firestore (jest to wymagane w przypadku Firestore):
export REGION_FIRESTORE=europe-west2
gcloud app create --region=${REGION_FIRESTORE}
Następnie utwórz bazę danych Firestore w tym samym regionie:
gcloud firestore databases create --region=${REGION_FIRESTORE}
Dokumenty zostaną utworzone programowo w naszej kolekcji i będą zawierać 4 pola:
- name (string): nazwa pliku przesłanego zdjęcia, która jest też kluczem dokumentu.
- labels (tablica ciągów znaków): etykiety rozpoznanych elementów przez Vision API.
- color (string): szesnastkowy kod koloru dominującego (np. #ab12ef)
- created (data): sygnatura czasowa zapisania metadanych tego obrazu.
- thumbnail (wartość logiczna): pole opcjonalne, które będzie obecne i będzie miało wartość „true”, jeśli dla tego zdjęcia została wygenerowana miniatura.
Będziemy wyszukiwać w Firestore zdjęcia, dla których dostępne są miniatury, i sortować je według daty utworzenia, więc musimy utworzyć indeks wyszukiwania. Indeks możesz utworzyć za pomocą tego polecenia:
gcloud firestore indexes composite create --collection-group=pictures \ --field-config field-path=thumbnail,order=descending \ --field-config field-path=created,order=descending
Pamiętaj, że utworzenie indeksu może potrwać około 10 minut.
Po utworzeniu indeksu możesz go wyświetlić w konsoli Google Cloud:

Krok storeMetadata przepływów pracy będzie teraz mógł przechowywać metadane obrazu w Firestore.
10. Usługa miniatur (Cloud Run)
Kolejnym krokiem jest utworzenie miniatury obrazu. Odbywa się to w kodzie usługi Cloud Run, a Workflows wywołuje tę usługę w thumbnailCall kroku:

Poznaj kod
Usługa Cloud Run ma nazwę thumbnails. Pełny kod znajdziesz w pliku index.js.
Tworzenie i publikowanie obrazu kontenera
Cloud Run uruchamia kontenery, ale najpierw musisz utworzyć obraz kontenera (zdefiniowany w Dockerfile). Do tworzenia obrazów kontenerów i hostowania ich w Google Container Registry możesz użyć Google Cloud Build.
Przejdź do folderu:
cd workflows/services/thumbnails/nodejs
Kompilacja:
export SERVICE_SRC=thumbnails
export SERVICE_NAME=${SERVICE_SRC}-service
gcloud builds submit \
. \
--tag gcr.io/${GOOGLE_CLOUD_PROJECT}/${SERVICE_NAME}
Po minucie lub dwóch kompilacja powinna się powieść, a kontener zostanie wdrożony w Google Container Registry.
Wdróż w Cloud Run
Ustaw potrzebne zmienne i konfigurację:
export BUCKET_THUMBNAILS=thumbnails-${GOOGLE_CLOUD_PROJECT}
export REGION=europe-west1
gcloud config set run/region ${REGION}
gcloud config set run/platform managed
Wdróż za pomocą tego polecenia:
gcloud run deploy ${SERVICE_NAME} \
--image gcr.io/${GOOGLE_CLOUD_PROJECT}/${SERVICE_NAME} \
--no-allow-unauthenticated \
--memory=1Gi \
--update-env-vars BUCKET_THUMBNAILS=${BUCKET_THUMBNAILS}
Po wdrożeniu usługi krok thumbnailCall w przepływach pracy będzie mógł ją wywoływać.
11. Usługa kolażu (Cloud Run)
Kolejnym krokiem jest utworzenie kolażu z najnowszych zdjęć. Odbywa się to w kodzie usługi Cloud Run, a Workflows wywołuje tę usługę w collageCall kroku:

Poznaj kod
Usługa Cloud Run ma nazwę collage. Pełny kod znajdziesz w pliku index.js.
Tworzenie i publikowanie obrazu kontenera
Cloud Run uruchamia kontenery, ale najpierw musisz utworzyć obraz kontenera (zdefiniowany w Dockerfile). Do tworzenia obrazów kontenerów i hostowania ich w Google Container Registry możesz użyć Google Cloud Build.
Przejdź do folderu:
cd services/collage/nodejs
Kompilacja:
export SERVICE_SRC=collage
export SERVICE_NAME=${SERVICE_SRC}-service
gcloud builds submit \
. \
--tag gcr.io/${GOOGLE_CLOUD_PROJECT}/${SERVICE_NAME}
Po minucie lub dwóch kompilacja powinna się powieść, a kontener zostanie wdrożony w Google Container Registry.
Wdróż w Cloud Run
Ustaw potrzebne zmienne i konfigurację:
export BUCKET_THUMBNAILS=thumbnails-${GOOGLE_CLOUD_PROJECT}
export REGION=europe-west1
gcloud config set run/region ${REGION}
gcloud config set run/platform managed
Wdróż:
gcloud run deploy ${SERVICE_NAME} \
--image gcr.io/${GOOGLE_CLOUD_PROJECT}/${SERVICE_NAME} \
--no-allow-unauthenticated \
--memory=1Gi \
--update-env-vars BUCKET_THUMBNAILS=${BUCKET_THUMBNAILS}
Po wdrożeniu usługi możesz sprawdzić, czy obie usługi działają w sekcji Cloud Run w konsoli Google Cloud, a krok Workflows collageCall będzie mógł wywołać tę usługę:

12. Wdrażanie przepływów pracy
Wdrożyliśmy wszystkie zewnętrzne zależności przepływów pracy. Wszystkie pozostałe kroki (finalizeCompleted, pictureGarbageCollectionGCS, pictureGarbageCollectionFirestore, deleteCompleted) mogą zostać wykonane przez samą usługę Workflows.
Czas wdrożyć przepływy pracy.
Otwórz folder zawierający plik workflows.yaml i wdroż go za pomocą tego polecenia:
export WORKFLOW_REGION=europe-west4
export WORKFLOW_NAME=picadaily-workflows
gcloud workflows deploy ${WORKFLOW_NAME} \
--source=workflows.yaml \
--location=${WORKFLOW_REGION}
Po kilku sekundach przepływ pracy powinien zostać wdrożony i będzie widoczny w sekcji Przepływy pracy w Cloud Console:

Możesz kliknąć przepływ pracy i go edytować. Podczas edycji zobaczysz przejrzystą wizualizację przepływu pracy:

Możesz też ręcznie uruchomić przepływ pracy z konsoli Cloud, podając odpowiednie parametry. Zamiast tego w następnym kroku wykonamy ją automatycznie w odpowiedzi na zdarzenia Cloud Storage.
13. Aktywatory przepływów pracy (Cloud Functions)
Przepływ pracy jest wdrożony i gotowy. Teraz musimy uruchamiać przepływy pracy, gdy plik jest tworzony lub usuwany w zasobniku Cloud Storage. Są to odpowiednio zdarzenia storage.object.finalize i storage.object.delete.
Przepływy pracy mają interfejsy API i biblioteki klienta do tworzenia przepływów pracy, zarządzania nimi i ich wykonywania. W tym przypadku do wywołania przepływu pracy użyjesz interfejsu Workflows Execution API, a konkretnie jego biblioteki klienta Node.js.
Przepływy pracy będziesz aktywować za pomocą funkcji w Cloud Functions, która nasłuchuje zdarzeń Cloud Storage. Funkcja Cloud Functions może nasłuchiwać tylko jednego typu zdarzeń, więc aby nasłuchiwać zarówno zdarzeń tworzenia, jak i usuwania, musisz wdrożyć 2 funkcje Cloud Functions:

Poznaj kod
Funkcja w Cloud Functions jest wywoływana jako trigger-workflow. Pełny kod znajdziesz w pliku index.js.
Wdrażanie w Cloud Functions
Przejdź do folderu:
cd workflows/functions/trigger-workflow/nodejs
Ustaw potrzebne zmienne i konfigurację:
export BUCKET_PICTURES=uploaded-pictures-${GOOGLE_CLOUD_PROJECT}
export REGION=europe-west1
export WORKFLOW_NAME=picadaily-workflows
export WORKFLOW_REGION=europe-west4
export COLLAGE_URL=$(gcloud run services describe collage-service --format 'value(status.url)')
export THUMBNAILS_URL=$(gcloud run services describe thumbnails-service --format 'value(status.url)')
export VISION_DATA_TRANSFORM_URL=$(gcloud functions describe vision-data-transform --format 'value(httpsTrigger.url)')
gcloud config set functions/region ${REGION}
Wdróż funkcję odpowiadającą na zdarzenia finalizacji:
export SERVICE_NAME=trigger-workflow-on-finalize
gcloud functions deploy ${SERVICE_NAME} \
--source=. \
--runtime nodejs10 \
--entry-point=trigger_workflow \
--trigger-resource=${BUCKET_PICTURES} \
--trigger-event=google.storage.object.finalize \
--allow-unauthenticated \
--set-env-vars GOOGLE_CLOUD_PROJECT=${GOOGLE_CLOUD_PROJECT},WORKFLOW_REGION=${WORKFLOW_REGION},WORKFLOW_NAME=${WORKFLOW_NAME},THUMBNAILS_URL=${THUMBNAILS_URL},COLLAGE_URL=${COLLAGE_URL},VISION_DATA_TRANSFORM_URL=${VISION_DATA_TRANSFORM_URL}
Wdróż drugą funkcję, która reaguje na zdarzenia usuwania:
export SERVICE_NAME=trigger-workflow-on-delete
gcloud functions deploy ${SERVICE_NAME} \
--source=. \
--runtime nodejs10 \
--entry-point=trigger_workflow \
--trigger-resource=${BUCKET_PICTURES} \
--trigger-event=google.storage.object.delete \
--allow-unauthenticated \
--set-env-vars GOOGLE_CLOUD_PROJECT=${GOOGLE_CLOUD_PROJECT},WORKFLOW_REGION=${WORKFLOW_REGION},WORKFLOW_NAME=${WORKFLOW_NAME},THUMBNAILS_URL=${THUMBNAILS_URL},COLLAGE_URL=${COLLAGE_URL},VISION_DATA_TRANSFORM_URL=${VISION_DATA_TRANSFORM_URL}
Po wdrożeniu obie funkcje będą widoczne w konsoli Cloud:

14. Frontend (App Engine)
W tym kroku utworzysz interfejs internetowy w Google App Engine na podstawie modułu Pic-a-daily: Lab 4 – tworzenie interfejsu internetowego, który umożliwi użytkownikom przesyłanie zdjęć z aplikacji internetowej, a także przeglądanie przesłanych zdjęć i ich miniatur.

Więcej informacji o App Engine i opis kodu znajdziesz w artykule Pic-a-daily: Lab 4—Create a web frontend (Pic-a-daily: Laboratorium 4 – tworzenie interfejsu internetowego).
Poznaj kod
Aplikacja App Engine nazywa się frontend. Pełny kod znajdziesz w pliku index.js.
Wdrażanie w App Engine
Przejdź do folderu:
cd frontend
Ustaw wybrany region i zastąp GOOGLE_CLOUD_PROJECT w pliku app.yaml rzeczywistym identyfikatorem projektu:
export REGION=europe-west1
gcloud config set compute/region ${REGION}
sed -i -e "s/GOOGLE_CLOUD_PROJECT/${GOOGLE_CLOUD_PROJECT}/" app.yaml
Wdróż:
gcloud app deploy app.yaml -q
Po minucie lub dwóch zobaczysz komunikat informujący, że aplikacja obsługuje ruch:
Beginning deployment of service [default]... ╔════════════════════════════════════════════════════════════╗ ╠═ Uploading 8 files to Google Cloud Storage ═╣ ╚════════════════════════════════════════════════════════════╝ File upload done. Updating service [default]...done. Setting traffic split for service [default]...done. Deployed service [default] to [https://GOOGLE_CLOUD_PROJECT.appspot.com] You can stream logs from the command line by running: $ gcloud app logs tail -s default To view your application in the web browser run: $ gcloud app browse
Możesz też otworzyć sekcję App Engine w konsoli Cloud, aby sprawdzić, czy aplikacja została wdrożona, i zapoznać się z funkcjami App Engine, takimi jak obsługa wersji i podział ruchu:

15. Testowanie przepływów pracy
Aby przetestować aplikację, otwórz domyślny adres URL App Engine (https://<YOUR_PROJECT_ID>.appspot.com/) i sprawdź, czy interfejs użytkownika działa prawidłowo.

Prześlij zdjęcie. Powinno to uruchomić przepływy pracy. W konsoli Google Cloud możesz zobaczyć wykonanie przepływu pracy w stanie Active:

Po zakończeniu przepływu pracy możesz kliknąć identyfikator wykonania i zobaczyć dane wyjściowe z różnych usług:

Prześlij jeszcze 3 zdjęcia. Powinny też zostać zaktualizowane miniatura i kolaż obrazów w zasobnikach Cloud Storage i interfejsie App Engine:

16. Zwalnianie miejsca (opcjonalnie)
Jeśli nie zamierzasz zachować aplikacji, możesz usunąć zasoby, aby zaoszczędzić koszty i być dobrym użytkownikiem chmury. W tym celu usuń cały projekt:
gcloud projects delete ${GOOGLE_CLOUD_PROJECT}
17. Gratulacje!
Udało Ci się utworzyć wersję aplikacji z orkiestracją za pomocą Workflows, aby zarządzać usługami i je wywoływać.
Omówione zagadnienia
- App Engine
- Cloud Firestore
- Cloud Functions
- Cloud Run
- Przepływy pracy