1. Wprowadzenie

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.
Workflows nie wymaga zarządzania infrastrukturą i płynnie skaluje się na żądanie, również w dół do zera. W przypadku modelu płatności tylko za wykorzystanie zasoby płacisz jedynie za czas wykonywania.
Z tego ćwiczenia z programowania dowiesz się, jak łączyć różne usługi Google Cloud i zewnętrzne interfejsy HTTP API z Workflows. W szczególności połączysz w przepływ pracy 2 publiczne usługi Cloud Functions, 1 prywatną usługę Cloud Run i zewnętrzny publiczny interfejs HTTP API.
Czego się nauczysz
- Podstawowe informacje o usłudze Workflows.
- Jak połączyć publiczne funkcje Cloud Functions z przepływami pracy.
- Jak łączyć prywatne usługi Cloud Run z Workflow.
- Jak łączyć zewnętrzne interfejsy API HTTP z usługą Workflows.
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 G Suite, 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 programu 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. Omówienie przepływów pracy
Podstawowe informacje
Przepływ pracy składa się z serii kroków opisanych za pomocą składni przepływów pracy opartej na YAML. To definicja przepływu pracy. Szczegółowe wyjaśnienie składni YAML przepływów pracy znajdziesz na stronie Dokumentacja składni.
Po utworzeniu przepływu pracy jest on wdrażany, co oznacza, że jest gotowy do wykonania. Wykonanie to jednorazowe uruchomienie logiki zawartej w definicji przepływu pracy. Wszystkie wykonania przepływu pracy są niezależne, a usługa obsługuje dużą liczbę jednoczesnych wykonań.
Włączanie usług
W tym laboratorium dowiesz się, jak połączyć funkcje Cloud Functions i usługi Cloud Run z przepływami pracy. Podczas tworzenia usług będziesz też korzystać z Cloud Build i Cloud Storage.
Włącz wszystkie niezbędne usługi:
gcloud services enable \ cloudfunctions.googleapis.com \ run.googleapis.com \ workflows.googleapis.com \ cloudbuild.googleapis.com \ storage.googleapis.com
W następnym kroku połączysz 2 funkcje Cloud Functions w przepływ pracy.
4. Wdrażanie pierwszej funkcji w Cloud Functions
Pierwsza funkcja to generator liczb losowych w Pythonie.
Utwórz katalog dla kodu funkcji i przejdź do niego:
mkdir ~/randomgen cd ~/randomgen
Utwórz w katalogu plik main.py z podaną niżej treścią:
import random, json
from flask import jsonify
def randomgen(request):
randomNum = random.randint(1,100)
output = {"random":randomNum}
return jsonify(output)
Gdy ta funkcja otrzyma żądanie HTTP, wygeneruje losową liczbę z zakresu od 1 do 100 i zwróci ją w formacie JSON do wywołującego.
Funkcja korzysta z biblioteki Flask do przetwarzania HTTP, więc musimy dodać ją jako zależność. Zależności w Pythonie są zarządzane za pomocą narzędzia pip i wyrażane w pliku metadanych o nazwie requirements.txt.
Utwórz w tym samym katalogu plik requirements.txt z następującą treścią:
flask>=1.0.2
Wdróż funkcję za pomocą aktywatora HTTP i zezwól na nieuwierzytelnione żądania za pomocą tego polecenia:
gcloud functions deploy randomgen \
--runtime python312 \
--trigger-http \
--allow-unauthenticated
Po wdrożeniu funkcji jej adres URL możesz zobaczyć we właściwości url wyświetlanej w konsoli lub za pomocą polecenia gcloud functions describe.
Możesz też otworzyć adres URL funkcji za pomocą tego polecenia curl:
curl $(gcloud functions describe randomgen --format='value(url)')
Funkcja jest gotowa do użycia w przepływie pracy.
5. Wdrażanie drugiej funkcji w Cloud Functions
Druga funkcja to mnożnik. Mnoży otrzymane dane wejściowe przez 2.
Utwórz katalog dla kodu funkcji i przejdź do niego:
mkdir ~/multiply cd ~/multiply
Utwórz w katalogu plik main.py z podaną niżej treścią:
import random, json
from flask import jsonify
def multiply(request):
request_json = request.get_json()
output = {"multiplied":2*request_json['input']}
return jsonify(output)
Gdy ta funkcja otrzyma żądanie HTTP, wyodrębnia wartość input z treści JSON, mnoży ją przez 2 i zwraca w formacie JSON do wywołującego.
Utwórz w tym samym katalogu ten sam plik requirements.txt z następującą treścią:
flask>=1.0.2
Wdróż funkcję za pomocą aktywatora HTTP i zezwól na nieuwierzytelnione żądania za pomocą tego polecenia:
gcloud functions deploy multiply \
--runtime python312 \
--trigger-http \
--allow-unauthenticated
Po wdrożeniu funkcji możesz też otworzyć jej adres URL za pomocą tego polecenia curl:
curl $(gcloud functions describe multiply --format='value(url)') \
-X POST \
-H "content-type: application/json" \
-d '{"input": 5}'
Funkcja jest gotowa do użycia w przepływie pracy.
6. Łączenie 2 funkcji w Cloud Functions
W pierwszej procedurze połącz ze sobą obie funkcje.
Utwórz plik workflow.yaml z podaną niżej treścią.
- randomgenFunction:
call: http.get
args:
url: https://<region>-<project-id>.cloudfunctions.net/randomgen
result: randomgenResult
- multiplyFunction:
call: http.post
args:
url: https://<region>-<project-id>.cloudfunctions.net/multiply
body:
input: ${randomgenResult.body.random}
result: multiplyResult
- returnResult:
return: ${multiplyResult}
W tym przepływie pracy pierwsza funkcja generuje losową liczbę, która jest przekazywana do drugiej funkcji. Wynikiem jest pomnożona liczba losowa.
Wdróż pierwszy przepływ pracy:
gcloud workflows deploy workflow --source=workflow.yaml
Wykonaj pierwszy przepływ pracy:
gcloud workflows execute workflow
Po wykonaniu przepływu pracy możesz zobaczyć wynik, podając identyfikator wykonania z poprzedniego kroku:
gcloud workflows executions describe <your-execution-id> --workflow workflow
Dane wyjściowe będą zawierać result i state:
result: '{"body":{"multiplied":108},"code":200 ... }
...
state: SUCCEEDED
7. Łączenie zewnętrznego interfejsu API HTTP
Następnie połącz math.js jako usługę zewnętrzną w przepływie pracy.
W math.js możesz obliczać wyrażenia matematyczne w ten sposób:
curl https://api.mathjs.org/v4/?'expr=log(56)'
Tym razem użyjesz Cloud Console, aby zaktualizować przepływ pracy. Znajdź Workflows w konsoli Google Cloud:

