Bermigrasi dari Blobstore App Engine ke Cloud Storage (Modul 16)

1. Ringkasan

Seri codelab Serverless Migration Station (tutorial interaktif mandiri) dan video terkait bertujuan untuk membantu developer serverless Google Cloud memodernisasi aplikasi mereka dengan memandu mereka melalui satu atau beberapa migrasi, terutama beralih dari layanan lama. Dengan begitu, aplikasi Anda akan lebih portabel dan Anda akan memiliki lebih banyak opsi dan fleksibilitas, sehingga Anda dapat berintegrasi dengan dan mengakses berbagai produk Cloud yang lebih luas serta lebih mudah mengupgrade ke rilis bahasa yang lebih baru. Meskipun awalnya berfokus pada pengguna Cloud paling awal, terutama developer App Engine (lingkungan standar), seri ini cukup luas untuk mencakup platform serverless lainnya seperti Cloud Functions dan Cloud Run, atau di tempat lain jika berlaku.

Codelab ini mengajarkan cara bermigrasi dari Blobstore App Engine ke Cloud Storage. Ada juga migrasi implisit dari:

Lihat modul migrasi terkait untuk mengetahui informasi langkah demi langkah selengkapnya.

Anda akan mempelajari cara

  • Menambahkan penggunaan App Engine Blobstore API/library
  • Menyimpan upload pengguna ke layanan Blobstore
  • Bersiap untuk langkah berikutnya guna bermigrasi ke Cloud Storage

Yang Anda butuhkan

Survei

Bagaimana Anda akan menggunakan tutorial ini?

Hanya membacanya Membacanya dan menyelesaikan latihan

Bagaimana penilaian Anda terhadap pengalaman dengan Python?

Pemula Menengah Mahir

Bagaimana penilaian Anda terhadap pengalaman menggunakan layanan Google Cloud?

Pemula Menengah Mahir

2. Latar belakang

Codelab ini dimulai dengan aplikasi contoh dari Modul 15 dan menunjukkan cara bermigrasi dari Blobstore (dan NDB) ke Cloud Storage (dan Cloud NDB). Proses migrasi melibatkan penggantian dependensi pada layanan paket lama App Engine, yang memungkinkan Anda memindahkan aplikasi ke platform serverless Cloud lain atau platform hosting lain jika diinginkan.

Migrasi ini memerlukan lebih banyak upaya dibandingkan dengan migrasi lain dalam seri ini. Blobstore memiliki dependensi pada framework webapp asli, dan itulah sebabnya aplikasi contoh menggunakan framework webapp2, bukan Flask. Tutorial ini menampilkan migrasi ke Cloud Storage, Cloud NDB, Flask, dan Python 3.

Aplikasi ini masih mendaftarkan "kunjungan" pengguna akhir dan menampilkan sepuluh kunjungan terbaru, tetapi codelab sebelumnya (Modul 15) menambahkan fungsi baru untuk mengakomodasi penggunaan Blobstore: aplikasi meminta pengguna akhir untuk mengupload artefak (file) yang sesuai dengan "kunjungan" mereka. Pengguna dapat melakukannya atau memilih "lewati" untuk memilih tidak ikut. Terlepas dari keputusan pengguna, halaman berikutnya akan merender output yang sama seperti versi sebelumnya dari aplikasi ini, yang menampilkan kunjungan terbaru. Satu hal tambahan adalah kunjungan dengan artefak yang sesuai memiliki link "lihat" untuk menampilkan artefak kunjungan. Codelab ini mengimplementasikan migrasi yang disebutkan sebelumnya sekaligus mempertahankan fungsi yang dijelaskan.

3. Penyiapan/Prakerja

Sebelum masuk ke bagian utama tutorial, mari kita siapkan project, dapatkan kode, lalu deploy aplikasi dasar pengukuran agar kita tahu bahwa kita memulai dengan kode yang berfungsi.

1. Siapkan project

