Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Saat mengembangkan untuk Azure Functions menggunakan Python, Anda perlu memahami performa fungsi Anda dan bagaimana performa tersebut memengaruhi cara aplikasi fungsi Anda diskalakan. Kebutuhan lebih penting saat merancang aplikasi dengan performa tinggi. Faktor utama yang perlu dipertimbangkan saat merancang, menulis, dan mengonfigurasi aplikasi fungsi Anda adalah penskalaan horizontal dan konfigurasi performa throughput.
Skala horizontal
Secara default, Azure Functions secara otomatis memantau beban pada aplikasi Anda dan membuat lebih banyak instans host untuk Python sesuai kebutuhan. Azure Functions menggunakan batasan bawaan untuk tipe pemicu yang berbeda untuk menentukan kapan harus menambahkan instans, seperti usia pesan dan ukuran antrean untuk QueueTrigger. Ambang batas ini tidak dapat dikonfigurasi pengguna. Untuk informasi selengkapnya, lihat penskalaan berbasis Event di Azure Functions.
Meningkatkan kinerja throughput
Konfigurasi default cocok untuk sebagian besar aplikasi Azure Functions. Namun, Anda dapat meningkatkan performa throughput aplikasi dengan menggunakan konfigurasi berdasarkan profil beban kerja Anda. Langkah pertama adalah memahami jenis beban kerja yang Anda jalankan.
| Tipe beban kerja | Karakteristik fungsi aplikasi | Contoh |
|---|---|---|
| tergantung I/O | • Aplikasi perlu menangani banyak pemanggilan bersamaan. • Aplikasi memproses sejumlah besar peristiwa I/O, seperti panggilan jaringan dan baca/tulis disk. |
• API Web |
| terikat CPU | • Aplikasi melakukan komputasi jangka panjang, seperti mengubah ukuran gambar. • Aplikasi melakukan transformasi data. |
• Pemrosesan data • Inferensi pembelajaran mesin |
Karena beban kerja fungsi dunia nyata biasanya merupakan campuran I/O dan terikat CPU, Anda harus memprofilkan aplikasi di bawah beban produksi yang realistis.
Konfigurasi khusus kinerja
Setelah Anda memahami profil beban kerja aplikasi fungsi Anda, berikut ini adalah konfigurasi yang dapat Anda gunakan untuk meningkatkan performa throughput fungsi Anda.
- Asinkron
- Pekerja dengan kemampuan multibahasa
- Jumlah pekerja maksimum dalam proses pekerja bahasa
- Event loop
- Skalabilitas Vertikal
Asinkron
Karena Python adalah runtime berulir tunggal, instans host untuk Python hanya dapat memproses satu pemanggilan fungsi pada satu waktu secara default. Untuk aplikasi yang memproses sejumlah besar peristiwa I/O dan/atau terikat I/O, Anda dapat meningkatkan performa secara signifikan dengan menjalankan fungsi secara asinkron.
Untuk menjalankan fungsi secara asinkron, gunakan pernyataan async def, yang menjalankan fungsi dengan asyncio secara langsung:
async def main():
await some_nonblocking_socket_io_op()
Berikut adalah contoh fungsi dengan pemicu HTTP yang menggunakan klien http aiohttp :
import aiohttp
import azure.functions as func
async def main(req: func.HttpRequest) -> func.HttpResponse:
async with aiohttp.ClientSession() as client:
async with client.get("PUT_YOUR_URL_HERE") as response:
return func.HttpResponse(await response.text())
return func.HttpResponse(body='NotFound', status_code=404)
Fungsi tanpa async kata kunci dijalankan secara otomatis di kumpulan utas ThreadPoolExecutor:
# Runs in a ThreadPoolExecutor threadpool. Number of threads is defined by PYTHON_THREADPOOL_THREAD_COUNT.
# The example is intended to show how default synchronous functions are handled.
def main():
some_blocking_socket_io()
Untuk mencapai manfaat penuh dari menjalankan fungsi secara asinkron, operasi/pustaka I/O yang digunakan dalam kode Anda juga harus memiliki asinkron yang diimplementasikan. Menggunakan operasi I/O sinkron dalam fungsi yang didefinisikan sebagai asinkron dapat merusak performa keseluruhan. Jika pustaka yang Anda gunakan tidak memiliki versi asinkron yang diterapkan, Anda mungkin masih mendapat manfaat dari menjalankan kode secara asinkron dengan mengelola perulangan peristiwa di aplikasi Anda.
Berikut adalah beberapa contoh pustaka klien yang telah menerapkan pola asinkron:
- aiohttp - Klien/server HTTP untuk asyncio
- Streams API - Primitif asinkron/siap tunggu tingkat tinggi untuk bekerja dengan koneksi jaringan
- Janus Queue - Antrean asinkio aman utas untuk Python
- pyzmq - Python pengikatan untuk ZeroMQ
Memahami asinkron di pekerja Python
Ketika Anda menulis async di depan tanda tangan fungsi, Python menandai fungsi tersebut sebagai korutin. Saat Anda memanggil coroutine, coroutine tersebut dapat dijadwalkan sebagai tugas dalam lingkaran peristiwa. Ketika Anda memanggil await dalam fungsi asinkron, ia mendaftarkan kelanjutan ke dalam perulangan peristiwa, yang memungkinkan perulangan peristiwa untuk memproses tugas berikutnya selama waktu tunggu.
Dalam Python Worker kami, pekerja berbagi perulangan peristiwa dengan fungsi async pelanggan dan mampu menangani beberapa permintaan secara bersamaan. Kami sangat mendorong pelanggan kami untuk menggunakan pustaka yang kompatibel dengan asyncio, seperti aiohttp dan pyzmq. Mengikuti rekomendasi ini meningkatkan throughput fungsi Anda dibandingkan dengan pustaka tersebut saat diimplementasikan secara sinkron.
Nota
Jika fungsi Anda dinyatakan sebagai async tanpa await di dalam implementasinya, performa fungsi Anda akan sangat terpengaruh karena perulangan peristiwa akan diblokir yang melarang pekerja Python menangani permintaan bersamaan.
Gunakan beberapa proses pekerja pemrosesan bahasa
Secara default, setiap instans host Azure Functions memiliki satu proses pekerja bahasa pemrograman. Anda dapat meningkatkan jumlah proses pekerja per host (hingga 10) dengan menggunakan pengaturan aplikasi FUNCTIONS_WORKER_PROCESS_COUNT. Azure Functions kemudian mencoba mendistribusikan pemanggilan fungsi simultan secara merata di seluruh pekerja ini.
Untuk aplikasi terikat CPU, Anda harus mengatur jumlah pekerja bahasa agar sama dengan atau lebih tinggi dari jumlah inti yang tersedia per aplikasi fungsi. Untuk mempelajari lebih lanjut, lihat SKU instans yang tersedia.
Aplikasi yang terikat I/O mungkin juga mendapat manfaat dengan menambah jumlah proses kerja melebihi jumlah inti yang tersedia. Perlu diingat bahwa mengatur jumlah pekerja yang terlalu tinggi dapat memengaruhi performa keseluruhan karena peningkatan jumlah pengalihan konteks yang diperlukan.
FUNCTIONS_WORKER_PROCESS_COUNT berlaku untuk setiap host yang Azure Functions buat saat menskalakan aplikasi Anda untuk memenuhi permintaan.
Mengatur pekerja maksimal dalam proses pekerja bahasa
Seperti disebutkan dalam bagian asinkron section, pengolah bahasa Python memperlakukan fungsi dan coroutines secara berbeda. Koroutine dijalankan dalam perulangan peristiwa yang sama dengan yang dijalankan pekerja bahasa. Di sisi lain, pemanggilan fungsi dijalankan dalam ThreadPoolExecutor, yang dikelola oleh pekerja bahasa dalam bentuk utas.
Anda dapat mengatur nilai pekerja maksimum yang diizinkan untuk menjalankan fungsi sinkronisasi menggunakan pengaturan aplikasi PYTHON_THREADPOOL_THREAD_COUNT . Nilai ini mengatur argumen max_worker objek ThreadPoolExecutor, yang memungkinkan Python menggunakan kumpulan paling banyak utas max_worker untuk menjalankan panggilan secara asinkron.
PYTHON_THREADPOOL_THREAD_COUNT berlaku untuk setiap utas yang dibuat oleh host Functions, dan Python memutuskan kapan harus membuat utas baru atau menggunakan kembali utas menganggur yang ada. Untuk versi Python yang lebih lama(yaitu, 3.8, 3.7, dan 3.6), nilai max_worker diatur ke 1. Untuk versi Python 3.9 , max_worker diatur ke None.
Untuk aplikasi yang terikat CPU, Anda harus menjaga pengaturan ke angka rendah, mulai dari 1 dan meningkat saat Anda bereksperimen dengan beban kerja Anda. Saran ini untuk mengurangi waktu yang dihabiskan pada pergantian konteks dan memungkinkan tugas yang berat pada CPU selesai.
Untuk aplikasi terikat I/O, Anda akan melihat keuntungan besar dengan meningkatkan jumlah utas yang bekerja pada setiap pemanggilan. Rekomendasinya adalah memulai dengan default Python (jumlah inti) + 4 lalu mengubah berdasarkan nilai throughput yang Anda lihat.
Untuk aplikasi beban kerja campuran, Anda harus menyeimbangkan konfigurasi FUNCTIONS_WORKER_PROCESS_COUNT dan PYTHON_THREADPOOL_THREAD_COUNT untuk memaksimalkan throughput. Untuk memahami apa yang paling sering dihabiskan oleh aplikasi fungsi Anda, sebaiknya profilkan dan atur nilai sesuai dengan perilakunya. Untuk mempelajari tentang pengaturan aplikasi ini, lihat Gunakan beberapa proses pekerja berganda.
Nota
Meskipun rekomendasi ini berlaku untuk fungsi yang dipicu HTTP dan non-HTTP, Anda mungkin perlu menyesuaikan konfigurasi khusus pemicu lainnya untuk fungsi yang dipicu non-HTTP untuk mendapatkan performa yang diharapkan dari aplikasi fungsi Anda. Untuk informasi selengkapnya tentang ini, silakan lihat praktik terbaik untuk Azure Functions yang andal.
Mengelola perulangan peristiwa
Anda harus menggunakan pustaka pihak ketiga yang kompatibel dengan asyncio. Jika tidak ada pustaka pihak ketiga yang memenuhi kebutuhan Anda, Anda juga dapat mengelola perulangan peristiwa di Azure Functions. Mengelola event loop memberi Anda lebih banyak fleksibilitas dalam manajemen sumber daya komputasi, dan juga memungkinkan pembungkusan pustaka I/O yang sinkron menjadi koroutin.
Ada banyak dokumen resmi Python berguna yang membahas Coroutines and Tasks dan Event Loop dengan menggunakan pustaka asyncio bawaan.
Ambil pustaka requests berikut sebagai contoh, cuplikan kode ini menggunakan pustaka asyncio untuk membungkus requests.get() method ke dalam korutin, menjalankan beberapa permintaan web untuk SAMPLE_URL secara bersamaan.
import asyncio
import json
import logging
import azure.functions as func
from time import time
from requests import get, Response
async def invoke_get_request(eventloop: asyncio.AbstractEventLoop) -> Response:
# Wrap requests.get function into a coroutine
single_result = await eventloop.run_in_executor(
None, # using the default executor
get, # each task call invoke_get_request
'SAMPLE_URL' # the url to be passed into the requests.get function
)
return single_result
async def main(req: func.HttpRequest) -> func.HttpResponse:
logging.info('Python HTTP trigger function processed a request.')
eventloop = asyncio.get_event_loop()
# Create 10 tasks for requests.get synchronous call
tasks = [
asyncio.create_task(
invoke_get_request(eventloop)
) for _ in range(10)
]
done_tasks, _ = await asyncio.wait(tasks)
status_codes = [d.result().status_code for d in done_tasks]
return func.HttpResponse(body=json.dumps(status_codes),
mimetype='application/json')
Skalabilitas Vertikal
Anda mungkin bisa mendapatkan lebih banyak unit pemrosesan, terutama dalam operasi terikat CPU, dengan meningkatkan ke paket premium dengan spesifikasi yang lebih tinggi. Dengan unit pemrosesan yang lebih tinggi, Anda dapat menyesuaikan jumlah jumlah proses pekerja sesuai dengan jumlah inti yang tersedia dan mencapai tingkat paralelisme yang lebih tinggi.
Langkah selanjutnya
Untuk informasi selengkapnya tentang pengembangan Azure Functions Python, lihat sumber daya berikut ini: