Algoritma pembatas saat ini
Saat ini, ada dua algoritma limiter saat ini: algoritma bucket token dan algoritma bucket bocor. Perbedaan utama adalah bahwa algoritma bucket bocor dapat secara paksa membatasi tingkat permintaan dan lancar permintaan burst, sedangkan algoritma token bucket memungkinkan sejumlah permintaan burst ketika membatasi tingkat rata -rata.
Di bawah ini adalah dua diagram algoritma yang ditemukan di internet, yang dapat dengan mudah dibedakan dari karakteristik kedua algoritma ini.
Algoritma bocor bucket
Algoritma Token Bucket
Untuk antarmuka, sejumlah permintaan burst umumnya diizinkan untuk diproses, dan hanya tingkat rata -rata yang diperlukan untuk membatasi, sehingga algoritma token bucket lebih umum.
Algoritma Token Bucket Algoritma Ratelimiter
Kelas Implementasi Algoritma Token Bucket yang paling sering saya gunakan adalah Ratelimiter dari Google Guava. Guava tidak hanya mengimplementasikan algoritma Token Bucket, tetapi juga cache, kelas koleksi baru, kelas alat bersamaan, kelas pemrosesan string, dll. Ini adalah set alat yang ampuh
API Ratelimiter Dapat Melihat Pengenalan Ratelimiter Guava di Jaringan Pemrograman Bersamaan
Analisis kode sumber ratelimiter
Secara default, atribut inti paling ratelimiter adalah dua NextFreeticketMicros. Waktu token dapat diperoleh waktu berikutnya dan jumlah token dalam ember yang disimpan.
Tentukan apakah akan mendapatkan token:
Setiap kali Anda mendapatkan token, hitung waktu tercepat untuk mendapatkan token lain kali berdasarkan jumlah token di ember. Saat menentukan apakah sumber daya dapat diperoleh, cukup bandingkan NextFreeticketMicros dengan waktu saat ini.
Dapatkan Operasi Token:
Untuk mendapatkan token, hitung jumlah token baru berdasarkan NextFreetICKETMICros dan waktu saat ini, tuliskan nomor token token bucket saat ini, dan hitung ulang NextFreeticketMicros. Jika ada token di ember, tulis waktu saat ini dan kurangi jumlah token yang diperoleh berdasarkan permintaan ini.
Sama seperti kelas AQS di Java, inti dari ratelimiter adalah metode tryacquire
Public Boolean TREACQUIRE (Izin int, waktu lama, Unit TimeUnit) {// Cobalah untuk mendapatkan waktu tunggu maksimum yang lama waktu outmicros = max (unit.tomicros (timeout), 0); // Periksa apakah jumlah sumber daya yang diperoleh adalah checkpermit yang benar (izin); Long Microstowait; // kunci disinkronkan (mutex ()) {// waktu saat ini long nowmicros = stopwatch.readmicros (); // menilai apakah sumber daya dapat diperoleh dalam waktu batas waktu jika (! CanAcquire (NowMicros, timeoutmicros)) {return false; } else {// sumber daya dapat diperoleh, menghitung ulang sumber daya, dan mengembalikan waktu tidur yang dibutuhkan oleh utas saat ini microstowait = reserveAndgetwaitlength (izin, nowmicros); }} // The Sleep Stopwatch.sleepmicrosuninterruptible (microstowait); Kembali Benar; }Tentukan apakah akan mendapatkan token:
private boolean canacquire (long nowmicros, long timeoutmicros) {// Pada waktu sumber daya paling awal dapat diperoleh - waktu tunggu <= waktu saat ini dapat diperoleh sebelum sumber daya dapat diperoleh pengembalian queryliestable (nowmicros) - timeoutmicros <= nowmicros;}Ratelimiter Kelas Implementasi Default QueryearliestAvailable adalah untuk mengambil variabel anggota nextFreeticketmicros
Dapatkan token dan hitung operasi waktu tunggu yang diperlukan:
Final Long ReserveAnDgetWaitLength (int Izin, Long NowMicros) {// Dapatkan waktu untuk mendapatkan momentavailable long kali berikutnya = cetakeArliestAvailable (izin, nowmicros); // Hitung waktu tidur yang diperlukan untuk utas saat ini untuk mengembalikan max (momentvailable - nowmicros, 0);} Final Long ReserveArliesTavailable (int wajib yang diperlukan, long nowmicros) {// menghitung ulang jumlah token dalam ember disimpan kembali (nowmicros); Long ReturnValue = NextFreeticketMicros; // Jumlah token yang dikonsumsi kali ini ganda STOREDPERMITSTOSPEND = MIN (Wajib, This.StoredPerMits); // Hitung ulang waktu untuk mendapatkan waktu berikutnya NextFreetICKETMICROS Double FreshPerMits = wajib yang dibutuhkan - StoredPerMitstospend; waitmicros long = storedpermitstoWaittime (this.storedpermits, storedpermitstospend) + (panjang) (freshpermits * stabilintervalmicros); this.nextfreeticketmicros = longmath.saturedAdd (nextFreeticketmicros, waitmicros); // Kurangi jumlah token dalam ember this.StoredPerMits -= StoredPerMitStospend; Return ReturnValue; }Menerapkan Interceptor Batas Saat Ini Sederhana MVC Sederhana
Menerapkan HandlerInterceptor, buat pembatas arus ratelimiter di konstruktor
publik SimplerAteLimItInceptor (int rate) {if (rate> 0) GlobalRatelImiter = ratelimiter.Create (rate); lain lempar runimeException baru ("rate harus lebih besar dari nol");}Panggil metode tryacquire dari limiter saat ini dalam prehandle untuk menentukan apakah laju batas telah melebihi itu
Public boolean prehandle (permintaan httpservletRequest, respons httpservletResponse, penangan objek) melempar pengecualian {if (! Globalratelimiter.tryacquire ()) {loggerutil.log (request.getRequesttur ()+"permintaan melebihi tingkat pembatas saat ini"); mengembalikan false; } return true; }Konfigurasikan Batas Interceptor saat ini di dispatcher-servlet.xml
<MVC: Interceptors> <!-Limit saat ini Interceptor-> <Mvc: Interceptor> <mvc: pemetaan path = "/**"/> <bean> <konstruktor-arg index = "0" value = "$ {TotalRATE}"/> </bean> </mvc: interceptor> </mvc: intercepors>Versi kompleks Spring MVC Current Limit Interceptor
Gunakan properti untuk dilewati dalam ekspresi URL yang dicegat -> laju laju
<Mvc: Interceptor> <mvc: pemetaan path = "/**"/> <bean> <!-batas arus URL tunggal-> <name properti = "urlproperties"> <props> <prop key = "/get/{id}"> 1 </pop> <prop Key = "/post"> 2 </get/{propsor> </propsy </prop> </post/post "> 2 </get/props </props> </prop> </props ="/post "> 2 </{ID}"> </prop> <for Key = "/POST"> 2 <//props </props> </prop> </propsy = "/post"> 2 </iD: Props </propsceps/mv </ban </ban </post/post/post/post/post/post/foror </props> Buat limiter arus ratelimiter yang sesuai untuk setiap ekspresi URL. Ekspresi URL dienkapsulasi sebagai org.springframework.web.servlet.mvc.condition.patternsRequestCondition. PatternsRequestCondition adalah kelas yang digunakan di SpringMVC's DispatcherServlet untuk mencocokkan permintaan dan pengontrol. Ini dapat menentukan apakah permintaan tersebut sesuai dengan ekspresi URL ini.
Dalam metode PreHandle Interceptor
// string jalur permintaan saat ini lookuppath = urlpathhelper.getLookuppathForRequest (request); // iterate over PatternSRequestCondition yang sesuai dengan semua ekspresi URL (PatternsRequestCondition Daftar <Tring> county = Urlratemap.keyset ()) {// Buat A CochRequestCondition: UrlrateMap.keyset ()) {// Buat A MatchSequestCondition: UrlrateMap.keyset ()) {// Buat A MatchSequestCondition: UrlrateMap.keyset ()) {// Make a MatchSequestCondition: Urlratemap.keyset () PatternSRequestCondition.getMatchingPatterns (lookuppath); if (! matches.isempty ()) {// Jika pertandingan berhasil, dapatkan token dari limiter saat ini yang sesuai jika (urlratemap.get (polaSrequestCondition) .tryryacquire ()) {loggerutil.log (lookuppath + "permintaan cocok dengan" + joiner.on ("). } else {// Gagal mendapatkan token loggerutil.log (lookuppath + "permintaan melebihi" + joiner.on (","). gabungkan (polaSrequestCondition.getPatterns ()) + "laju pembatas saat ini"); mengembalikan false; }}}Kelas implementasi spesifik
Silakan lihat GitHub
Di atas adalah semua konten artikel ini. Saya berharap ini akan membantu untuk pembelajaran semua orang dan saya harap semua orang akan lebih mendukung wulin.com.