1. Wprowadzenie
Przepływy pracy umożliwiają tworzenie bezserwerowych przepływów pracy, które łączą serię bezserwerowych zadań w określonej przez Ciebie kolejności. Możesz połączyć możliwości interfejsów API Google Cloud, usług bezserwerowych, takich jak Cloud Functions i Cloud Run, oraz wywołań zewnętrznych interfejsów API, aby tworzyć elastyczne aplikacje bezserwerowe.
Przepływy pracy nie wymagają zarządzania infrastrukturą i sprawnie skalują się wraz z zapotrzebowaniem, w tym skalowanie do zera. W przypadku modelu płatności tylko za wykorzystanie zasoby płacisz jedynie za czas wykonywania.
Z tego ćwiczenia w Codelabs dowiesz się, jak łączyć różne usługi Google Cloud i zewnętrzne interfejsy API HTTP przy użyciu Workflows. Dokładniej rzecz ujmując, w przepływie pracy połączysz 2 publiczne usługi Cloud Functions – 1 prywatną usługę Cloud Run i zewnętrzny publiczny interfejs API HTTP.
Czego się nauczysz
- Podstawy Workflows.
- Jak połączyć publiczne funkcje w Cloud Functions z Workflows.
- Łączenie prywatnych usług Cloud Run z Workflows.
- Łączenie zewnętrznych interfejsów API HTTP z Workflows.
2. Konfiguracja i wymagania
Samodzielne konfigurowanie środowiska
- Zaloguj się w konsoli Google Cloud i utwórz nowy projekt lub wykorzystaj już istniejący. Jeśli nie masz jeszcze konta Gmail lub G Suite, musisz je utworzyć.
Zapamiętaj identyfikator projektu, unikalną nazwę we wszystkich projektach Google Cloud (powyższa nazwa jest już zajęta i nie będzie Ci odpowiadać). W dalszej części tego ćwiczenia w Codelabs będzie ona określana jako PROJECT_ID
.
- Następnie musisz włączyć płatności w Cloud Console, aby korzystać z zasobów Google Cloud.
Ukończenie tego ćwiczenia z programowania nie powinno kosztować zbyt wiele. Postępuj zgodnie z instrukcjami podanymi w sekcji „Czyszczenie” W tym samouczku znajdziesz wskazówki, jak wyłączyć zasoby, aby uniknąć naliczania opłat. Nowi użytkownicy Google Cloud mogą skorzystać z programu bezpłatnego okresu próbnego o wartości 300 USD.
Uruchamianie Cloud Shell
Google Cloud można obsługiwać zdalnie z laptopa, ale w ramach tego ćwiczenia z programowania wykorzystasz Google Cloud Shell – środowisko wiersza poleceń działające w chmurze.
W konsoli GCP kliknij ikonę Cloud Shell na górnym pasku narzędzi:
Uzyskanie dostępu do środowiska i połączenie się z nim powinno zająć tylko kilka chwil. Po zakończeniu powinno pojawić się coś takiego:
Ta maszyna wirtualna ma wszystkie potrzebne narzędzia dla programistów. Zawiera stały katalog domowy o pojemności 5 GB i działa w Google Cloud, znacząco zwiększając wydajność sieci i uwierzytelnianie. Wszystkie zadania w tym module możesz wykonać w przeglądarce.
3. Omówienie przepływów pracy
Podstawy
Przepływ pracy składa się z serii kroków opisanych za pomocą składni YAML Workflows. To jest definicja przepływu pracy. Szczegółowe omówienie składni YAML Workflows znajdziesz na stronie z informacjami o składni.
Podczas tworzenia przepływu pracy jest on wdrażany, dzięki czemu jest on 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 ćwiczeniu w Codelabs połączysz usługi Cloud Functions i Cloud Run z Workflows. Podczas tworzenia usług będziesz też używać 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 w Cloud Functions w ramach przepływu pracy.
4. Wdróż pierwszą funkcję w Cloud Functions
Pierwszą funkcją jest generator liczb losowych w Pythonie.
Utwórz katalog i przejdź do katalogu z kodem funkcji:
mkdir ~/randomgen cd ~/randomgen
Utwórz w katalogu plik main.py
o następującej treści:
import random, json from flask import jsonify def randomgen(request): randomNum = random.randint(1,100) output = {"random":randomNum} return jsonify(output)
Po otrzymaniu żądania HTTP ta funkcja generuje losową liczbę od 1 do 100 i zwraca w formacie JSON z powrotem do elementu wywołującego.
Funkcja ta korzysta z platformy Flask do przetwarzania HTTP i trzeba ją dodać jako zależność. Zależnościami w Pythonie zarządza się za pomocą pip i są wyrażane w pliku metadanych o nazwie requirements.txt
.
W tym samym katalogu utwórz plik requirements.txt
z tą zawartością:
flask>=1.0.2
Wdróż funkcję za pomocą aktywatora HTTP, przy czym żądania nieuwierzytelnione są dozwolone za pomocą tego polecenia:
gcloud functions deploy randomgen \ --runtime python37 \ --trigger-http \ --allow-unauthenticated
Po wdrożeniu funkcji adres URL funkcji we właściwości httpsTrigger.url
możesz zobaczyć 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(httpsTrigger.url)')
Funkcja jest gotowa do wykonania przepływu pracy.
5. Wdróż drugą funkcję w Cloud Functions
Druga funkcja jest mnożnikiem. Mnoży ona odebrane dane wejściowe przez 2.
Utwórz katalog i przejdź do katalogu z kodem funkcji:
mkdir ~/multiply cd ~/multiply
Utwórz w katalogu plik main.py
o następującej 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)
Po otrzymaniu żądania HTTP ta funkcja wyodrębnia input
z treści JSON, mnoży ją przez 2 i zwraca w formacie JSON z powrotem do elementu wywołującego.
W tym samym katalogu utwórz ten sam plik requirements.txt
z następującą zawartością:
flask>=1.0.2
Wdróż funkcję za pomocą aktywatora HTTP, przy czym żądania nieuwierzytelnione są dozwolone za pomocą tego polecenia:
gcloud functions deploy multiply \ --runtime python37 \ --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(httpsTrigger.url)') \ -X POST \ -H "content-type: application/json" \ -d '{"input": 5}'
Funkcja jest gotowa do wykonania przepływu pracy.
6. Połącz 2 funkcje w Cloud Functions
W pierwszym przepływie pracy połącz obie funkcje.
Utwórz plik workflow.yaml
o następującej zawartoś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 z pierwszej funkcji otrzymujesz liczbę losową i przekazujesz ją do drugiej. Wynik to 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, przekazując identyfikator wykonania podany w poprzednim kroku:
gcloud workflows executions describe <your-execution-id> --workflow workflow
Dane wyjściowe obejmują wartości result
i state
:
result: '{"body":{"multiplied":108},"code":200 ... } ... state: SUCCEEDED
7. Połącz zewnętrzny interfejs API HTTP
Następnie połącz w przepływie pracy math.js jako usługę zewnętrzną.
W pliku math.js możesz oceniać wyrażenia matematyczne w ten sposób:
curl https://api.mathjs.org/v4/?'expr=log(56)'
Tym razem do aktualizacji przepływu pracy użyjesz Cloud Console. Znajdź Workflows
w konsoli Google Cloud:
Odszukaj odpowiedni przepływ pracy i kliknij kartę Definition
:
Edytuj definicję przepływu pracy i dodaj wywołanie 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 dane wyjściowe funkcji mnożenia do wywołania funkcji logu w math.js
.
Interfejs zawiera instrukcje edytowania i wdrażania przepływu pracy. Po wdrożeniu kliknij Execute
, aby wykonać przepływ pracy. Zobaczysz szczegóły wykonania kodu:
Zwróć uwagę na kod stanu 200
i body
z danymi wyjściowymi funkcji logu.
Właśnie udało Ci się zintegrować usługę zewnętrzną z naszym przepływem pracy. Super!
8. Wdrażanie usługi Cloud Run
W ostatniej części dokończ przepływ pracy, wywołując prywatną usługę Cloud Run. Oznacza to, że aby wywołać usługę Cloud Run, przepływ pracy musi być uwierzytelniony.
Usługa Cloud Run zwraca math.floor
z przekazanej liczby.
Utwórz katalog z kodem usługi i przejdź do niego:
mkdir ~/floor cd ~/floor
Utwórz w katalogu plik app.py
o następującej 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 zmienną środowiskową 0.0.0.0
i PORT
, więc kod jest opisany powyżej.
Po otrzymaniu żądania HTTP ta funkcja wyodrębnia input
z treści JSON, wywołuje funkcję math.floor i zwraca wynik z powrotem do elementu wywołującego.
W tym samym katalogu utwórz taki plik 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 skompilowaniu kontenera wdróż go w Cloud Run. Zwróć uwagę na flagę no-allow-unauthenticated
. Dzięki temu usługa będzie akceptować tylko uwierzytelnione połączenia:
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 pracy.
9. Łączenie usługi Cloud Run
Zanim skonfigurujesz Workflows pod kątem wywoływania prywatnej usługi Cloud Run, musisz utworzyć konto usługi do wykorzystania przez Workflows:
export SERVICE_ACCOUNT=workflows-sa gcloud iam service-accounts create ${SERVICE_ACCOUNT}
Przypisz do konta usługi rolę run.invoker
. Pozwoli to kontu usługi na 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 również pole auth
, aby usługa Workflows przekazywał 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. Tym razem 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
Już za kilka sekund możesz przyjrzeć się wykonaniu przepływu pracy, by poznać efekt:
gcloud workflows executions describe <your-execution-id> --workflow workflow
Dane wyjściowe będą zawierać liczby całkowitą result
i state
:
result: '{"body":"5","code":200 ... } ... state: SUCCEEDED
10. Gratulacje!
Gratulujemy ukończenia ćwiczeń z programowania.
Omówione zagadnienia
- Podstawy Workflows.
- Jak połączyć publiczne funkcje w Cloud Functions z Workflows.
- Łączenie prywatnych usług Cloud Run z Workflows.
- Łączenie zewnętrznych interfejsów API HTTP z Workflows.