1. Przegląd
Seria codelabów Serverless Migration Station (samodzielne, praktyczne samouczki) i powiązane z nimi filmy mają na celu pomóc deweloperom usług bezserwerowych Google Cloud w modernizacji aplikacji poprzez przeprowadzenie ich przez co najmniej jedną migrację, głównie z usług starszego typu. Dzięki temu Twoje aplikacje będą bardziej przenośne, a Ty zyskasz więcej opcji i elastyczności, co umożliwi Ci integrację z szerszą gamą usług w chmurze i łatwiejsze przechodzenie na nowsze wersje języka. Chociaż początkowo skupialiśmy się na pierwszych użytkownikach usług w chmurze, głównie na deweloperach App Engine (środowisko standardowe), ta seria jest wystarczająco szeroka, aby obejmować inne platformy bezserwerowe, takie jak Cloud Functions i Cloud Run, lub inne, jeśli ma to zastosowanie.
Ten przewodnik uczy, jak przeprowadzić migrację z App Engine Blobstore do Cloud Storage. Istnieją też niejawne migracje z tych usług:
webapp2platformy internetowej na Flask (omówionej w module 1).- App Engine NDB na Cloud NDB na potrzeby dostępu do Datastore (omówione w module 2).
- Python 2 do 3 (przeniesiona aplikacja jest zgodna z językami Python 2 i 3)
Więcej szczegółowych informacji znajdziesz w powiązanych modułach migracji.
Dowiesz się, jak:
- Dodawanie korzystania z interfejsu API/biblioteki Blobstore App Engine
- Przechowywanie plików przesłanych przez użytkowników w usłudze Blobstore
- Przygotowanie do następnego kroku migracji do Cloud Storage
Czego potrzebujesz
- projekt Google Cloud Platform z aktywnym kontem rozliczeniowym GCP;
- podstawowe umiejętności w zakresie Pythona,
- Praktyczna znajomość typowych poleceń systemu Linux
- Podstawowa wiedza na temat tworzenia i wdrażania aplikacji App Engine.
- Działająca aplikacja App Engine z modułu 15: wykonaj ćwiczenie z programowania z modułu 15 (zalecane) lub skopiuj aplikację z modułu 15 z repozytorium.
Ankieta
Jak zamierzasz korzystać z tego samouczka?
Jak oceniasz swoje doświadczenie z Pythonem?
Jak oceniasz korzystanie z usług Google Cloud?
2. Tło
W tym laboratorium zaczynamy od przykładowej aplikacji z modułu 15 i pokazujemy, jak przeprowadzić migrację z Blobstore (i NDB) do Cloud Storage (i Cloud NDB). Proces migracji polega na zastąpieniu zależności od starszych usług pakietowych App Engine, co umożliwia przeniesienie aplikacji na inną bezserwerową platformę Cloud lub inną platformę hostingową.
Ta migracja wymaga nieco więcej wysiłku niż inne migracje z tej serii. Blobstore jest zależny od oryginalnej platformy programistycznej, dlatego w przykładowej aplikacji używana jest platforma webapp2 zamiast Flask. Ten samouczek zawiera informacje o migracjach do Cloud Storage, Cloud NDB, Flask i Python 3.
Aplikacja nadal rejestruje „wizyty” użytkowników i wyświetla 10 najnowszych, ale w poprzednim laboratorium (moduł 15) dodaliśmy nową funkcję, która umożliwia korzystanie z Blobstore: aplikacja prosi użytkowników o przesłanie artefaktu (pliku) odpowiadającego ich „wizycie”. Użytkownicy mogą to zrobić lub wybrać „Pomiń”, aby zrezygnować. Niezależnie od decyzji użytkownika następna strona renderuje te same dane wyjściowe co poprzednie wersje tej aplikacji, wyświetlając najnowsze wizyty. Dodatkowo wizyty z odpowiednimi artefaktami mają link „Wyświetl”, który pozwala wyświetlić artefakt wizyty. W tym laboratorium kodowania wdrażamy wspomniane wcześniej migracje, zachowując opisaną funkcjonalność.
3. Konfiguracja/przygotowanie
Zanim przejdziemy do głównej części samouczka, skonfigurujmy projekt, pobierzmy kod i wdrożymy aplikację podstawową, aby mieć pewność, że zaczynamy od działającego kodu.
1. Konfigurowanie projektu
Jeśli aplikacja z modułu 15 została już wdrożona, zalecamy ponowne użycie tego samego projektu (i kodu). Możesz też utworzyć zupełnie nowy projekt lub ponownie wykorzystać inny istniejący projekt. Sprawdź, czy projekt ma aktywne konto rozliczeniowe i czy usługa App Engine jest włączona.
2. Pobieranie przykładowej aplikacji podstawowej
Jednym z wymagań wstępnych tego laboratorium jest działająca przykładowa aplikacja z modułu 15. Jeśli jej nie masz, możesz ją pobrać z folderu „START” modułu 15 (link poniżej). W tym ćwiczeniu Codelabs znajdziesz instrukcje krok po kroku, a na końcu kod podobny do tego, który znajduje się w folderze „FINISH” modułu 16.
- START: Folder modułu 15 (Python 2)
- ZAKOŃCZ: Folder modułu 16 (Python 2)
- Całe repozytorium (do sklonowania lub pobrania pliku ZIP)
Katalog plików początkowych modułu 15 powinien wyglądać tak:
$ ls README.md app.yaml main-gcs.py main.py templates
Plik main-gcs.py to alternatywna wersja pliku main.py z modułu 15, która umożliwia wybór zasobnika Cloud Storage innego niż domyślny adres URL przypisany do aplikacji na podstawie identyfikatora projektu: PROJECT_ID.appspot.com. Ten plik nie odgrywa żadnej roli w tym laboratorium (moduł 16). W razie potrzeby można do niego zastosować podobne techniki migracji.
3. (Ponowne) wdrażanie aplikacji bazowej
Pozostałe czynności przygotowawcze, które musisz teraz wykonać:
- Przypomnij sobie, jak działa narzędzie wiersza poleceń
gcloud. - Ponowne wdrażanie przykładowej aplikacji za pomocą
gcloud app deploy - Sprawdź, czy aplikacja działa w App Engine bez problemów.
Po wykonaniu tych czynności i potwierdzeniu, że aplikacja z modułu 15 działa prawidłowo. Na stronie początkowej wyświetla się formularz z prośbą o przesłanie pliku artefaktu wizyty oraz opcją rezygnacji w postaci przycisku „Pomiń”:

