Panduan ini menjelaskan pengoptimalan untuk layanan Cloud Run yang ditulis dalam bahasa pemrograman Python, beserta informasi latar belakang untuk membantu Anda memahami kompromi yang terlibat pada beberapa pengoptimalan. Informasi di halaman ini melengkapi tips pengoptimalan umum, yang juga berlaku pada Python.
Sebagian besar praktik terbaik dan pengoptimalan dalam aplikasi berbasis web Python tradisional ini berkisar tentang:
- Menangani permintaan serentak (baik I/O yang berbasis thread maupun yang tidak memblokir)
- Mengurangi latensi respons menggunakan penggabungan koneksi dan mengelompokkan fungsi yang tidak penting. Misalnya, mengirim trace dan metrik ke tugas latar belakang.
Mengoptimalkan image container
Dengan mengoptimalkan image container, Anda dapat mengurangi waktu pemuatan dan startup. Anda dapat mengoptimalkan image dengan:
- Hanya memasukkan ke dalam penampung apa yang dibutuhkan aplikasi Anda saat runtime
- Mengoptimalkan server WSGI
Hanya masukkan ke dalam penampung yang diperlukan aplikasi Anda saat runtime
Pertimbangkan komponen mana yang disertakan dalam penampung, dan apakah komponen tersebut diperlukan untuk eksekusi layanan. Ada beberapa cara untuk meminimalkan image container:
- Menggunakan image dasar yang lebih kecil
- Memindahkan file besar ke luar penampung
Menggunakan image dasar yang lebih kecil
Docker Hub menyediakan sejumlah image dasar Python resmi yang dapat Anda gunakan, jika Anda memilih untuk tidak menginstal Python dari sumber dalam container. Server ini didasarkan pada sistem operasi Debian.
Jika Anda menggunakan image python
Docker Hub, pertimbangkan untuk menggunakan versi slim
.
Ukuran image ini lebih kecil karena tidak dilengkapi dengan sejumlah
paket yang akan digunakan untuk mem-build wheel, misalnya, yang mungkin tidak perlu
Anda lakukan untuk aplikasi Anda. Misalnya, image python dilengkapi dengan compiler,
preprocessor, dan utilitas inti GNU C.
Untuk mengidentifikasi sepuluh paket terbesar dalam image dasar, Anda dapat menjalankan perintah berikut:
DOCKER_IMAGE=python # or python:slim
docker run --rm ${DOCKER_IMAGE} dpkg-query -Wf '${Installed-Size}\t${Package}\t${Description}\n' | sort -n | tail -n10 | column -t -s $'\t'
Karena paket tingkat rendah ini lebih sedikit, image berbasis slim
juga menawarkan lebih sedikit platform serangan untuk potensi kerentanan. Perhatikan bahwa image ini
mungkin tidak menyertakan elemen yang diperlukan untuk mem-build wheel dari sumber.
Anda dapat menambahkan kembali paket tertentu dengan menambahkan baris RUN apt install
ke Dockerfile. Lihat selengkapnya tentang cara menggunakan Paket Sistem di Cloud Run.
Ada juga opsi untuk penampung non-Debian. Opsi python:alpine
mungkin menghasilkan penampung yang jauh lebih kecil, tetapi banyak paket Python mungkin tidak
memiliki wheel yang telah dikompilasi sebelumnya yang mendukung sistem berbasis alpine. Dukungan terus ditingkatkan
(lihat PEP-656), tetapi terus
bervariasi. Anda juga dapat mempertimbangkan untuk menggunakan
distroless base image
,
yang tidak berisi pengelola paket, shell, atau program lainnya.
Memindahkan file besar ke luar penampung
File besar, seperti aset media, dll., tidak perlu disertakan dalam penampung dasar.
Google Cloud menawarkan beberapa opsi hosting, seperti Cloud Storage, untuk menyimpan item besar ini. Pindahkan aset besar ke layanan ini, lalu referensikan dari aplikasi Anda pada waktu proses.
Mengoptimalkan server WSGI
Python telah menstandarkan cara aplikasi dapat berinteraksi dengan server web
dengan penerapan standar WSGI,
PEP-3333. Salah satu server WSGI yang lebih umum adalah gunicorn
, yang digunakan di sebagian besar dokumentasi contoh.
Mengoptimalkan gunicorn
Tambahkan CMD
berikut ke Dockerfile
untuk mengoptimalkan pemanggilan
gunicorn
:
CMD exec gunicorn --bind :$PORT --workers 1 --threads 8 --timeout 0 main:app
Jika Anda mempertimbangkan untuk mengubah setelan ini, sesuaikan jumlah pekerja dan thread berdasarkan per aplikasi. Misalnya, coba gunakan sejumlah pekerja yang sama dengan core yang tersedia dan pastikan ada peningkatan performa, lalu sesuaikan jumlah thread. Menetapkan terlalu banyak pekerja atau thread dapat memiliki dampak negatif, seperti latensi cold start yang lebih lama, lebih banyak memori yang digunakan, permintaan yang lebih kecil per detik, dll.
Secara default, gunicorn
membuat pekerja dan memproses port yang ditentukan saat
memulai, bahkan sebelum mengevaluasi kode aplikasi Anda. Dalam hal ini, Anda
harus menyiapkan pemeriksaan startup kustom
untuk layanan Anda, karena pemeriksaan startup default Cloud Run segera menandai
instance container sebagai responsif segera setelah mulai memproses di $PORT
.
Jika ingin mengubah perilaku ini, Anda dapat memanggil gunicorn
dengan
setelan --preload
untuk mengevaluasi kode aplikasi sebelum memproses. Hal ini dapat membantu:
- Mengidentifikasi bug runtime serius pada waktu deployment
- Menghemat resource memori
Anda harus mempertimbangkan apa yang dimuat sebelumnya oleh aplikasi sebelum menambahkannya.
Server WSGI lainnya
Anda tidak dibatasi untuk menggunakan gunicorn
untuk menjalankan Python dalam container.
Anda dapat menggunakan server web WSGI atau ASGI apa pun, selama penampung memproses
$PORT
port HTTP, sesuai dengan
Kontrak runtime penampung.
Alternatif umum mencakup uwsgi
,
uvicorn
,
dan waitress
.
Misalnya, file bernama main.py
yang berisi objek app
, pemanggilan berikut akan memulai server WSGI:
# uwsgi: pip install pyuwsgi
uwsgi --http :$PORT -s /tmp/app.sock --manage-script-name --mount /app=main:app
# uvicorn: pip install uvicorn
uvicorn --port $PORT --host 0.0.0.0 main:app
# waitress: pip install waitress
waitress-serve --port $PORT main:app
Ini dapat ditambahkan sebagai baris CMD exec
di Dockerfile
, atau sebagai entri web:
di Procfile
saat menggunakan buildpack Google Cloud.
Mengoptimalkan aplikasi
Dalam kode layanan Cloud Run, Anda juga dapat mengoptimalkan waktu startup dan penggunaan memori yang lebih cepat.
Mengurangi thread
Anda dapat mengoptimalkan memori dengan mengurangi jumlah thread, yaitu dengan cara menggunakan strategi reaktif yang tidak memblokir dan menghindari aktivitas latar belakang. Selain itu, hindari menulis ke sistem file, seperti yang disebutkan di halaman tips umum.
Jika Anda ingin mendukung aktivitas latar belakang di layanan Cloud Run, setel CPU layanan Cloud Run agar selalu dialokasikan. Hal ini memungkinkan Anda menjalankan aktivitas latar belakang di luar permintaan dan tetap memiliki akses CPU.
Mengurangi tugas startup
Aplikasi berbasis web Python dapat memiliki banyak tugas untuk diselesaikan selama startup, misalnya, pramuat data, pemanasan cache, pembuatan kumpulan koneksi, dll. Tugas ini menjadi lambat saat dijalankan secara berurutan. Namun, jika ingin dijalankan secara paralel, Anda harus meningkatkan jumlah core CPU.
Cloud Run saat ini mengirimkan permintaan pengguna yang sebenarnya untuk memicu instance cold start. Pengguna yang memiliki permintaan ditetapkan ke instance yang baru dimulai mungkin akan mengalami penundaan yang lama. Cloud Run saat ini tidak memiliki pemeriksaan "kesiapan" untuk menghindari pengiriman permintaan ke aplikasi yang belum siap.
Langkah selanjutnya
Untuk tips lainnya, lihat