Terjemahan disediakan oleh mesin penerjemah. Jika konten terjemahan yang diberikan bertentangan dengan versi bahasa Inggris aslinya, utamakan versi bahasa Inggris.
Memecahkan masalah konfigurasi di Lambda
Pengaturan konfigurasi fungsi Anda dapat berdampak pada kinerja dan perilaku fungsi Lambda secara keseluruhan. Ini mungkin tidak menyebabkan kesalahan fungsi yang sebenarnya, tetapi dapat menyebabkan batas waktu dan hasil yang tidak terduga.
Topik berikut memberikan saran pemecahan masalah untuk masalah umum yang mungkin Anda temui terkait pengaturan konfigurasi fungsi Lambda.
Topik
Konfigurasi memori
Anda dapat mengonfigurasi fungsi Lambda untuk menggunakan memori antara 128 MB dan 10.240 MB. Secara default, fungsi apa pun yang dibuat di konsol diberi jumlah memori terkecil. Banyak fungsi Lambda berkinerja pada pengaturan terendah ini. Namun, jika Anda mengimpor pustaka kode besar atau menyelesaikan tugas intensif memori, 128 MB tidak cukup.
Jika fungsi Anda berjalan jauh lebih lambat dari yang diharapkan, langkah pertama adalah meningkatkan pengaturan memori. Untuk fungsi yang terikat memori, ini menyelesaikan hambatan dan mungkin meningkatkan kinerja fungsi Anda.
CPU-bound konfigurasi
Untuk operasi intensif komputasi, jika fungsi Anda mengalami kinerja yang lebih lambat dari yang diharapkan, ini mungkin karena fungsi Anda. CPU-bound Dalam hal ini, kapasitas komputasi fungsi tidak dapat mengimbangi pekerjaan.
Sementara Lambda tidak memungkinkan Anda untuk memodifikasi konfigurasi CPU secara langsung, CPU secara tidak langsung dikendalikan melalui pengaturan memori. Layanan Lambda secara proporsional mengalokasikan lebih banyak CPU virtual saat Anda mengalokasikan lebih banyak memori. Pada memori 1, 8 GB, fungsi Lambda memiliki seluruh vCPU yang dialokasikan, dan di atas level ini ia memiliki akses ke lebih dari satu inti vCPU. Pada 10.240MB, ia memiliki 6 vCPU yang tersedia. Dengan kata lain, Anda dapat meningkatkan kinerja dengan meningkatkan alokasi memori, bahkan jika fungsi tersebut tidak menggunakan semua memori.
Waktu habis
Waktu hab is untuk fungsi Lambda dapat diatur antara 1 dan 900 detik (15 menit). Secara default, konsol Lambda menyetel ini menjadi 3 detik. Nilai batas waktu adalah katup pengaman yang memastikan fungsi tidak berjalan tanpa batas waktu. Setelah nilai batas waktu tercapai, Lambda menghentikan pemanggilan fungsi.
Jika nilai batas waktu ditetapkan mendekati durasi rata-rata suatu fungsi, ini meningkatkan risiko waktu fungsi habis secara tidak terduga. Durasi fungsi dapat bervariasi berdasarkan jumlah transfer dan pemrosesan data, dan latensi layanan apa pun yang berinteraksi dengan fungsi tersebut. Penyebab umum batas waktu meliputi:
-
Saat mengunduh data dari bucket S3 atau penyimpanan data lainnya, unduhan lebih besar atau membutuhkan waktu lebih lama dari rata-rata.
-
Suatu fungsi membuat permintaan ke layanan lain, yang membutuhkan waktu lebih lama untuk merespons.
-
Parameter yang disediakan untuk suatu fungsi memerlukan lebih banyak kompleksitas komputasi dalam fungsi, yang menyebabkan pemanggilan memakan waktu lebih lama.
Saat menguji aplikasi Anda, pastikan pengujian Anda secara akurat mencerminkan ukuran dan kuantitas data, serta nilai parameter yang realistis. Yang penting, gunakan kumpulan data di batas atas dari apa yang diharapkan secara wajar untuk beban kerja Anda.
Selain itu, terapkan batas batas atas dalam beban kerja Anda di mana pun praktis. Dalam contoh ini, aplikasi dapat menggunakan batas ukuran maksimum untuk setiap jenis file. Anda kemudian dapat menguji kinerja aplikasi Anda untuk berbagai ukuran file yang diharapkan, hingga dan termasuk batas maksimum.
Kebocoran memori antara pemanggilan
Variabel global dan objek yang disimpan dalam fase INIT dari pemanggilan Lambda mempertahankan statusnya di antara pemanggilan hangat. Mereka sepenuhnya diatur ulang hanya ketika lingkungan eksekusi dijalankan untuk pertama kalinya (juga dikenal sebagai “start dingin”). Setiap variabel yang disimpan dalam handler dihancurkan saat handler keluar. Praktik terbaik adalah menggunakan fase INIT untuk mengatur koneksi database, memuat pustaka, membuat cache, dan memuat aset yang tidak dapat diubah.
Saat Anda menggunakan pustaka pihak ketiga di beberapa pemanggilan di lingkungan eksekusi yang sama, periksa dokumentasinya untuk digunakan di lingkungan komputasi tanpa server. Beberapa koneksi database dan pustaka logging mungkin menyimpan hasil pemanggilan menengah dan data lainnya. Hal ini menyebabkan penggunaan memori perpustakaan ini tumbuh dengan pemanggilan hangat berikutnya. Jika ini masalahnya, Anda mungkin menemukan fungsi Lambda kehabisan memori, bahkan jika kode khusus Anda membuang variabel dengan benar.
Masalah ini memengaruhi pemanggilan yang terjadi di lingkungan eksekusi yang hangat. Misalnya, kode berikut membuat kebocoran memori di antara pemanggilan. Fungsi Lambda mengkonsumsi memori tambahan dengan setiap pemanggilan dengan meningkatkan ukuran array global:
let a = []
exports.handler = async (event) => {
a.push(Array(100000).fill(1))
}
Dikonfigurasi dengan memori 128 MB, setelah memanggil fungsi ini 1000 kali, tab Pem antauan fungsi Lambda menunjukkan perubahan khas dalam pemanggilan, durasi, dan jumlah kesalahan ketika kebocoran memori terjadi:
-
Pemanggilan — Tingkat transaksi yang stabil terganggu secara berkala karena pemanggilan membutuhkan waktu lebih lama untuk diselesaikan. Selama kondisi mapan, kebocoran memori tidak menghabiskan semua memori yang dialokasikan fungsi. Ketika kinerja menurun, sistem operasi paging penyimpanan lokal untuk mengakomodasi memori yang berkembang yang diperlukan oleh fungsi, yang menghasilkan lebih sedikit transaksi yang diselesaikan.
-
Durasi — Sebelum fungsi kehabisan memori, ia menyelesaikan pemanggilan pada kecepatan milidetik dua digit yang stabil. Saat paging terjadi, durasinya membutuhkan waktu lebih lama.
-
Jumlah kesalahan - Karena kebocoran memori melebihi memori yang dialokasikan, akhirnya kesalahan fungsi karena perhitungan melebihi batas waktu, atau lingkungan eksekusi menghentikan fungsi.
Setelah kesalahan, Lambda memulai ulang lingkungan eksekusi, yang menjelaskan mengapa ketiga grafik menunjukkan kembali ke keadaan semula. Memperluas CloudWatch metrik untuk durasi memberikan detail lebih lanjut untuk statistik durasi minimum, maksimum, dan rata-rata:
Untuk menemukan kesalahan yang dihasilkan di 1000 pemanggilan, Anda dapat menggunakan bahasa kueri In CloudWatch sights. Kueri berikut mengecualikan log informasi untuk melaporkan hanya kesalahan:
fields @timestamp, @message | sort @timestamp desc | filter @message not like 'EXTENSION' | filter @message not like 'Lambda Insights' | filter @message not like 'INFO' | filter @message not like 'REPORT' | filter @message not like 'END' | filter @message not like 'START'
Ketika dijalankan terhadap grup log untuk fungsi ini, ini menunjukkan bahwa batas waktu bertanggung jawab atas kesalahan periodik:
Hasil asinkron dikembalikan ke pemanggilan selanjutnya
Untuk kode fungsi yang menggunakan pola asinkron, dimungkinkan hasil panggilan balik dari satu pemanggilan dikembalikan dalam pemanggilan mendatang. Contoh ini menggunakan Node.js, tetapi logika yang sama dapat diterapkan ke runtime lain menggunakan pola asinkron. Fungsi ini menggunakan sintaks callback tradisional di JavaScript. Ini memanggil fungsi asinkron dengan penghitung inkremental yang melacak jumlah pemanggilan:
let seqId = 0 exports.handler = async (event, context) => { console.log(`Starting: sequence Id=${++seqId}`) doWork(seqId, function(id) { console.log(`Work done: sequence Id=${id}`) }) } function doWork(id, callback) { setTimeout(() => callback(id), 3000) }
Ketika dipanggil beberapa kali berturut-turut, hasil panggilan balik terjadi pada pemanggilan berikutnya:
-
Kode memanggil
doWorkfungsi, menyediakan fungsi callback sebagai parameter terakhir. -
doWorkFungsi ini membutuhkan beberapa periode waktu untuk diselesaikan sebelum memanggil callback. -
Logging fungsi menunjukkan bahwa pemanggilan berakhir sebelum
doWorkfungsi selesai eksekusi. Selain itu, setelah memulai iterasi, callback dari iterasi sebelumnya sedang diproses, seperti yang ditunjukkan dalam log.
Di JavaScript, panggilan balik asinkron ditangani dengan loop peristiwa.
Setelah dil JavaScript anjutkan, lanjutkan memproses loop peristiwa, yang dalam hal ini mencakup panggilan balik asinkron dari pemanggilan sebelumnya. Tanpa konteks ini, dapat tampak bahwa fungsi menjalankan kode tanpa alasan, dan mengembalikan data sewenang-wenang. Faktanya, ini benar-benar artefak tentang bagaimana konkurensi runtime dan lingkungan eksekusi berinteraksi.
Ini menciptakan potensi data pribadi dari pemanggilan sebelumnya untuk muncul dalam pemanggilan berikutnya. Ada dua cara untuk mencegah atau mendeteksi perilaku ini. Pertama, JavaScript menyediakan kata kunci async dan wait
let seqId = 0 exports.handler = async (event) => { console.log(`Starting: sequence Id=${++seqId}`) const result = await doWork(seqId) console.log(`Work done: sequence Id=${result}`) } function doWork(id) { return new Promise(resolve => { setTimeout(() => resolve(id), 4000) }) }
Menggunakan sintaks ini mencegah handler keluar sebelum fungsi asinkron selesai. Dalam hal ini, jika panggilan balik membutuhkan waktu lebih lama dari batas waktu fungsi Lambda, fungsi akan menimbulkan kesalahan, alih-alih mengembalikan hasil panggilan balik dalam pemanggilan selanjutnya:
-
Kode memanggil
doWorkfungsi asinkron menggunakan kata kunci wait di handler. -
doWorkFungsi ini membutuhkan beberapa periode waktu untuk diselesaikan sebelum menyelesaikan janji. -
Fungsi habis waktu karena
doWorkmembutuhkan waktu lebih lama dari batas waktu tunggu yang memungkinkan dan hasil panggilan balik tidak dikembalikan dalam pemanggilan selanjutnya.
Umumnya, Anda harus memastikan setiap proses latar belakang atau panggilan balik dalam kode selesai sebelum kode keluar. Jika ini tidak memungkinkan dalam kasus penggunaan Anda, Anda dapat menggunakan pengenal untuk memastikan bahwa panggilan balik milik pemanggilan saat ini. Untuk melakukan ini, Anda dapat menggunakan aws RequestId yang disediakan oleh objek konteks. Dengan meneruskan nilai ini ke callback asinkron, Anda dapat membandingkan nilai yang diteruskan dengan nilai saat ini untuk mendeteksi apakah panggilan balik berasal dari pemanggilan lain:
let currentContext exports.handler = async (event, context) => { console.log(`Starting: request id=$\{context.awsRequestId}`) currentContext = context doWork(context.awsRequestId, function(id) { if (id != currentContext.awsRequestId) { console.info(`This callback is from another invocation.`) } }) } function doWork(id, callback) { setTimeout(() => callback(id), 3000) }
-
Handler fungsi Lambda mengambil parameter konteks, yang menyediakan akses ke ID permintaan pemanggilan unik.
-
Ini
awsRequestIdditeruskan ke fungsi DoWork. Dalam panggilan balik, ID dibandingkan denganawsRequestIdpemanggilan saat ini. Jika nilai-nilai ini berbeda, kode dapat mengambil tindakan yang sesuai.