Gdy użytkownicy prześlą plik lub pominą ten krok, aplikacja wyświetli znaną stronę „Ostatnie wizyty”:

Wizyty zawierające artefakt będą miały link „Wyświetl” po prawej stronie sygnatury czasowej wizyty, który umożliwia wyświetlenie (lub pobranie) artefaktu. Gdy potwierdzisz, że aplikacja działa prawidłowo, możesz przeprowadzić migrację z usług starszego typu App Engine (webapp2, NDB, Blobstore) na współczesne alternatywy (Flask, Cloud NDB, Cloud Storage).
4. Aktualizowanie plików konfiguracji
W przypadku zaktualizowanej wersji naszej aplikacji używane są 3 pliki konfiguracyjne. Wymagane zadania to:
- Zaktualizuj wymagane wbudowane biblioteki innych firm w
app.yaml, a także pozostaw możliwość migracji do Pythona 3. - Dodaj
requirements.txt, który określa wszystkie wymagane biblioteki, które nie są wbudowane. - Dodaj
appengine_config.py, aby aplikacja obsługiwała zarówno wbudowane, jak i zewnętrzne biblioteki innych firm.
app.yaml
Edytuj plik app.yaml, aktualizując sekcję libraries. Usuń jinja2 i dodaj grpcio, setuptools i ssl. Wybierz najnowszą wersję dostępną dla wszystkich 3 bibliotek. Dodaj też dyrektywę runtime Python 3, ale w postaci komentarza. Gdy skończysz, powinno to wyglądać tak (jeśli wybrano Pythona 3.9):
PRZED:
runtime: python27
threadsafe: yes
api_version: 1
handlers:
- url: /.*
script: main.app
libraries:
- name: jinja2
version: latest
PO:
#runtime: python39
runtime: python27
threadsafe: yes
api_version: 1
handlers:
- url: /.*
script: main.app
libraries:
- name: grpcio
version: latest
- name: setuptools
version: latest
- name: ssl
version: latest
Zmiany dotyczą głównie wbudowanych bibliotek języka Python 2 dostępnych na serwerach App Engine (dzięki czemu nie musisz ich samodzielnie pakować). Usunęliśmy Jinja2, ponieważ jest on dostarczany z Flaskiem, który dodamy do pliku reqs.txt. Gdy używane są biblioteki klienta Google Cloud, takie jak biblioteki Cloud NDB i Cloud Storage, wymagane są grpcio i setuptools. Biblioteka ssl jest też wymagana przez samą usługę Cloud Storage. Zakomentowana dyrektywa środowiska wykonawczego u góry jest przeznaczona na moment, w którym będziesz gotowy do przeniesienia tej aplikacji do Pythona 3. Tym tematem zajmiemy się pod koniec tego samouczka.
requirements.txt
Dodaj plik requirements.txt, który wymaga frameworka Flask oraz bibliotek klienta Cloud NDB i Cloud Storage. Żadna z nich nie jest wbudowana. Utwórz plik z tą zawartością:
flask
google-cloud-ndb
google-cloud-storage
Środowisko wykonawcze App Engine Python 2 wymaga samodzielnego pakowania bibliotek innych firm, które nie są wbudowane, więc uruchom to polecenie, aby zainstalować te biblioteki w folderze lib:
pip install -t lib -r requirements.txt
Jeśli na komputerze używanym do programowania masz zainstalowane zarówno Pythona 2, jak i 3, może być konieczne użycie polecenia pip2, aby uzyskać wersje tych bibliotek dla Pythona 2. Po uaktualnieniu do Pythona 3 nie musisz już samodzielnie tworzyć pakietów.
appengine_config.py
Dodaj plik appengine_config.py obsługujący wbudowane i zewnętrzne biblioteki innych firm. Utwórz plik z tą zawartością:
import pkg_resources
from google.appengine.ext import vendor
# Set PATH to your libraries folder.
PATH = 'lib'
# Add libraries installed in the PATH folder.
vendor.add(PATH)
# Add libraries to pkg_resources working set to find the distribution.
pkg_resources.working_set.add_entry(PATH)
Wykonane przed chwilą czynności powinny być podobne lub identyczne z czynnościami wymienionymi w sekcji Instalowanie bibliotek w aplikacjach w Pythonie 2 w dokumentacji App Engine, a w szczególności zawartość pliku appengine_config.py powinna być zgodna z zawartością kroku 5.
Praca z plikami konfiguracji została zakończona, więc przejdźmy do aplikacji.
5. Modyfikowanie plików aplikacji
Importy
Pierwszy zestaw zmian w przypadku main.py obejmuje zamianę wszystkich elementów, które mają zostać zastąpione. Co się zmienia:
webapp2zostaje zastąpiony przez Flask- Zamiast korzystać z Jinja2 z
webapp2_extras, używaj Jinja2 dołączonego do Flaska. - App Engine Blobstore i NDB zostały zastąpione przez Cloud NDB i Cloud Storage
- Obsługa Blobstore w
webappzostała zastąpiona kombinacją modułu biblioteki standardowejio, Flaska i narzędziwerkzeug. - Domyślnie Blobstore zapisuje dane w zasobniku Cloud Storage o nazwie odpowiadającej adresowi URL aplikacji (
PROJECT_ID.appspot.com). Ponieważ przenosimy dane do biblioteki klienta Cloud Storage,google.authsłuży do pobierania identyfikatora projektu w celu określenia dokładnie tej samej nazwy zasobnika. (Możesz zmienić nazwę zasobnika, ponieważ nie jest już zakodowana na stałe).
PRZED:
import webapp2
from webapp2_extras import jinja2
from google.appengine.ext import blobstore, ndb
from google.appengine.ext.webapp import blobstore_handlers
Wprowadź zmiany z powyższej listy, zastępując bieżącą sekcję importu w pliku main.py fragmentem kodu poniżej.
PO:
import io
from flask import (Flask, abort, redirect, render_template,
request, send_file, url_for)
from werkzeug.utils import secure_filename
import google.auth
from google.cloud import exceptions, ndb, storage
Inicjalizacja i niepotrzebna obsługa Jinja2
Kolejny blok kodu do zastąpienia to BaseHandler, który określa użycie Jinja2 z webapp2_extras. Jest to niepotrzebne, ponieważ Jinja2 jest dostarczana z Flaskiem i jest jego domyślnym silnikiem szablonów, więc usuń ją.
Po stronie modułu 16 utwórz instancje obiektów, których nie było w starszej aplikacji. Obejmuje to zainicjowanie aplikacji Flask i utworzenie klientów interfejsu API dla Cloud NDB i Cloud Storage. Na koniec tworzymy nazwę zasobnika Cloud Storage zgodnie z opisem w sekcji importów. Oto przykłady przed wprowadzeniem tych zmian i po ich wprowadzeniu:
PRZED:
class BaseHandler(webapp2.RequestHandler):
'Derived request handler mixing-in Jinja2 support'
@webapp2.cached_property
def jinja2(self):
return jinja2.get_jinja2(app=self.app)
def render_response(self, _template, **context):
self.response.write(self.jinja2.render_template(_template, **context))
PO:
app = Flask(__name__)
ds_client = ndb.Client()
gcs_client = storage.Client()
_, PROJECT_ID = google.auth.default()
BUCKET = '%s.appspot.com' % PROJECT_ID
Aktualizowanie dostępu do Datastore
Cloud NDB jest w większości przypadków zgodna z App Engine NDB. Jedną z różnic, o której już wspomnieliśmy, jest konieczność używania klienta interfejsu API. Kolejna różnica polega na tym, że w przypadku tego drugiego dostępu do Datastore musi zarządzać menedżer kontekstu Pythona klienta API. Oznacza to, że wszystkie wywołania dostępu do Datastore za pomocą biblioteki klienta Cloud NDB mogą występować tylko w blokach Pythona with.
To jedna zmiana.Druga polega na tym, że Blobstore i jego obiekty, np. BlobKey, nie są obsługiwane przez Cloud Storage, więc zamiast file_blob użyj ndb.StringProperty. Poniżej znajdziesz klasę modelu danych oraz zaktualizowane funkcje store_visit() i fetch_visits(), które odzwierciedlają te zmiany:
PRZED:
class Visit(ndb.Model):
'Visit entity registers visitor IP address & timestamp'
visitor = ndb.StringProperty()
timestamp = ndb.DateTimeProperty(auto_now_add=True)
file_blob = ndb.BlobKeyProperty()
def store_visit(remote_addr, user_agent, upload_key):
'create new Visit entity in Datastore'
Visit(visitor='{}: {}'.format(remote_addr, user_agent),
file_blob=upload_key).put()
def fetch_visits(limit):
'get most recent visits'
return Visit.query().order(-Visit.timestamp).fetch(limit)
PO:
class Visit(ndb.Model):
'Visit entity registers visitor IP address & timestamp'
visitor = ndb.StringProperty()
timestamp = ndb.DateTimeProperty(auto_now_add=True)
file_blob = ndb.StringProperty()
def store_visit(remote_addr, user_agent, upload_key):
'create new Visit entity in Datastore'
with ds_client.context():
Visit(visitor='{}: {}'.format(remote_addr, user_agent),
file_blob=upload_key).put()
def fetch_visits(limit):
'get most recent visits'
with ds_client.context():
return Visit.query().order(-Visit.timestamp).fetch(limit)
Oto graficzne przedstawienie wprowadzonych do tej pory zmian:

Aktualizowanie modułów obsługi
Przesyłanie
Obsługi w webapp2 to klasy, a w Flask są funkcjami. Zamiast metody czasownika HTTP Flask używa czasownika do dekorowania funkcji. Blobstore i jego moduły obsługi webapp zostały zastąpione funkcjami Cloud Storage oraz Flask i jego narzędziami:
PRZED:
class UploadHandler(blobstore_handlers.BlobstoreUploadHandler):
'Upload blob (POST) handler'
def post(self):
uploads = self.get_uploads()
blob_id = uploads[0].key() if uploads else None
store_visit(self.request.remote_addr, self.request.user_agent, blob_id)
self.redirect('/', code=307)
PO:
@app.route('/upload', methods=['POST'])
def upload():
'Upload blob (POST) handler'
fname = None
upload = request.files.get('file', None)
if upload:
fname = secure_filename(upload.filename)
blob = gcs_client.bucket(BUCKET).blob(fname)
blob.upload_from_file(upload, content_type=upload.content_type)
store_visit(request.remote_addr, request.user_agent, fname)
return redirect(url_for('root'), code=307)
Kilka uwag dotyczących tej aktualizacji:
- Zamiast
blob_idartefakty plików są teraz identyfikowane na podstawie nazwy pliku (fname), jeśli jest dostępna, lubNonew przeciwnym razie (użytkownik zrezygnował z przesyłania pliku). - Obsługa Blobstore odciążała użytkowników od procesu przesyłania, ale Cloud Storage tego nie robi. Dlatego możesz zobaczyć nowo dodany kod, który ustawia obiekt blob pliku i jego lokalizację (zasobnik), a także wywołanie, które wykonuje rzeczywiste przesyłanie. (
upload_from_file()). webapp2korzysta z tabeli routingu u dołu pliku aplikacji, a trasy Flaska znajdują się w każdym dekorowanym module obsługi.- Oba moduły obsługi kończą swoje działanie, przekierowując do strony głównej (
/) przy zachowaniu żądaniaPOSTz kodem zwrotu HTTP 307.
Moduł obsługi pobierania
Aktualizowanie modułu obsługi pobierania przebiega podobnie jak w przypadku modułu obsługi przesyłania, tylko jest tu znacznie mniej kodu do przeanalizowania. Zastąp funkcje Blobstore i webapp odpowiednikami w Cloud Storage i Flask:
PRZED:
class ViewBlobHandler(blobstore_handlers.BlobstoreDownloadHandler):
'view uploaded blob (GET) handler'
def get(self, blob_key):
self.send_blob(blob_key) if blobstore.get(blob_key) else self.error(404)
PO:
@app.route('/view/<path:fname>')
def view(fname):
'view uploaded blob (GET) handler'
blob = gcs_client.bucket(BUCKET).blob(fname)
try:
media = blob.download_as_bytes()
except exceptions.NotFound:
abort(404)
return send_file(io.BytesIO(media), mimetype=blob.content_type)
Uwagi dotyczące tej aktualizacji:
- Flask dekoruje funkcje obsługi za pomocą ich trasy, a
webapprobi to w tabeli routingu u dołu. Zwróć uwagę na składnię dopasowywania wzorców w przypadkuwebapp(('/view/([^/]+)?') i Flaska ('/view/<path:fname>'). - Podobnie jak w przypadku modułu obsługi przesyłania, po stronie Cloud Storage trzeba wykonać nieco więcej pracy w przypadku funkcji, które są abstrakcyjnie obsługiwane przez moduły obsługi blobstore, a mianowicie zidentyfikować dany plik (BLOB) i jawnie pobrać dane binarne w porównaniu z pojedynczym wywołaniem metody
send_blob()modułu obsługi blobstore. - W obu przypadkach, jeśli artefakt nie zostanie znaleziony, użytkownik otrzyma błąd HTTP 404.
Główny moduł obsługi
Ostateczne zmiany w głównej aplikacji są wprowadzane w głównym programie obsługi. Metody czasownika HTTP webapp2 zostały zastąpione jedną funkcją łączącą ich działanie. Zastąp klasę MainHandler funkcją root() i usuń tabelę routingu webapp2, jak pokazano poniżej:
PRZED:
class MainHandler(BaseHandler):
'main application (GET/POST) handler'
def get(self):
self.render_response('index.html',
upload_url=blobstore.create_upload_url('/upload'))
def post(self):
visits = fetch_visits(10)
self.render_response('index.html', visits=visits)
app = webapp2.WSGIApplication([
('/', MainHandler),
('/upload', UploadHandler),
('/view/([^/]+)?', ViewBlobHandler),
], debug=True)
PO:
@app.route('/', methods=['GET', 'POST'])
def root():
'main application (GET/POST) handler'
context = {}
if request.method == 'GET':
context['upload_url'] = url_for('upload')
else:
context['visits'] = fetch_visits(10)
return render_template('index.html', **context)
Zamiast oddzielnych metod get() i post() są one w zasadzie instrukcją if-else w języku root(). Poza tym, ponieważ root() to jedna funkcja, istnieje tylko jedno wywołanie renderowania szablonu zarówno dla GET, jak i POST, co nie jest możliwe w przypadku webapp2.
Oto graficzne przedstawienie drugiego i ostatniego zestawu zmian w main.py:

(opcjonalnie) „Ulepszenie” zgodności wstecznej
Powyższe rozwiązanie działa doskonale, ale tylko wtedy, gdy zaczynasz od zera i nie masz plików utworzonych przez Blobstore. Zaktualizowaliśmy aplikację, aby identyfikowała pliki według nazwy, a nie BlobKey, więc ukończona aplikacja z modułu 16 w obecnej postaci nie będzie mogła wyświetlać plików Blobstore. Innymi słowy, podczas tej migracji wprowadziliśmy zmianę, która nie jest wstecznie kompatybilna. Przedstawiamy teraz alternatywną wersję main.py o nazwie main-migrate.py (znajdującą się w Repo), która ma na celu wypełnienie tej luki.
Pierwszym „rozszerzeniem” obsługującym pliki utworzone w Blobstore jest model danych, który ma BlobKeyProperty (oprócz StringProperty w przypadku plików utworzonych w Cloud Storage):
class Visit(ndb.Model):
'Visit entity registers visitor IP address & timestamp'
visitor = ndb.StringProperty()
timestamp = ndb.DateTimeProperty(auto_now_add=True)
file_blob = ndb.BlobKeyProperty() # backwards-compatibility
file_gcs = ndb.StringProperty()
Właściwość file_blob będzie używana do identyfikowania plików utworzonych przez Blobstore, a właściwość file_gcs – plików Cloud Storage. Teraz podczas tworzenia nowych wizyt wyraźnie zapisuj wartość w parametrze file_gcs zamiast w parametrze file_blob, więc parametr store_visit będzie wyglądać nieco inaczej:
PRZED:
def store_visit(remote_addr, user_agent, upload_key):
'create new Visit entity in Datastore'
with ds_client.context():
Visit(visitor='{}: {}'.format(remote_addr, user_agent),
file_blob=upload_key).put()
PO:
def store_visit(remote_addr, user_agent, upload_key):
'create new Visit entity in Datastore'
with ds_client.context():
Visit(visitor='{}: {}'.format(remote_addr, user_agent),
file_gcs=upload_key).put()
Podczas pobierania najnowszych wizyt „normalizuj” dane przed wysłaniem ich do szablonu:
PRZED:
@app.route('/', methods=['GET', 'POST'])
def root():
'main application (GET/POST) handler'
context = {}
if request.method == 'GET':
context['upload_url'] = url_for('upload')
else:
context['visits'] = fetch_visits(10)
return render_template('index.html', **context)
PO:
@app.route('/', methods=['GET', 'POST'])
def root():
'main application (GET/POST) handler'
context = {}
if request.method == 'GET':
context['upload_url'] = url_for('upload')
else:
context['visits'] = etl_visits(fetch_visits(10))
return render_template('index.html', **context)
Następnie sprawdź, czy występuje file_blob lub file_gcs (lub żadne z nich). Jeśli plik jest dostępny, wybierz istniejący plik i użyj jego identyfikatora (BlobKey w przypadku plików utworzonych w Blobstore lub nazwy pliku w przypadku plików utworzonych w Cloud Storage). Określenie „pliki utworzone przez Cloud Storage” oznacza pliki utworzone przy użyciu biblioteki klienta Cloud Storage. Blobstore też zapisuje dane w Cloud Storage, ale w tym przypadku są to pliki utworzone przez Blobstore.
Co ważniejsze, czym jest ta funkcja etl_visits(), która służy do normalizowania lub ETL (wyodrębniania, przekształcania i ładowania) danych dla użytkownika? Wygląda on następująco:
def etl_visits(visits):
return [{
'visitor': v.visitor,
'timestamp': v.timestamp,
'file_blob': v.file_gcs if hasattr(v, 'file_gcs') \
and v.file_gcs else v.file_blob
} for v in visits]
Prawdopodobnie wygląda on tak, jak się spodziewasz: kod przechodzi przez wszystkie wizyty i w przypadku każdej z nich pobiera dane o użytkowniku i sygnaturze czasowej, a następnie sprawdza, czy istnieje file_gcs lub file_blob, i jeśli tak, wybiera jeden z nich (lub None, jeśli żaden z nich nie istnieje).
Ilustracja różnic między main.py a main-migrate.py:

Jeśli zaczynasz od zera i nie masz plików utworzonych przez Blobstore, użyj main.py. Jeśli jednak przechodzisz na nową usługę i chcesz obsługiwać pliki utworzone zarówno przez Blobstore , jak i Cloud Storage, zapoznaj się z przykładem main-migrate.py, który pokazuje, jak postępować w takim przypadku, aby ułatwić sobie planowanie migracji własnych aplikacji. Podczas złożonych migracji mogą wystąpić przypadki specjalne, dlatego ten przykład ma na celu pokazanie większego podobieństwa do modernizacji prawdziwych aplikacji z prawdziwymi danymi.
6. Podsumowanie i czyszczenie
W tej sekcji podsumowujemy te warsztaty, wdrażając aplikację i sprawdzając, czy działa zgodnie z oczekiwaniami i czy dane wyjściowe są prawidłowe. Po zweryfikowaniu aplikacji wykonaj czynności związane z czyszczeniem i zastanów się, co dalej zrobić.
Wdrażanie i weryfikowanie aplikacji
Zanim ponownie wdrożysz aplikację, uruchom polecenie pip install -t lib -r requirements.txt, aby uzyskać te samodzielnie spakowane biblioteki innych firm w folderze lib. Jeśli chcesz uruchomić rozwiązanie zgodne wstecznie, najpierw zmień nazwę pliku main-migrate.py na main.py. Teraz uruchom gcloud app deploy i sprawdź, czy aplikacja działa tak samo jak aplikacja z modułu 15. Ekran formularza wygląda tak:

Strona z najnowszymi wizytami wygląda tak:

Gratulujemy ukończenia tego ćwiczenia (w Codelabs), w którym zastąpiliśmy App Engine Blobstore usługą Cloud Storage, App Engine NDB usługą Cloud NDB, a webapp2 platformą Flask. Kod powinien teraz odpowiadać temu, który znajduje się w folderze FINISH (Module 16). W tym folderze znajduje się też alternatywna wersja main-migrate.py.
„Migracja” do Pythona 3
Wystarczy, że na początku pliku app.yaml umieścisz dyrektywę Python 3 runtime, która jest zakomentowana, aby przenieść tę aplikację do Pythona 3. Sam kod źródłowy jest już zgodny z Pythonem 3, więc nie trzeba go zmieniać. Aby wdrożyć tę aplikację jako aplikację w Pythonie 3, wykonaj te czynności:
- Odkomentuj dyrektywę Pythona 3
runtimeu góry plikuapp.yaml. - Usuń wszystkie pozostałe wiersze w
app.yaml. - Usuń plik
appengine_config.py. (nieużywane w środowisku wykonawczym Python 3) - Usuń folder
lib, jeśli istnieje. (niepotrzebne w środowisku wykonawczym Pythona 3)
Czyszczenie danych
Ogólne
Jeśli na razie nie chcesz już korzystać z usługi, zalecamy wyłączenie aplikacji App Engine, aby uniknąć naliczania opłat. Jeśli jednak chcesz przeprowadzić więcej testów lub eksperymentów, platforma App Engine ma bezpłatny limit, więc dopóki nie przekroczysz tego poziomu wykorzystania, nie powinny być naliczane żadne opłaty. Dotyczy to obliczeń, ale mogą też wystąpić opłaty za odpowiednie usługi App Engine, więc więcej informacji znajdziesz na stronie z cennikiem. Jeśli migracja obejmuje inne usługi w chmurze, są one rozliczane oddzielnie. W każdym przypadku, jeśli to konieczne, zapoznaj się z sekcją „Specyficzne dla tego laboratorium” poniżej.
Wdrożenie na bezserwerowej platformie obliczeniowej Google Cloud, takiej jak App Engine, wiąże się z niewielkimi kosztami kompilacji i przechowywania. Cloud Build ma własny bezpłatny limit, podobnie jak Cloud Storage. Przechowywanie tego obrazu wykorzystuje część tego limitu. Możesz jednak mieszkać w regionie, w którym nie ma takiego bezpłatnego pakietu, więc kontroluj wykorzystanie miejsca na dane, aby zminimalizować potencjalne koszty. Sprawdź te „foldery” Cloud Storage:
console.cloud.google.com/storage/browser/LOC.artifacts.PROJECT_ID.appspot.com/containers/imagesconsole.cloud.google.com/storage/browser/staging.PROJECT_ID.appspot.com- Linki do pamięci masowej powyżej zależą od
PROJECT_IDi *LOC*acji, np. „us”, jeśli Twoja aplikacja jest hostowana w Stanach Zjednoczonych.
Jeśli nie zamierzasz kontynuować pracy z tą aplikacją ani innymi powiązanymi z nią samouczkami dotyczącymi migracji i chcesz wszystko całkowicie usunąć, wyłącz projekt.
Dotyczy tych ćwiczeń z programowania
Usługi wymienione poniżej są dostępne tylko w tym laboratorium. Więcej informacji znajdziesz w dokumentacji poszczególnych usług:
- Usługa Blobstore App Engine podlega limitom i limitom danych przechowywanych, więc zapoznaj się z nimi oraz ze stroną z cennikiem starszych usług pakietowych.
- Cloud Storage ma bezpłatny poziom w określonych regionach. Więcej informacji znajdziesz na ogólnej stronie z cennikiem.
- Usługa App Engine Datastore jest udostępniana przez Cloud Datastore (Cloud Firestore w trybie Datastore), która również ma bezpłatny poziom. Więcej informacji znajdziesz na stronie z cennikiem.
Pamiętaj, że jeśli nastąpiła migracja z modułu 15 do 16, nadal będziesz mieć dane w Blobstore, dlatego powyżej podajemy informacje o cenach tej usługi.
Dalsze kroki
Oprócz tego samouczka warto zapoznać się z innymi modułami migracji, które koncentrują się na przejściu ze starszych pakietów usług:
- Moduł 2. Migracja z App Engine
ndbdo Cloud NDB - Moduły 7–9: migracja z zadań push w kolejce zadań App Engine do Cloud Tasks
- Moduły 12–13: migracja z Memcache App Engine do Cloud Memorystore
- Moduły 18–19: migracja z kolejki zadań App Engine (zadania pull) do Cloud Pub/Sub
App Engine nie jest już jedyną platformą bezserwerową w Google Cloud. Jeśli masz małą aplikację App Engine lub aplikację o ograniczonej funkcjonalności i chcesz przekształcić ją w samodzielny mikroserwis albo podzielić aplikację monolityczną na wiele komponentów wielokrotnego użytku, warto rozważyć przejście na Cloud Functions. Jeśli konteneryzacja stała się częścią procesu tworzenia aplikacji, zwłaszcza jeśli obejmuje potok CI/CD (tryb ciągłej integracji/tryb ciągłego dostarczania lub wdrażanie), rozważ migrację do Cloud Run. Te scenariusze są omówione w tych modułach:
- Migracja z App Engine do Cloud Functions: patrz moduł 11
- Migracja z App Engine do Cloud Run: w module 4 dowiesz się, jak skonteneryzować aplikację za pomocą Dockera, a w module 5 – jak to zrobić bez kontenerów, wiedzy o Dockerze ani
Dockerfiles
Przejście na inną platformę bezserwerową jest opcjonalne. Zanim wprowadzisz jakiekolwiek zmiany, zalecamy rozważenie najlepszych opcji dla Twoich aplikacji i przypadków użycia.
Niezależnie od tego, który moduł migracji wybierzesz, wszystkie materiały dotyczące Serverless Migration Station (ćwiczenia z programowania, filmy, kod źródłowy [jeśli jest dostępny]) znajdziesz w repozytorium open source. W repozytorium README znajdziesz też wskazówki dotyczące migracji, które warto rozważyć, oraz odpowiednią „kolejność” modułów migracji.
7. Dodatkowe materiały
Problemy z ćwiczeniami z programowania i opinie na ich temat
Jeśli zauważysz jakieś problemy z tym kursem, najpierw poszukaj rozwiązania, a dopiero potem zgłoś problem. Linki do wyszukiwania i tworzenia nowych problemów:
Materiały dotyczące migracji
Linki do folderów repozytorium dla modułu 15 (START) i modułu 16 (FINISH) znajdziesz w tabeli poniżej. Możesz też uzyskać do nich dostęp w repozytorium wszystkich migracji codelabów App Engine, które możesz sklonować lub pobrać jako plik ZIP.
Ćwiczenia z programowania | Python 2 | Python 3 |
Moduł 15 | Nie dotyczy | |
Moduł 16 (to ćwiczenie) | (tak samo jak w przypadku Pythona 2) |
Zasoby online
Poniżej znajdziesz zasoby online, które mogą być przydatne w tym samouczku:
App Engine Blobstore i Cloud Storage
- Usługa Blobstore App Engine
- Migracja do biblioteki klienta Cloud Storage
- Strona główna Cloud Storage
- Dokumentacja Cloud Storage
Platforma App Engine
- Dokumentacja App Engine
- Środowisko wykonawcze App Engine (środowisko standardowe) w Pythonie 2
- Korzystanie z wbudowanych bibliotek App Engine w App Engine w Pythonie 2
- Środowisko wykonawcze Pythona 3 w App Engine (środowisko standardowe)
- Różnice między środowiskami wykonawczymi App Engine (środowisko standardowe) w Pythonie 2 i 3
- Przewodnik po migracji z App Engine (środowisko standardowe) z Pythona 2 na Pythona 3
- Informacje o cenach i limitach App Engine
- Uruchomienie platformy App Engine drugiej generacji (2018)
- Porównanie platform pierwszej i drugiej generacji
- Wsparcie długoterminowe dla starszych środowisk wykonawczych
- Repozytorium z przykładami migracji dokumentacji
- Repozytorium próbek migracji udostępnionych przez społeczność
Inne informacje o chmurze
- Python w Google Cloud Platform
- Biblioteki klienta Google Cloud Python
- Poziom „Zawsze bezpłatny” w Google Cloud
- Google Cloud SDK (narzędzie wiersza poleceń
gcloud) - Cała dokumentacja Google Cloud
Python
- systemy szablonów Django i Jinja2,
webapp2framework internetowywebapp2dokumentacjawebapp2_extraslinkiwebapp2_extrasDokumentacja Jinja2- Framework internetowy Flask
Filmy
- Serverless Migration Station
- Ekspedycje bezserwerowe
- Subskrybuj Google Cloud Tech
- Subskrybuj Google Developers
Licencja
To zadanie jest licencjonowane na podstawie ogólnej licencji Creative Commons Attribution 2.0.