Modul 1: Melakukan migrasi dari webapp2 App Engine ke Flask

Rangkaian codelab ini (tutorial praktik mandiri) bertujuan untuk membantu developer Google App Engine (Standar) memodernisasi aplikasi mereka dengan memandu mereka melalui serangkaian migrasi. Langkah yang paling signifikan adalah beralih dari layanan paket runtime asli karena runtime generasi berikutnya lebih fleksibel, sehingga memberikan opsi layanan yang lebih beragam kepada pengguna. Peralihan ke runtime generasi baru memungkinkan Anda berintegrasi dengan produk Google Cloud dengan lebih mudah, menggunakan berbagai layanan yang didukung, dan mendukung rilis bahasa saat ini.

Tutorial awal ini menunjukkan langkah-langkah migrasi pertama untuk memodernisasi framework web di aplikasi App Engine: berpindah dari webapp2 ke Flask. Di aplikasi, Anda bisa menggunakan framework web apa pun yang menangani perutean, namun untuk tutorial ini, kami menggunakan Flask karena digunakan secara luas oleh komunitas.

Anda akan mempelajari cara

  • Menggunakan library pihak ketiga (built-in atau lainnya)
  • Memperbarui file konfigurasi
  • Memigrasikan aplikasi sederhana dari webapp2 ke Flask

Yang akan Anda perlukan

Survei

Bagaimana Anda akan menggunakan codelab ini?

Hanya membacanya Membacanya dan menyelesaikan latihan

Framework webapp dipaketkan saat App Engine pertama kali diluncurkan di Python 2.5 pada tahun 2008. Bertahun-tahun kemudian, aplikasi ini digantikan oleh penerusnya webapp2 ketika runtime versi 2.5 habis dan digantikan versi 2.7 pada tahun 2013.

Meskipun webapp2 (lihat dokumen) masih ada dan dapat digunakan di luar App Engine sebagai framework web yang sesuai dengan WSGI, namun aplikasi ini tidak melakukan perutean permintaan penggunanya sendiri ke kode yang sesuai dalam aplikasi. Sebagai gantinya, aplikasi tersebut mengandalkan App Engine, file konfigurasi, dan developer untuk melakukan perutean traffic web tersebut ke "pengendali" yang sesuai. Selain itu, manfaat inti webapp2 sangat terkait dengan layanan paket App Engine, yang secara efektif menghentikan penggunaannya meskipun aplikasi ini berfungsi di Python 3 (lihat juga masalah terkait).

Modul ini memberikan pengalaman praktis kepada para Praktisi untuk memigrasikan aplikasi webapp2 sederhana ke Flask, sebuah framework yang didukung oleh App Engine dan banyak layanan lainnya di luar Google Cloud, yang membuat aplikasi jadi jauh lebih portabel. Jika Flask bukan framework yang diinginkan sebagai tujuan pemindahan aplikasi Anda, Anda dapat memilih yang lain asalkan framework tersebut melakukan perutean sendiri. Codelab ini menunjukkan kepada pembuat keputusan teknologi informasi (ITDM) dan developer tentang langkah-langkah migrasi, sehingga Anda dapat membiasakan diri dengan proses ini terlepas dari framework yang benar-benar menjadi tujuan migrasi Anda.

Berikut adalah langkah-langkah utama untuk migrasi ini:

  1. Penyiapan/Prakerja
  2. Tambahkan library pihak ke-3 Flask
  3. Perbarui file aplikasi
  4. Perbarui file template HTML

Sebelum melanjutkan dengan bagian utama tutorial, siapkan project, dapatkan kode, lalu biasakan (kembali) diri Anda dengan perintah gcloud dan deploy aplikasi dasar pengukuran sehingga kami dapat memulai dengan kode yang berfungsi.

1. Siapkan project

Sebagai developer yang sudah ada, dasbor App Engine Anda mungkin sudah menunjukkan layanan yang telah Anda jalankan. Untuk keperluan tutorial ini, sebaiknya Anda membuat project baru atau menggunakan kembali project yang sudah ada untuk tutorial ini. Pastikan project memiliki akun penagihan yang aktif dan App Engine (aplikasi) diaktifkan.