Jika Anda sudah men-deploy aplikasi Modul 15, sebaiknya gunakan kembali project (dan kode) yang sama. Atau, Anda dapat membuat project baru atau menggunakan kembali project lain yang sudah ada. Pastikan project memiliki akun penagihan yang aktif dan App Engine diaktifkan.

2. Dapatkan aplikasi contoh dasar pengukuran

Salah satu prasyarat untuk codelab ini adalah memiliki aplikasi contoh Modul 15 yang berfungsi. Jika belum memilikinya, Anda bisa mendapatkannya dari folder "START" Modul 15 (link di bawah). Codelab ini akan memandu Anda melalui setiap langkah, yang diakhiri dengan kode yang menyerupai kode dalam folder "FINISH" Modul 16.

Direktori file START Modul 15 akan terlihat seperti ini:

$ ls
README.md       app.yaml        main-gcs.py     main.py         templates

File main-gcs.py adalah versi alternatif dari main.py dari Modul 15 yang memungkinkan pemilihan bucket Cloud Storage yang berbeda dari URL default yang ditetapkan aplikasi berdasarkan ID project: PROJECT_ID.appspot.com. File ini tidak berperan dalam codelab (Modul 16) ini, selain teknik migrasi serupa yang dapat diterapkan ke file tersebut jika diinginkan.

3. Deploy (ulang) aplikasi dasar pengukuran

Langkah prakerja yang tersisa untuk dijalankan sekarang:

  1. Biasakan kembali diri Anda dengan alat command-line gcloud
  2. Deploy kembali aplikasi contoh dengan gcloud app deploy
  3. Konfirmasikan bahwa aplikasi berjalan di App Engine tanpa masalah

Setelah Anda berhasil menjalankan langkah-langkah tersebut dan mengonfirmasi bahwa aplikasi Modul 15 Anda berfungsi. Halaman awal menyambut pengguna dengan formulir yang meminta file artefak kunjungan untuk diupload beserta opsi, tombol "lewati", untuk memilih tidak ikut:

f5b5f9f19d8ae978.png

Setelah pengguna mengupload file atau melewati langkah ini, aplikasi akan merender halaman "kunjungan terbaru" yang sudah dikenal:

f5ac6b98ee8a34cb.png

Kunjungan yang menampilkan artefak akan memiliki link "view" di sebelah kanan stempel waktu kunjungan untuk menampilkan (atau mendownload) artefak. Setelah mengonfirmasi fungsi aplikasi, Anda siap untuk bermigrasi dari layanan lama App Engine (webapp2, NDB, Blobstore) ke alternatif kontemporer (Flask, Cloud NDB, Cloud Storage).

4. Update file konfigurasi

Tiga file konfigurasi akan digunakan untuk versi terbaru aplikasi kita. Tugas yang diperlukan adalah:

  1. Mengupdate library pihak ketiga bawaan yang diperlukan di app.yaml serta membuka peluang untuk migrasi Python 3
  2. Tambahkan requirements.txt, yang menentukan semua library yang diperlukan yang tidak bawaan
  3. Tambahkan appengine_config.py agar aplikasi mendukung library pihak ketiga bawaan dan non-bawaan

app.yaml

Edit file app.yaml Anda dengan memperbarui bagian libraries. Hapus jinja2 dan tambahkan grpcio, setuptools, dan ssl. Pilih versi terbaru yang tersedia untuk ketiga library tersebut. Tambahkan juga perintah runtime Python 3, tetapi jadikan sebagai komentar. Setelah selesai, tampilannya akan terlihat seperti ini (jika Anda memilih Python 3.9):

BEFORE:

runtime: python27
threadsafe: yes
api_version: 1

handlers:
- url: /.*
  script: main.app

libraries:
- name: jinja2
  version: latest

AFTER:

#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

Perubahan ini terutama berkaitan dengan library bawaan Python 2 yang tersedia di server App Engine (sehingga Anda tidak perlu memaketkannya sendiri). Kami menghapus Jinja2 karena sudah disertakan dalam Flask, yang akan kami tambahkan ke reqs.txt. Setiap kali library klien Google Cloud, seperti untuk Cloud NDB dan Cloud Storage, digunakan, grpcio dan setuptools diperlukan. Terakhir, Cloud Storage sendiri memerlukan library ssl. Perintah runtime yang dijadikan sebagai komentar di bagian atas adalah untuk saat Anda siap mem-porting aplikasi ini ke Python 3. Kami akan membahas topik ini di akhir tutorial ini.

requirements.txt

Tambahkan file requirements.txt, yang memerlukan framework Flask, serta library klien Cloud NDB dan Cloud Storage, yang tidak ada dalam paket bawaan. Buat file dengan konten ini:

flask
google-cloud-ndb
google-cloud-storage

Runtime App Engine Python 2 memerlukan pemaketan mandiri library pihak ketiga non-bawaan, jadi jalankan perintah berikut untuk menginstal library ini ke folder lib:

pip install -t lib -r requirements.txt

Jika Anda memiliki Python 2 dan 3 di mesin pengembangan, Anda mungkin harus menggunakan perintah pip2 untuk memastikan mendapatkan library versi Python 2. Setelah mengupgrade ke Python 3, Anda tidak perlu lagi melakukan pemaketan mandiri.

appengine_config.py

Tambahkan file appengine_config.py yang mendukung library pihak ketiga bawaan dan non-bawaan. Buat file dengan konten ini:

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)

Langkah-langkah yang baru saja diselesaikan seharusnya serupa atau identik dengan langkah-langkah yang tercantum di bagian Menginstal library untuk aplikasi Python 2 dalam dokumen App Engine, dan lebih spesifiknya, konten appengine_config.py harus cocok dengan yang ada di Langkah 5 di sana.

Pekerjaan pada file konfigurasi telah selesai, jadi mari kita lanjutkan ke aplikasi.

5. Mengubah file aplikasi

Impor

Kumpulan perubahan pertama untuk main.py mencakup penggantian semua hal yang diganti. Berikut yang akan berubah:

  1. webapp2 diganti dengan Flask
  2. Daripada menggunakan Jinja2 dari webapp2_extras, gunakan Jinja2 yang disertakan dengan Flask
  3. Blobstore dan NDB App Engine digantikan oleh Cloud NDB dan Cloud Storage
  4. Pengendali Blobstore di webapp diganti dengan kombinasi modul library standar io, Flask, dan utilitas werkzeug
  5. Secara default, Blobstore menulis ke bucket Cloud Storage yang diberi nama berdasarkan URL aplikasi Anda (PROJECT_ID.appspot.com). Karena kita melakukan porting ke library klien Cloud Storage, google.auth digunakan untuk mendapatkan project ID guna menentukan nama bucket yang sama persis. (Anda dapat mengubah nama bucket karena nama tersebut tidak lagi di-hardcode.)

BEFORE:

import webapp2
from webapp2_extras import jinja2
from google.appengine.ext import blobstore, ndb
from google.appengine.ext.webapp import blobstore_handlers

Terapkan perubahan dalam daftar di atas dengan mengganti bagian impor saat ini di main.py dengan cuplikan kode di bawah.

AFTER:

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

Inisialisasi dan dukungan Jinja2 yang tidak diperlukan

Blok kode berikutnya yang akan diganti adalah BaseHandler yang menentukan penggunaan Jinja2 dari webapp2_extras. Hal ini tidak diperlukan karena Jinja2 disertakan dengan Flask dan merupakan mesin template default-nya, jadi hapus saja.

Di sisi Modul 16, buat instance objek yang tidak ada di aplikasi lama. Hal ini termasuk menginisialisasi aplikasi Flask dan membuat klien API untuk Cloud NDB dan Cloud Storage. Terakhir, kita menyusun nama bucket Cloud Storage seperti yang dijelaskan di atas di bagian impor. Berikut adalah tampilan sebelum dan setelah menerapkan pembaruan ini:

BEFORE:

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))

AFTER:

app = Flask(__name__)
ds_client = ndb.Client()
gcs_client = storage.Client()
_, PROJECT_ID = google.auth.default()
BUCKET = '%s.appspot.com' % PROJECT_ID

Memperbarui akses Datastore

Cloud NDB sebagian besar kompatibel dengan App Engine NDB. Satu perbedaan yang telah dibahas adalah perlunya klien API. Hal lainnya adalah yang terakhir mengharuskan akses Datastore dikontrol oleh pengelola konteks Python klien API. Intinya, ini berarti semua panggilan akses Datastore yang menggunakan library klien Cloud NDB hanya dapat terjadi dalam blok with Python.

Itu adalah salah satu perubahan; perubahan lainnya adalah Blobstore dan objeknya, misalnya, BlobKey, tidak didukung oleh Cloud Storage, jadi ubah file_blob menjadi ndb.StringProperty. Berikut adalah class model data serta fungsi store_visit() dan fetch_visits() yang diperbarui yang mencerminkan perubahan ini:

BEFORE:

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)

AFTER:

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)

Berikut adalah representasi bergambar dari perubahan yang telah dilakukan sejauh ini:

a8f74ca392275822.png

Memperbarui pengendali

Pengendali upload

Pengendali di webapp2 adalah class, sedangkan di Flask, pengendali adalah fungsi. Alih-alih metode kata kerja HTTP, Flask menggunakan kata kerja untuk mendekorasi fungsi. Blobstore dan pengendali webapp-nya digantikan oleh fungsi dari Cloud Storage serta Flask dan utilitasnya:

BEFORE:

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)

AFTER:

@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)

Beberapa catatan terkait pembaruan ini:

  • Alih-alih blob_id, artefak file kini diidentifikasi berdasarkan nama file (fname) jika ada, dan None jika tidak ada (pengguna memilih untuk tidak mengupload file).
  • Pengendali Blobstore mengabstraksi proses upload dari penggunanya, tetapi Cloud Storage tidak, sehingga Anda dapat melihat kode yang baru ditambahkan yang menetapkan objek blob dan lokasi (bucket) file serta panggilan yang melakukan upload sebenarnya. (upload_from_file()).
  • webapp2 menggunakan tabel perutean di bagian bawah file aplikasi, sedangkan rute Flask ditemukan di setiap pengendali yang didekorasi.
  • Kedua pengendali menyelesaikan fungsinya dengan mengalihkan ke beranda ( / ) sambil mempertahankan permintaan POST dengan kode pengembalian HTTP 307.

Pengelola download

Memperbarui pengendali download mengikuti pola yang mirip dengan pengendali upload, hanya saja kode yang perlu dilihat jauh lebih sedikit. Ganti fungsi Blobstore dan webapp dengan fungsi Cloud Storage dan Flask yang setara:

BEFORE:

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)

AFTER:

@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)

Catatan tentang update ini:

  • Sekali lagi, Flask mendekorasi fungsi pengendali dengan rutenya, sedangkan webapp melakukannya dalam tabel pemilihan rute di bagian bawah, jadi kenali sintaksis pencocokan pola yang terakhir ('/view/([^/]+)?') vs. Flask ('/view/<path:fname>').
  • Seperti pengendali upload, ada sedikit lebih banyak pekerjaan yang diperlukan di sisi Cloud Storage untuk fungsi yang diabstraksi oleh pengendali Blobstore, yaitu mengidentifikasi file (blob) yang dimaksud dan secara eksplisit mendownload biner vs. panggilan metode send_blob() tunggal pengendali Blobstore.
  • Dalam kedua kasus tersebut, error HTTP 404 akan ditampilkan kepada pengguna jika artefak tidak ditemukan.

Pengendali utama

Perubahan akhir pada aplikasi utama dilakukan di pengendali utama. Metode kata kerja HTTP webapp2 diganti dengan satu fungsi yang menggabungkan fungsinya. Ganti class MainHandler dengan fungsi root() dan hapus tabel pemilihan rute webapp2 seperti yang ditunjukkan di bawah:

BEFORE:

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)

AFTER:

@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)

Alih-alih memisahkan metode get() dan post(), metode tersebut pada dasarnya adalah pernyataan if-else di root(). Selain itu, karena root() adalah fungsi tunggal, hanya ada satu panggilan untuk merender template untuk GET dan POST, sedangkan hal ini tidak mungkin dilakukan di webapp2.

Berikut adalah representasi bergambar dari kumpulan perubahan kedua dan terakhir pada main.py:

5ec38818c32fec2.png

(opsional) "Peningkatan" kompatibilitas mundur

Jadi, solusi yang dibuat di atas berfungsi dengan sempurna... tetapi hanya jika Anda memulai dari awal dan tidak memiliki file yang dibuat oleh Blobstore. Karena kami telah mengupdate aplikasi untuk mengidentifikasi file berdasarkan nama file, bukan BlobKey, aplikasi Modul 16 yang telah selesai tidak akan dapat melihat file Blobstore. Dengan kata lain, kami membuat perubahan yang tidak kompatibel dengan versi lama saat melakukan migrasi ini. Kami sekarang menyajikan versi alternatif main.py yang disebut main-migrate.py (ditemukan di repo) yang mencoba menjembatani kesenjangan ini.

"Ekstensi" pertama yang mendukung file yang dibuat Blobstore adalah model data yang memiliki BlobKeyProperty (selain StringProperty untuk file yang dibuat 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()

Properti file_blob akan digunakan untuk mengidentifikasi file yang dibuat Blobstore, sedangkan file_gcs untuk file Cloud Storage. Sekarang, saat membuat kunjungan baru, simpan nilai secara eksplisit di file_gcs, bukan file_blob, sehingga store_visit terlihat sedikit berbeda:

BEFORE:

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()

AFTER:

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()

Saat mengambil kunjungan terbaru, "normalkan" data sebelum mengirimkannya ke template:

BEFORE:

@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)

AFTER:

@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)

Selanjutnya, konfirmasi keberadaan file_blob atau file_gcs (atau tidak keduanya). Jika ada file yang tersedia, pilih file yang ada dan gunakan ID tersebut (BlobKey untuk file yang dibuat Blobstore atau nama file untuk file yang dibuat Cloud Storage). Yang kami maksud dengan "file yang dibuat Cloud Storage" adalah file yang dibuat menggunakan library klien Cloud Storage. Blobstore juga menulis ke Cloud Storage, tetapi dalam hal ini, file tersebut akan dibuat oleh Blobstore.

Sekarang, yang lebih penting, apa fungsi etl_visits() yang digunakan untuk menormalisasi atau ETL (ekstrak, transformasi, dan pemuatan) data bagi pengguna akhir? Tampilannya terlihat seperti ini:

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]

Mungkin terlihat seperti yang Anda harapkan: kode melakukan loop melalui semua kunjungan, dan untuk setiap kunjungan, mengambil data pengunjung dan stempel waktu secara verbatim, lalu memeriksa apakah file_gcs atau file_blob ada, dan jika ada, memilih salah satunya (atau None jika keduanya tidak ada).

Berikut ilustrasi perbedaan antara main.py dan main-migrate.py:

718b05b2adadb2e1.png

Jika Anda memulai dari awal tanpa file yang dibuat Blobstore, gunakan main.py, tetapi jika Anda sedang bertransisi dan ingin mendukung file yang dibuat oleh Blobstore dan Cloud Storage, lihat main-migrate.py sebagai contoh cara menangani skenario seperti ini untuk membantu Anda merencanakan migrasi untuk aplikasi Anda sendiri. Saat melakukan migrasi yang kompleks, kasus khusus kemungkinan akan muncul, sehingga contoh ini dimaksudkan untuk menunjukkan afinitas yang lebih besar terhadap modernisasi aplikasi nyata dengan data nyata.

6. Ringkasan/Pembersihan

Bagian ini mengakhiri codelab dengan men-deploy aplikasi, memverifikasi bahwa aplikasi berfungsi sebagaimana mestinya dan dalam output yang ditampilkan. Setelah validasi aplikasi, lakukan langkah-langkah pembersihan dan pertimbangkan langkah berikutnya.

Men-deploy dan memverifikasi aplikasi

Sebelum men-deploy ulang aplikasi, pastikan untuk menjalankan pip install -t lib -r requirements.txt guna mendapatkan library pihak ketiga yang dipaketkan sendiri di folder lib. Jika Anda ingin menjalankan solusi yang kompatibel dengan versi lama, ganti nama main-migrate.py menjadi main.py terlebih dahulu. Sekarang jalankan gcloud app deploy, dan pastikan aplikasi berfungsi sama dengan aplikasi Modul 15. Layar formulir akan terlihat seperti ini:

f5b5f9f19d8ae978.png

Halaman kunjungan terbaru akan terlihat seperti ini:

f5ac6b98ee8a34cb.png

Selamat, Anda telah menyelesaikan codelab ini yang mengganti Blobstore App Engine dengan Cloud Storage, NDB App Engine dengan Cloud NDB, dan webapp2 dengan Flask. Kode Anda sekarang akan cocok dengan yang ada di folder FINISH (Modul 16). main-migrate.py alternatif juga ada di folder tersebut.

"Migrasi" Python 3

Perintah runtime Python 3 yang dijadikan sebagai komentar di bagian atas app.yaml adalah satu-satunya yang diperlukan untuk mem-porting aplikasi ini ke Python 3. Kode sumbernya sendiri sudah kompatibel dengan Python 3, jadi tidak perlu ada perubahan. Untuk men-deploy-nya sebagai aplikasi Python 3, lakukan langkah-langkah berikut:

  1. Hapus tanda komentar pada perintah runtime Python 3 di bagian atas app.yaml.
  2. Hapus semua baris lainnya di app.yaml.
  3. Hapus file appengine_config.py. (tidak digunakan dalam runtime Python 3)
  4. Hapus folder lib jika ada. (tidak diperlukan dengan runtime Python 3)

Pembersihan

Umum

Jika Anda sudah selesai, sebaiknya nonaktifkan aplikasi App Engine untuk menghindari tagihan. Namun, jika Anda ingin menguji atau bereksperimen lebih lanjut, platform App Engine memiliki kuota gratis, dan selama Anda tidak melebihi tingkat penggunaan tersebut, Anda tidak akan dikenai biaya. Biaya tersebut adalah untuk komputasi, tetapi mungkin juga ada biaya untuk layanan App Engine yang relevan, jadi periksa halaman harganya untuk mengetahui informasi selengkapnya. Jika migrasi ini melibatkan layanan Cloud lainnya, layanan tersebut akan ditagih secara terpisah. Dalam kedua kasus tersebut, jika ada, lihat bagian "Khusus untuk codelab ini" di bawah.

Sebagai informasi, men-deploy ke platform komputasi serverless Google Cloud seperti App Engine akan dikenai biaya build dan penyimpanan yang kecil. Cloud Build memiliki kuota gratisnya sendiri, begitu juga dengan Cloud Storage. Penyimpanan gambar tersebut akan menggunakan sebagian kuota tersebut. Namun, Anda mungkin tinggal di wilayah yang tidak memiliki paket gratis tersebut, jadi perhatikan penggunaan penyimpanan Anda untuk meminimalkan potensi biaya. "Folder" Cloud Storage tertentu yang harus Anda tinjau meliputi:

  • console.cloud.google.com/storage/browser/LOC.artifacts.PROJECT_ID.appspot.com/containers/images
  • console.cloud.google.com/storage/browser/staging.PROJECT_ID.appspot.com
  • Link penyimpanan di atas bergantung pada PROJECT_ID dan *LOC*ation Anda, misalnya, "us" jika aplikasi Anda dihosting di Amerika Serikat.

