Rumah >hujung hadapan web >tutorial js >Pendikitan Dijelaskan: Panduan Mengurus Had Permintaan API
Untuk projek besar, biasanya lebih baik menggunakan alatan seperti Pengehadan Kadar Cloudflare atau HAProxy. Ini berkuasa, boleh dipercayai dan menjaga angkat berat untuk anda.
Tetapi untuk projek yang lebih kecil—atau jika anda ingin mengetahui cara sesuatu berfungsi—anda boleh membuat pengehad kadar anda sendiri terus dalam kod anda. Kenapa?
Menjelang penghujung panduan ini, anda akan tahu cara membina pendikit asas dalam TypeScript untuk melindungi API anda daripada tertekan. Inilah perkara yang akan kami bincangkan:
Panduan ini direka bentuk untuk menjadi titik permulaan yang praktikal, sesuai untuk pembangun yang ingin mempelajari asas tanpa kerumitan yang tidak perlu. Tetapi ia belum siap pengeluaran.
Sebelum bermula, saya ingin memberikan kredit yang betul kepada bahagian Had Kadar Lucia.
Mari kita tentukan kelas Throttler:
export class Throttler { private storage = new Map<string, ThrottlingCounter>(); constructor(private timeoutSeconds: number[]) {} }
Pembina Throttler menerima senarai tempoh tamat masa (timeoutSeconds). Setiap kali pengguna disekat, tempoh meningkat secara progresif berdasarkan senarai ini. Akhirnya, apabila tamat masa terakhir dicapai, anda malah boleh mencetuskan panggilan balik untuk melarang IP pengguna secara kekal—walaupun itu di luar skop panduan ini.
Berikut ialah contoh mencipta tika pendikit yang menyekat pengguna untuk meningkatkan selang:
const throttler = new Throttler([1, 2, 4, 8, 16]);
Acara ini akan menyekat pengguna buat kali pertama selama satu saat. Kali kedua untuk dua orang, dan seterusnya.
Kami menggunakan Peta untuk menyimpan alamat IP dan data yang sepadan. Peta sesuai kerana ia mengendalikan penambahan dan pemadaman yang kerap dengan cekap.
Petua Pro: Gunakan Peta untuk data dinamik yang kerap berubah. Untuk data statik, tidak berubah, objek adalah lebih baik. (Lubang arnab 1)
Apabila titik akhir anda menerima permintaan, ia mengekstrak alamat IP pengguna dan merujuk kepada Pendikit untuk menentukan sama ada permintaan itu harus dibenarkan.
Kes A: Pengguna Baharu atau Tidak Aktif
Jika IP tidak ditemui dalam Throttler, ini sama ada permintaan pertama pengguna atau mereka telah tidak aktif cukup lama. Dalam kes ini:
Kes B: Pengguna Aktif
Jika IP ditemui, ia bermakna pengguna telah membuat permintaan sebelumnya. Di sini:
Dalam kes terakhir ini, kita perlu menyemak sama ada masa yang mencukupi telah berlalu sejak blok terakhir. Kita tahu mana antara timeoutSeconds yang harus kita rujuk terima kasih kepada indeks. Jika tidak, bangkit semula. Jika tidak, kemas kini cap masa.
export class Throttler { private storage = new Map<string, ThrottlingCounter>(); constructor(private timeoutSeconds: number[]) {} }
Apabila mengemas kini indeks, ia dihadkan kepada indeks terakhir masa tamatSekon. Tanpanya, counter.index 1 akan melimpahinya dan seterusnya akses this.timeoutSeconds[counter.index] akan mengakibatkan ralat masa jalan.
Contoh ini menunjukkan cara menggunakan Throttler untuk mengehadkan kekerapan pengguna boleh menghubungi API anda. Jika pengguna membuat terlalu banyak permintaan, mereka akan mendapat ralat dan bukannya menjalankan logik utama.
const throttler = new Throttler([1, 2, 4, 8, 16]);
Apabila menggunakan pengehadan kadar dengan sistem log masuk, anda mungkin menghadapi isu ini:
Untuk mengelakkan ini, gunakan ID pengguna unik pengguna dan bukannya IP mereka untuk mengehadkan kadar. Selain itu, anda mesti menetapkan semula keadaan pendikit selepas log masuk yang berjaya untuk mengelakkan sekatan yang tidak perlu.
Tambah kaedah tetapan semula pada kelas Throttler:
export class Throttler { // ... public consume(key: string): boolean { const counter = this.storage.get(key) ?? null; const now = Date.now(); // Case A if (counter === null) { // At next request, will be found. // The index 0 of [1, 2, 4, 8, 16] returns 1. // That's the amount of seconds it will have to wait. this.storage.set(key, { index: 0, updatedAt: now }); return true; // allowed } // Case B const timeoutMs = this.timeoutSeconds[counter.index] * 1000; const allowed = now - counter.updatedAt >= timeoutMs; if (!allowed) { return false; // denied } // Allow the call, but increment timeout for following requests. counter.updatedAt = now; counter.index = Math.min(counter.index + 1, this.timeoutSeconds.length - 1); this.storage.set(key, counter); return true; // allowed } }
Dan gunakannya selepas log masuk berjaya:
export class Throttler { private storage = new Map<string, ThrottlingCounter>(); constructor(private timeoutSeconds: number[]) {} }
Apabila pendikit anda menjejaki IP dan had kadar, adalah penting untuk memikirkan cara dan bila untuk mengalih keluar rekod IP yang tidak diperlukan lagi. Tanpa mekanisme pembersihan, pendikit anda akan terus menyimpan rekod dalam ingatan, yang berpotensi membawa kepada isu prestasi dari semasa ke semasa apabila data berkembang.
Untuk mengelakkan ini, anda boleh melaksanakan fungsi pembersihan yang secara berkala mengalih keluar rekod lama selepas tempoh tertentu tidak aktif. Berikut ialah contoh cara menambah kaedah pembersihan mudah untuk mengalih keluar masukan lapuk daripada pendikit.
const throttler = new Throttler([1, 2, 4, 8, 16]);
Cara yang sangat mudah (tetapi mungkin bukan yang terbaik) untuk menjadualkan pembersihan adalah dengan setInterval:
export class Throttler { // ... public consume(key: string): boolean { const counter = this.storage.get(key) ?? null; const now = Date.now(); // Case A if (counter === null) { // At next request, will be found. // The index 0 of [1, 2, 4, 8, 16] returns 1. // That's the amount of seconds it will have to wait. this.storage.set(key, { index: 0, updatedAt: now }); return true; // allowed } // Case B const timeoutMs = this.timeoutSeconds[counter.index] * 1000; const allowed = now - counter.updatedAt >= timeoutMs; if (!allowed) { return false; // denied } // Allow the call, but increment timeout for following requests. counter.updatedAt = now; counter.index = Math.min(counter.index + 1, this.timeoutSeconds.length - 1); this.storage.set(key, counter); return true; // allowed } }
Mekanisme pembersihan ini membantu memastikan pendikit anda tidak menyimpan rekod lama selama-lamanya, memastikan aplikasi anda cekap. Walaupun pendekatan ini mudah dan mudah dilaksanakan, pendekatan ini mungkin memerlukan penghalusan lanjut untuk kes penggunaan yang lebih kompleks (cth., menggunakan penjadualan yang lebih maju atau mengendalikan keselarasan tinggi).
Dengan pembersihan berkala, anda menghalang memori memori dan memastikan bahawa pengguna yang tidak cuba membuat permintaan untuk seketika tidak lagi dijejaki - ini adalah langkah pertama ke arah menjadikan sistem pengehad kadar anda berskala dan cekap sumber.
Jika anda berasa mencabar, anda mungkin berminat untuk membaca cara harta tanah diperuntukkan dan cara ia berubah. Juga, mengapa tidak, tentang pengoptimuman VM seperti cache sebaris, yang sangat disukai oleh monomorfisme. Nikmati. ↩
Atas ialah kandungan terperinci Pendikitan Dijelaskan: Panduan Mengurus Had Permintaan API. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!