2. Download aplikasi contoh dasar pengukuran

Repo migrasi GAE memiliki semua kode yang Anda butuhkan. Clone atau download file ZIP-nya. Untuk tutorial ini, Anda akan memulai dengan kode di folder Modul 0 (START), dan setelah menyelesaikan tutorial, kode Anda harus cocok dengan folder Modul 1 (FINISH). Jika tidak, periksa perbedaannya sehingga Anda dapat melanjutkan ke lab berikutnya.

Folder Modul 0 harus memiliki file yang terlihat seperti ini, sebagaimana yang diilustrasikan dengan perintah POSIX ls:

$ ls
app.yaml        index.html      main.py

3. Biasakan (kembali) diri Anda dengan perintah gcloud

Jika Anda belum memiliki perintah gcloud di komputer, instal Google Cloud SDK dan pastikan gcloud tersedia sebagai bagian dari jalur eksekusi Anda, lalu biasakan diri Anda dengan perintah gcloud berikut:

  1. gcloud components update — perbarui Google Cloud SDK
  2. gcloud auth login — login ke akun kredensial Anda
  3. gcloud config list — daftar setelan konfigurasi project GCP
  4. gcloud config set project PROJECT_ID — tetapkan project ID GCP
  5. gcloud app deploy — Deploy aplikasi App Engine Anda