Di sisi lain, jika Anda tidak akan melanjutkan aplikasi ini atau codelab migrasi terkait lainnya dan ingin menghapus semuanya sepenuhnya, nonaktifkan project Anda.

Khusus untuk codelab ini

Layanan yang tercantum di bawah ini unik untuk codelab ini. Lihat dokumentasi setiap produk untuk mengetahui informasi selengkapnya:

Perlu diperhatikan bahwa jika Anda bermigrasi dari Modul 15 ke 16, Anda masih akan memiliki data di Blobstore, sehingga kami menyertakan informasi harganya di atas.

Langkah berikutnya

Selain tutorial ini, modul migrasi lain yang berfokus pada peralihan dari paket layanan lama yang perlu dipertimbangkan meliputi:

  • Modul 2: bermigrasi dari ndb App Engine ke Cloud NDB
  • Modul 7-9: bermigrasi dari tugas push Task Queue App Engine ke Cloud Tasks
  • Modul 12-13: bermigrasi dari Memcache App Engine ke Cloud Memorystore
  • Modul 18-19: bermigrasi dari Task Queue App Engine (tugas pull) ke Cloud Pub/Sub

App Engine bukan lagi satu-satunya platform serverless di Google Cloud. Jika Anda memiliki aplikasi App Engine kecil atau aplikasi yang memiliki fungsi terbatas dan ingin mengubahnya menjadi microservice mandiri, atau Anda ingin memecah aplikasi monolitik menjadi beberapa komponen yang dapat digunakan kembali, ini adalah alasan yang tepat untuk mempertimbangkan beralih ke Cloud Functions. Jika containerization telah menjadi bagian dari alur kerja pengembangan aplikasi Anda, terutama jika terdiri dari pipeline CI/CD (continuous integration/continuous delivery atau deployment), pertimbangkan untuk bermigrasi ke Cloud Run. Skenario ini dibahas dalam modul berikut:

  • Melakukan migrasi dari App Engine ke Cloud Functions: lihat Modul 11
  • Bermigrasi dari App Engine ke Cloud Run: lihat Modul 4 untuk memasukkan aplikasi Anda ke dalam container dengan Docker, atau Modul 5 untuk melakukannya tanpa container, pengetahuan Docker, atau Dockerfile

Beralih ke platform serverless lain bersifat opsional, dan sebaiknya pertimbangkan opsi terbaik untuk aplikasi dan kasus penggunaan Anda sebelum melakukan perubahan apa pun.

Terlepas dari modul migrasi yang Anda pertimbangkan berikutnya, semua konten Serverless Migration Station (codelab, video, kode sumber [jika tersedia]) dapat diakses di repo open source-nya. README repositori juga memberikan panduan tentang migrasi yang perlu dipertimbangkan dan "urutan" Modul Migrasi yang relevan.

7. Referensi lainnya

Masalah/masukan codelab

Jika Anda menemukan masalah dengan codelab ini, telusuri masalah Anda terlebih dahulu sebelum mengajukan masalah. Link untuk menelusuri dan membuat masalah baru:

Referensi migrasi

Link ke folder repo untuk Modul 15 (START) dan Modul 16 (FINISH) dapat ditemukan dalam tabel di bawah. Kode tersebut juga dapat diakses dari repo untuk semua migrasi codelab App Engine yang dapat Anda clone atau download file ZIP-nya.

Codelab

Python 2

Python 3

Modul 15

kode

T/A

Modul 16 (codelab ini)

kode

(sama seperti Python 2)

Referensi online

Berikut adalah referensi online yang mungkin relevan untuk tutorial ini:

Blobstore App Engine dan Cloud Storage

Platform App Engine

Informasi Cloud lainnya

Python

Video

Lisensi

Karya ini dilisensikan berdasarkan Lisensi Umum Creative Commons Attribution 2.0.