خوارزمية المحدد الحالية
حاليًا ، هناك نوعان من خوارزميات المحدد الحالية الشائعة: خوارزمية دلو رمزية وخوارزمية دلو تسرب. الفرق الرئيسي هو أن خوارزمية الجرافة المتسربة يمكن أن تحد قسراً من معدل الطلب وطلبات الاندفاع السلس ، في حين تتيح خوارزمية الجرافة الرمزية مبلغًا معينًا من طلبات الانفجار عند الحد من متوسط معدل.
فيما يلي مخططان خوارزمية موجودان على الإنترنت ، والتي يمكن تمييزها بسهولة عن خصائص هاتين الخوارزميات.
خوارزمية دلو تسرب
خوارزمية دلو الرمز المميز
بالنسبة للواجهات ، يُسمح عمومًا بمعالجة عدد معين من طلبات الانفجار ، ولا يلزم سوى متوسط معدل الحد ، وبالتالي فإن خوارزمية الجرافة الرمزية أكثر شيوعًا.
رمز دلو الخوارزمية أداة ratelimiter
فئة تنفيذ خوارزمية دلو الرمز المميز الذي أستخدمه هو الأكثر شيوعًا هو Ratelimiter من Google Guava. لا تنفذ الجوافة خوارزمية دلو الرمز المميز فحسب ، بل أيضًا ذاكرة التخزين المؤقت ، فئات التجميع الجديدة ، فئات الأدوات المتزامنة ، فئات معالجة السلسلة ، إلخ. إنها مجموعة أدوات قوية
يمكن لـ RateLimiter API عرض إدخال Ratelimiter في شبكة البرمجة المتزامنة
تحليل رمز المصدر Ratelimiter
بشكل افتراضي ، فإن أكثر السمات الأساسية لـ Ratelimiter هي اثنين من NextFreeticketMicros. يمكن الحصول على وقت الرمز المميز في المرة القادمة وعدد الرموز في دلو المخزن.
تحديد ما إذا كان سيتم الحصول على الرمز المميز:
في كل مرة تحصل فيها على رمز ، احسب أسرع وقت للحصول على الرمز المميز في المرة القادمة بناءً على عدد الرموز في الدلو. عند تحديد ما إذا كان يمكن الحصول على المورد ، فقط قارن NextFreeticketMicros مع الوقت الحالي.
احصل على عملية رمزية:
للحصول على الرمز المميز ، احسب عدد الرموز الجديدة بناءً على NextFreeticketMicros والوقت الحالي ، واكتب رقم الرمز المميز الرمزي الحالي ، وإعادة حساب NextFreeticketMicros. إذا كان هناك رمز في الدلو ، فاكتب الوقت الحالي وقلل من عدد الرموز التي تم الحصول عليها من هذا الطلب.
تمامًا مثل فئة AQS في Java ، فإن جوهر Ratelimiter هو طريقة Tryacquire
BOOLEAN Public TryAcquire (تصاريح INT ، فترة طويلة ، وحدة TimeUnit) {// حاول الحصول على الحد الأقصى لوقت الانتظار الطويل timeoutmicros = max (unit.tomicros (timeout) ، 0) ؛ // تحقق مما إذا كان عدد الموارد التي تم الحصول عليها هو checkpermits صحيح (تصاريح) ؛ microstowait طويلة. // lock synchronized (mutex ()) {// time time long nowmicros = STOPTWATCH.READMICROS () ؛ // احكم على ما إذا كان يمكن الحصول على المورد في غضون مهلة الوقت إذا (! canacquire (nowmicros ، timeoutmicros)) {return false ؛ } آخر {// يمكن الحصول على المورد ، وإعادة حساب المورد ، وإرجاع وقت النوم المطلوب من قبل مؤشر الترابط الحالي microstowait = sudgenendgetWaitLength (التصاريح ، nowmicros) ؛ }} // Sleep Forptwatch.SleePmicrosuninterruptluredruptlurectly (microstowait) ؛ العودة صحيح. }تحديد ما إذا كان سيتم الحصول على الرمز المميز:
Canacquire الخاص المنطقي الخاص (Nowmicros Long ، timeoutmicros) {// في أقرب وقت للموارد يمكن الحصول عليه - وقت الانتظار <= يمكن الحصول على الوقت الحالي قبل الحصول على المورد Return queryearliestavail (nowmicros) - timeOtmicros <= nowmicros ؛}Ratelimiter الافتراضي للتنفيذ QueryearLiestAvailable هو أخذ متغير الأعضاء NextFreeticketMicros
احصل على الرمز المميز وحساب عملية وقت الانتظار المطلوبة:
Long Long Engendangwaitlength (تصاريح int ، Nowmicros Long) {// احصل على الوقت للحصول على الوقت التالي Long MoveAvailable = ReserveArliestAvailivation (تصاريح ، nowmicros) ؛ // احسب وقت النوم المطلوب للخيط الحالي لإرجاع الحد الأقصى (Moxivailable - Nowmicros ، 0) ؛} Final Long ReserveArliestAvailable (int requiredmits ، long nowmicros) {// إعادة حساب عدد الرموز في دلو storedpermits resync (nowmicros) ؛ عودة طويلة = nextFreeticketMicros ؛ // عدد الرموز المستهلكة هذه المرة المخزنة المزدوجة = min (المطلوبة ، هذا. . long waitmicros = storedPermitStowAittime (this.storedPermits ، storedPermitStospend) + (long) (freshpermits * stableintervalmicros) ؛ this.nextfreeticketmicros = longmath.suTratedadd (nextFreeticketMicros ، waitmicros) ؛ // تقليل عدد الرموز في الدلو this.storedpermits -= storedPermitStospend ؛ إرجاع القيمة ؛ }قم بتنفيذ اعتراض الحد الحالي لـ Spring MVC
قم بتنفيذ مقبول معالج ، قم بإنشاء محدد تيار Ratelimiter في المُنشئ
publicerateLimItInterceptor (معدل int) {if (rate> 0) GlobalRateLimiter = rateLimiter.Create (معدل) ؛ آخر رمي RunTimeException ("يجب أن أكبر من الصفر") ؛}استدعاء طريقة TryAcquire للمحدد الحالي في Prehandle لتحديد ما إذا كان معدل الحد قد تجاوزه
طلب Boolean Pre -Handle (httpservletrequest ، استجابة httpservletresponse ، معالج الكائن) يلقي الاستثناء {if (! globalRatelimiter.TryAcquire ()) {loggerUtil.log (request.getRequesturi ()+"يتجاوز طلب المحدد الحالي") ؛ العودة كاذبة } إعادة صواب ؛ }قم بتكوين اعتراض الحد الحالي في Servatcher-Servlet.xml
<mvc: interceptors> <!-اعتراض الحد الحالي-> <mvc: interceptor> <mvc: mapping path = "/**"/> <bean>
نسخة معقدة من عرض الحد الأقصى الحالي لـ SPRING MVC
استخدم الخصائص لتمرير التعبير عن عنوان URL المعترض -> معدل معدل
<mvc: interceptor> <mvc: mapping path = "/**"/> <bean> <!-حد عنوان URL واحد-> <property name = "urlproperties"> <bors> <prop key = "/get/id {id}"> 1 </proctor> <props key = "/post"> 2 </props> إنشاء محدد تيار Ratelimiter المقابل لكل تعبير عناوين URL. يتم تغليف تعبير عنوان URL على أنه org.springframework.web.servlet.mvc.condition.patternsRequestCondition. PatternSrequestCondition هو فئة تستخدم في SPRINGMVC's DisterServlet لمطابقة الطلبات ووحدات التحكم. يمكنه تحديد ما إذا كان الطلب يتوافق مع تعبيرات عنوان URL هذه.
في طريقة التقاطع المسبق
. PatternSrequestCondition.getMatchingPatterns (lookuppath) ؛ إذا كانت (! matches.isempty ()) {// إذا كانت المباراة ناجحة ، فاحصل على الرمز المميز للمحدد الحالي المقابل إذا (urlrateMap.get (patternsrequestcondition) .rytyriacquire ()) محدد ") ؛ } آخر {// فشل في الحصول على token loggerUtil.log (lookuppath + "request يتجاوز" + joiner.on ("،"). العودة كاذبة }}}فئات التنفيذ المحددة
يرجى الاطلاع على جيثب
ما سبق هو كل محتوى هذه المقالة. آمل أن يكون ذلك مفيدًا لتعلم الجميع وآمل أن يدعم الجميع wulin.com أكثر.