Znajdź swój przepływ pracy i kliknij kartę Definition:

Edytuj definicję przepływu pracy i dodaj wywołanie funkcji math.js.
- randomgenFunction:
call: http.get
args:
url: https://<region>-<project-id>.cloudfunctions.net/randomgen
result: randomgenResult
- multiplyFunction:
call: http.post
args:
url: https://<region>-<project-id>.cloudfunctions.net/multiply
body:
input: ${randomgenResult.body.random}
result: multiplyResult
- logFunction:
call: http.get
args:
url: https://api.mathjs.org/v4/
query:
expr: ${"log(" + string(multiplyResult.body.multiplied) + ")"}
result: logResult
- returnResult:
return: ${logResult}
Przepływ pracy przekazuje teraz wynik funkcji mnożenia do wywołania funkcji logowania w math.js.
Interfejs użytkownika poprowadzi Cię przez proces edytowania i wdrażania przepływu pracy. Po wdrożeniu kliknij Execute, aby wykonać przepływ pracy. Wyświetlą się szczegóły wykonania:

Zwróć uwagę na kod stanu 200 i body z wynikiem funkcji logowania.
Właśnie udało Ci się zintegrować zewnętrzną usługę z naszym przepływem pracy. Świetnie!
8. Wdrażanie usługi Cloud Run
W ostatniej części zakończ przepływ pracy wywołaniem prywatnej usługi Cloud Run. Oznacza to, że przepływ pracy musi być uwierzytelniony, aby wywoływać usługę Cloud Run.
Usługa Cloud Run zwraca math.floor przekazanej liczby.
Utwórz katalog kodu usługi i przejdź do niego:
mkdir ~/floor cd ~/floor
Utwórz w katalogu plik app.py z podaną niżej treścią:
import json
import logging
import os
import math
from flask import Flask, request
app = Flask(__name__)
@app.route('/', methods=['POST'])
def handle_post():
content = json.loads(request.data)
input = float(content['input'])
return f"{math.floor(input)}", 200
if __name__ != '__main__':
# Redirect Flask logs to Gunicorn logs
gunicorn_logger = logging.getLogger('gunicorn.error')
app.logger.handlers = gunicorn_logger.handlers
app.logger.setLevel(gunicorn_logger.level)
app.logger.info('Service started...')
else:
app.run(debug=True, host='0.0.0.0', port=int(os.environ.get('PORT', 8080)))
Cloud Run wdraża kontenery, więc potrzebujesz Dockerfile, a kontener musi być powiązany ze zmiennymi środowiskowymi 0.0.0.0 i PORT, dlatego powyższy kod jest wymagany.
Gdy ta funkcja otrzyma żądanie HTTP, wyodrębni z treści JSON wartość input, wywoła funkcję math.floor i zwróci wynik do wywołującego.
W tym samym katalogu utwórz te pliki Dockerfile:
# Use an official lightweight Python image. # https://hub.docker.com/_/python FROM python:3.7-slim # Install production dependencies. RUN pip install Flask gunicorn # Copy local code to the container image. WORKDIR /app COPY . . # Run the web service on container startup. Here we use the gunicorn # webserver, with one worker process and 8 threads. # For environments with multiple CPU cores, increase the number of workers # to be equal to the cores available. CMD exec gunicorn --bind 0.0.0.0:8080 --workers 1 --threads 8 app:app
Utwórz kontener:
export SERVICE_NAME=floor
gcloud builds submit --tag gcr.io/${GOOGLE_CLOUD_PROJECT}/${SERVICE_NAME}
Po utworzeniu kontenera wdróż go w Cloud Run. Zwróć uwagę na flagę no-allow-unauthenticated. Dzięki temu usługa będzie akceptować tylko uwierzytelnione wywołania:
gcloud run deploy ${SERVICE_NAME} \
--image gcr.io/${GOOGLE_CLOUD_PROJECT}/${SERVICE_NAME} \
--platform managed \
--no-allow-unauthenticated
Po wdrożeniu usługa jest gotowa do użycia w przepływie pracy.
9. Łączenie usługi Cloud Run
Zanim skonfigurujesz przepływy pracy do wywoływania prywatnej usługi Cloud Run, musisz utworzyć konto usługi, które będą one używać:
export SERVICE_ACCOUNT=workflows-sa
gcloud iam service-accounts create ${SERVICE_ACCOUNT}
Przypisz do konta usługi rolę run.invoker. Umożliwi to kontu usługi wywoływanie uwierzytelnionych usług Cloud Run:
gcloud projects add-iam-policy-binding ${GOOGLE_CLOUD_PROJECT} \
--member "serviceAccount:${SERVICE_ACCOUNT}@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com" \
--role "roles/run.invoker"
Zaktualizuj definicję przepływu pracy w workflow.yaml, aby uwzględnić usługę Cloud Run. Zwróć uwagę, że uwzględniasz też pole auth, aby mieć pewność, że Workflows przekazuje token uwierzytelniania w wywołaniach usługi Cloud Run:
- randomgenFunction:
call: http.get
args:
url: https://<region>-<project-id>.cloudfunctions.net/randomgen
result: randomgenResult
- multiplyFunction:
call: http.post
args:
url: https://<region>-<project-id>.cloudfunctions.net/multiply
body:
input: ${randomgenResult.body.random}
result: multiplyResult
- logFunction:
call: http.get
args:
url: https://api.mathjs.org/v4/
query:
expr: ${"log(" + string(multiplyResult.body.multiplied) + ")"}
result: logResult
- floorFunction:
call: http.post
args:
url: https://floor-<random-hash>.run.app
auth:
type: OIDC
body:
input: ${logResult.body}
result: floorResult
- returnResult:
return: ${floorResult}
Zaktualizuj przepływ pracy. Ten czas przekazywany na koncie usługi:
gcloud workflows deploy workflow \
--source=workflow.yaml \
--service-account=${SERVICE_ACCOUNT}@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com
Wykonaj przepływ pracy:
gcloud workflows execute workflow
Po kilku sekundach możesz sprawdzić wykonanie przepływu pracy, aby zobaczyć wynik:
gcloud workflows executions describe <your-execution-id> --workflow workflow
Dane wyjściowe będą zawierać liczby całkowite result i state:
result: '{"body":"5","code":200 ... }
...
state: SUCCEEDED
10. Gratulacje!
Gratulujemy ukończenia ćwiczenia.
Omówione zagadnienia
- Podstawowe informacje o usłudze Workflows.
- Jak połączyć publiczne funkcje Cloud Functions z przepływami pracy.
- Jak łączyć prywatne usługi Cloud Run z Workflow.
- Jak łączyć zewnętrzne interfejsy API HTTP z usługą Workflows.