Jika Anda belum melakukan pengembangan App Engine dengan gcloud baru-baru ini, Anda harus menjalankan empat perintah pertama (#1-#4) agar siap sebelum melanjutkan ke langkah berikutnya. Mari kita telusuri ringkasan singkat perintah ini.

Pertama, gcloud components update memastikan Anda memiliki Cloud SDK versi terbaru. Menjalankan perintah ini akan memberikan output seperti berikut:

$ gcloud components update

Your current Cloud SDK version is: 317.0.0
You will be upgraded to version: 318.0.0

┌──────────────────────────────────────────────────┐
│        These components will be updated.         │
├──────────────────────────┬────────────┬──────────┤
│           Name           │  Version   │   Size   │
├──────────────────────────┼────────────┼──────────┤
│ Cloud SDK Core Libraries │ 2020.11.06 │ 15.5 MiB │
│ gcloud cli dependencies  │ 2020.11.06 │ 10.6 MiB │
└──────────────────────────┴────────────┴──────────┘

The following release notes are new in this upgrade.
Please read carefully for information about new features, breaking changes,
and bugs fixed.  The latest full release notes can be viewed at:
  https://cloud.google.com/sdk/release_notes

318.0.0 (2020-11-10)

      . . .
      (release notes)
      . . .

    Subscribe to these release notes at
    https://groups.google.com/forum/#!forum/google-cloud-sdk-announce.

Do you want to continue (Y/n)?

╔════════════════════════════════════════════════════════════╗
╠═ Creating update staging area                             ═╣
╠════════════════════════════════════════════════════════════╣
╠═ Uninstalling: Cloud SDK Core Libraries                   ═╣
╠════════════════════════════════════════════════════════════╣
╠═ Uninstalling: gcloud cli dependencies                    ═╣
╠════════════════════════════════════════════════════════════╣
╠═ Installing: Cloud SDK Core Libraries                     ═╣
╠════════════════════════════════════════════════════════════╣
╠═ Installing: gcloud cli dependencies                      ═╣
╠════════════════════════════════════════════════════════════╣
╠═ Creating backup and activating new installation          ═╣
╚════════════════════════════════════════════════════════════╝

Performing post processing steps...done.

Update done!

To revert your SDK to the previously installed version, you may run:
  $ gcloud components update --version 317.0.0

Selanjutnya, gunakan gcloud auth login guna mengautentikasi diri untuk perintah gcloud yang akan Anda terbitkan selanjutnya:

$ gcloud auth login
Your browser has been opened to visit:

    https://accounts.google.com/o/oauth2/auth?response_type=code&client_id= . . .

You are now logged in as [YOUR_EMAIL].
Your current project is [PROJECT_ID].  You can change this setting by running:
  $ gcloud config set project PROJECT_ID

Gunakan gcloud config list untuk melihat setelan project Anda saat ini:

$ gcloud config list
[core]
account = YOUR_EMAIL
disable_usage_reporting = False
project = PROJECT_ID

Your active configuration is: [default]

Perintah di atas akan memandu Anda dalam membuat project baru atau memilih project yang sudah ada. Jika output gcloud config list tidak cocok dengan project yang dipilih yang ingin Anda gunakan untuk tutorial ini, jalankan gcloud config set project PROJECT_ID untuk menetapkan project ID. Kemudian, pastikan project ID yang tepat ditetapkan dengan menjalankan gcloud config list lagi.

$ gcloud config set project PROJECT_ID
Updated property [core/project].

Jika memilih menggunakan Cloud Console, Anda dapat mengikuti antarmuka pengguna untuk membuat project baru jika diinginkan atau menggunakan project yang sudah ada. Di dasbor project, Anda akan melihat kartu info project yang menampilkan ID-nya (beserta nama dan nomor project):

kartu info project

Perintah terakhir (#5), gcloud app deploy, adalah untuk men-deploy aplikasi Anda ke App Engine. Karena kita baru memulai, menjalankannya sekarang bersifat opsional, tetapi kita tentu tidak melarang deploy kode Modul 0 untuk mengonfirmasi bahwa kode tersebut berfungsi. Setelah eksekusi, pilih region geografis tempat aplikasi akan dijalankan (biasanya lokasi Anda berada). Ini tidak dapat diubah setelah ditetapkan. Kemudian tonton informasi deployment selanjutnya. Setelah selesai, Anda akan diberi tahu tentang URL tempat aplikasi Anda akan ditayangkan. Berikut adalah versi ringkas yang mungkin Anda lihat:

$ gcloud app deploy
Services to deploy:

descriptor:      [/private/tmp/mod0-baseline/app.yaml]
source:          [/private/tmp/mod0-baseline]
target project:  [PROJECT_ID]
target service:  [default]
target version:  [20201116t220827]
target url:      [https://PROJECT_ID.REG_ABBR.r.appspot.com]

Do you want to continue (Y/n)?

Beginning deployment of service [default]...
╔════════════════════════════════════════════════════════════╗
╠═ Uploading 1 file to Google Cloud Storage                 ═╣
╚════════════════════════════════════════════════════════════╝
File upload done.
Updating service [default]...done.
Setting traffic split for service [default]...done.
Deployed service [default] to [https://PROJECT_ID.REG_ABBR.r.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

Jika Anda sudah lama tidak menggunakan App Engine, Anda mungkin akan melihat deployment awal perintah appcfg.py update telahdiganti oleh gcloud app deploy. Untuk mempelajari lebih lanjut tentang gcloud app deploy, lihat halaman dokumentasinya.

Perubahan terbaru lainnya adalah URL aplikasi yang di-deploy, yang diubah dari http://PROJECT_ID.appspot.com menjadi http://PROJECT_ID.REG_ABBR.r.appspot.com. Sebagian besar aplikasi pada akhirnya akan dikonversi ke format baru. Info selengkapnya tentang format URL di dokumentasi permintaan dan perutean.

Setelah aplikasi di-deploy, muat ulang browser (mungkin beberapa kali) untuk melihat kunjungan terbaru:

aplikasi visitme

Jika aplikasi Anda baru, Anda hanya akan melihat satu atau beberapa kunjungan.

Runtime Python 2 App Engine menyediakan kumpulan library pihak ketiga "bawaan" yang hanya perlu Anda tentukan di file app.yaml yang akan digunakan. Meskipun migrasi ini tidak memerlukan penggunaannya, kumpulan library tersebut akan ada dalam tutorial migrasi berikutnya (untuk Modul 2).

Library pihak ketiga yang bukan bawaan harus ditentukan dalam file dengan nama requirements.txt dan diinstal secara lokal di folder lib dalam direktori yang sama dengan kode aplikasi tempat semua file diupload ke App Engine. Dokumentasi untuk memaketkan library pihak ketiga memiliki informasi lebih lanjut.

Library yang disalin seperti Flask mengharuskan Anda memberi tahu App Engine untuk mencarinya di folder lib menggunakan file konfigurasi appengine_config.py. File konfigurasi appengine_config.py ditempatkan di folder aplikasi tingkat atas yang sama dengan requirements.txt dan lib. Di bagian tutorial ini, Anda akan:

  • Membuat requirements.txt (sebutkan library pihak ketiga [non-bawaan] yang disalin)
  • Membuat appengine_config.py (mengenali library pihak ketiga)
  • Menginstal paket dan dependensi (pihak ketiga)

1. Buat requirements.txt

Buat file requirements.txt untuk menentukan paket Anda. Dalam kasus kami, Flask adalah library pihak ketiga yang diperlukan. Pada saat penulisan tutorial ini, versi terbaru adalah 1.1.2, jadi buat requirements.txt dengan satu baris ini:

Flask==1.1.2

Lihat dokumentasi requirements.txt untuk mempelajari lebih lanjut tentang format yang diterima.

2. Buat appengine_config.py

Langkah berikutnya adalah membuat App Engine mengenali library pihak ketiga eksternal. Buat file bernama appengine_config.py dengan konten berikut:

from google.appengine.ext import vendor

# Set PATH to your libraries folder.
PATH = 'lib'
# Add libraries installed in the PATH folder.
vendor.add(PATH)

Kode ini melakukan persis seperti yang ditentukan sebelumnya, yaitu mengarahkan App Engine ke folder lib untuk library yang disalin.

3. Instal paket dan dependensi

Lalu jalankan perintah pip install untuk membuat folder lib dan menginstal Flask beserta dependensinya di sana:

$ pip install -t lib -r requirements.txt

Jika menggunakan pip atau pip2, setelah penginstalan paket selesai, Anda akan memiliki folder lib yang akan memiliki konten serupa dengan:

$ ls lib
bin/
click/
click-7.1.2.dist-info/
flask/
Flask-1.1.2.dist-info/
itsdangerous/
itsdangerous-1.1.0.dist-info/
jinja2/
Jinja2-2.11.2.dist-info/
markupsafe/
MarkupSafe-1.1.1.dist-info/
werkzeug/
Werkzeug-1.0.1.dist-info/

Sekarang mari perbarui file aplikasi, main.py.

1. Impor

Impor akan dilakukan terlebih dahulu seperti pada semua file Python. Impor framework webapp2 diikuti oleh library Datastore ndb, dan terakhir, ekstensi App Engine yang memproses template yang sesuai dengan gaya Django. Anda akan melihat berikut ini:

  • SEBELUM:
import webapp2
from google.appengine.ext import ndb
from google.appengine.ext.webapp import template

Saat memindahkan ke Flask, Anda akan mengimpor potongan Flask dan perender template sekaligus. Hapus pasangan impor terkait webapp2 dan ganti sebagai berikut (biarkan ndb impor apa adanya):

  • SETELAH:
from flask import Flask, render_template, request
from google.appengine.ext import ndb

2. Startup

Aplikasi yang menggunakan webapp2 memerlukan satu array (daftar Python) yang mencantumkan semua rute dan pengendali di file Python apa pun (mungkin ada pula yang lain):

  • SEBELUM:
app = webapp2.WSGIApplication([
    ('/', MainHandler),
], debug=True)

Perlu diingat bahwa app.yaml melakukan perutean tingkat yang lebih tinggi dan dapat memanggil pengendali yang berbeda. Aplikasi sampel cukup sederhana sehingga semua rute datang ke pengendali main.py.

Flask tidak menggunakan tabel perutean seperti ini, jadi hapus baris ini di main.py. Flask juga memerlukan inisialisasi, jadi tambahkan baris berikut di atas main.py tepat di bawah impor:

  • SETELAH:
app = Flask(__name__)

Di Flask, Anda menginisialisasi framework lalu menggunakan dekorator untuk menentukan rute. Selain itu, rute juga dipasangkan dengan fungsi, bukan class atau metode.

Di luar cakupan, Anda dapat menyertakan tutorial Flask di codelab ini, jadi luangkan waktu untuk mempelajari tutorial Flask dan tinjau dokumentasi Flask agar lebih nyaman dengan framework tersebut.

3. Model data

Tidak ada perubahan di sini. Datastore akan menjadi fokus codelab berikutnya.

4. Pengendali

Aplikasi, terlepas dari framework yang Anda gunakan (webapp2 atau Flask), melakukan 3 hal:

  1. Menangani permintaan GET (/) jalur root
  2. Daftarkan "kunjungan" halaman web (buat/simpan objek Visit)
  3. Tampilkan 10 kunjungan terbaru (dengan template yang ditentukan sebelumnya, index.html)

Framework webapp2 menggunakan model eksekusi berbasis class dengan pengendali dibuat untuk setiap metode HTTP yang didukung. Dalam kasus sederhana, kami hanya memiliki GET, sehingga metode get() ditentukan:

  • SEBELUM:
class MainHandler(webapp2.RequestHandler):
    def get(self):
        store_visit(self.request.remote_addr, self.request.user_agent)
        visits = fetch_visits(10) or ()  # empty sequence if None
        tmpl = os.path.join(os.path.dirname(__file__), 'index.html')
        self.response.out.write(template.render(tmpl, {'visits': visits}))

Seperti yang disebutkan di atas, Flask melakukan perutean sendiri. Sebagai ganti class pengendali, Anda menulis fungsi dan mendekorasinya dengan rute yang harus dipanggil. Pengguna bisa menetapkan metode HTTP yang ditangani dalam panggilan dekorator, yaitu @app.route('/app/', methods=['GET', 'POST']). Karena defaultnya hanya GET (dan secara implisit HEAD), ini bisa ditinggalkan.

Dalam melakukan migrasi ke Flask, ganti class MainHandler dan metode get() dengan fungsi perutean Flask berikut:

  • SETELAH:
@app.route('/')
def root():
    store_visit(request.remote_addr, request.user_agent)
    visits = fetch_visits(10) or ()  # empty sequence if None
    return render_template('index.html', visits=visits)

Tentu saja hal ini tidak mewakili aplikasi Anda yang pasti akan lebih kompleks daripada contoh ini. Salah satu tujuan utama tutorial ini adalah membantu Anda memulai, mem-build sebagian dari "memori otot", dan memahami tempat untuk membuat perubahan di kode khusus App Engine. Untuk mengonfirmasi bahwa Anda telah melakukan perubahan ini dengan benar, bandingkan kode Anda dengan main.py Modul 1.

5. File tambahan

Tidak ada perubahan pada file .gcloudignore. Tujuannya adalah menentukan file yang tidak di-deploy ke App Engine yang tidak diperlukan untuk men-deploy dan menjalankan aplikasi, termasuk namun tidak terbatas pada Python tambahan, kontrol asal, repo boilerplate, dan file lainnya. .gcloudignore kami terlihat seperti ini (dengan komentar yang dihapus agar singkat):

.gcloudignore
.git
.gitignore
.hgignore
.hg/
*.pyc
*.pyo
__pycache__/
/setup.cfg
README.md

1. Pindahkan file template

Dalam folder repositori baseline (Modul 0), file template index.html berada dalam folder yang sama dengan file aplikasi. Karena Flask memerlukan file HTML yang ditempatkan di folder templates, Anda harus membuat folder tersebut (mkdir templates) dan memindahkan index.html di sana. Dalam sistem yang kompatibel dengan POSIX seperti Linux atau Mac OS X, perintahnya adalah:

mkdir templates
mv index.html templates

2. Perbarui file template

Setelah Anda memindahkan index.html ke templates, kini saatnya membuat pengeditan kecil namun diperlukan. Mari kita lihat file template asli secara keseluruhan:

<!doctype html>
<html>
<head>
<title>VisitMe Example</title>
<body>

<h1>VisitMe example</h1>
<h3>Last 10 visits</h3>
<ul>
{% for visit in visits %}
    <li>{{ visit.timestamp.ctime }} from {{ visit.visitor }}</li>
{% endfor %}
</ul>

</body>
</html>

Sementara webapp2 menggunakan template Django yang menjalankan callable seperti visit.timestamp.ctime tanpa tanda kurung ( ), Jinja2 memerlukannya secara eksplisit. Meskipun ini terlihat seperti penyesuaian kecil, template Jinja lebih andal karena Anda dapat meneruskan argumen dalam panggilan.

Di Django, Anda harus membuat "tag template" atau menulis filter. Dengan pemahaman ini, perbarui index.html dengan menambahkan sepasang tanda kurung ke panggilan visit.timestamp.ctime:

  • SEBELUM:
<li>{{ visit.timestamp.ctime }} from {{ visit.visitor }}</li>
  • SETELAH:
<li>{{ visit.timestamp.ctime() }} from {{ visit.visitor }}</li>

Ini adalah satu-satunya perubahan yang diperlukan; tidak diperlukan perubahan tambahan pada index.html untuk semua codelab migrasi yang tersisa.

Deploy aplikasi

Setelah menyelesaikan semua perubahan dalam tutorial ini, file dalam folder aplikasi Anda harus sama (atau hampir sama) dengan file dalam folder repo Modul 1. Sekarang deploy dan lihat apakah aplikasi Modul 1 Flask Anda berjalan sama persis dengan versi webapp2 Modul 0.

Gunakan perintah gcloud app deploy seperti yang kita lakukan sebelumnya saat men-deploy kode Modul 0 asli. Mengakses aplikasi di PROJECT_ID.appspot.com, baik dari browser web atau perintah curl maupun wget untuk mengonfirmasi bahwa aplikasi berfungsi seperti yang diharapkan.

Jika Anda menerima beberapa jenis error server, biasanya ada salah ketik di kode Python Anda. Lihat log aplikasi Anda untuk menginvestigasi. Bandingkan juga file Anda dengan file di repositori Modul 1 (link tepat di atas).

Opsional: Pembersihan

Bagaimana dengan pembersihan agar tidak ditagih hingga Anda siap untuk beralih ke codelab migrasi berikutnya? Sebagai developer yang sudah ada, Anda mungkin sudah mengetahui yang terbaru tentang informasi harga App Engine.

Opsional: Nonaktifkan aplikasi

Jika Anda belum siap melanjutkan ke tutorial berikutnya, nonaktifkan aplikasi untuk menghindari tagihan. Jika sudah siap untuk beralih ke codelab berikutnya, Anda dapat mengaktifkannya kembali. Meskipun dinonaktifkan, aplikasi tidak akan mendapatkan traffic yang dikenakan biaya, namun hal lain yang dapat ditagih adalah penggunaan Datastore jika melebihi kuota gratis, jadi cukup hapus hingga berada di bawah batas tersebut.

Di sisi lain, jika Anda tidak akan melanjutkan migrasi dan ingin menghapus semuanya, Anda dapat mematikan project.

Langkah berikutnya

Ada dua modul migrasi yang dilengkapi dengan kode Modul 1 lengkap, Modul 2 dan 7:

  • Modul 2 (diperlukan jika Anda menggunakan Datastore)
    • Migrasikan dari ndb App Engine ke Cloud NDB
    • Setelah beralih ke Cloud NDB, banyak opsi lain yang tersedia
      • Mem-build aplikasi Anda dalam container untuk dijalankan di Cloud Run
      • Selanjutnya, memigrasikan aplikasi Anda ke library klien Cloud Datastore
      • Memigrasikan aplikasi ke Cloud Firestore untuk mengakses fitur Firebase
  • Modul 7 (diperlukan jika Anda menggunakan Task Queue [push])
    • Tambahkan penggunaan taskqueue App Engine (push)
    • Siapkan aplikasi Modul 1 untuk migrasi ke Cloud Tasks di Modul 8

Masalah/masukan codelab modul migrasi App Engine

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

Resource migrasi

Link ke folder repo untuk Modul 0 (START) dan Modul 1 (FINISH) dapat ditemukan pada tabel di bawah. Link tersebut juga dapat diakses dari repo untuk semua migrasi App Engine yang dapat Anda clone atau download file ZIP.

Codelab

Python 2

Python 3

Modul 0

kode

(T/A)

Modul 1

kode

(T/A)

Resource App Engine

Berikut adalah resource tambahan terkait migrasi khusus ini: