Алгоритм ограничения тока
В настоящее время существует два алгоритма общего тока: алгоритм ковша токена и алгоритм протекания. Основное отличие состоит в том, что алгоритм протекания ковша может насильно ограничивать скорость запроса и плавные запросы на разрыв, в то время как алгоритм ковша токенов позволяет определить определенное количество запросов на разрыв при ограничении средней скорости.
Ниже приведены две диаграммы алгоритма, обнаруженные в Интернете, которые можно легко отличить от характеристик этих двух алгоритмов.
Утечка ведра алгоритм
Алгоритм ковша токена
Для интерфейсов определенное количество запросов на взрыв, как правило, разрешено обрабатывать, и для ограничения требуется только средняя скорость, поэтому алгоритм ковша токена чаще встречается.
Токеновый алгоритм инструмент ratelimiter ratelimiter
Класс реализации алгоритма токенов, который я использую наиболее часто используемым, является ratelimiter of Google Guava. Гуава не только реализует алгоритм ковша токена, но и кэш, новые классы коллекций, одновременные классы инструментов, классы обработки строк и т. Д. Это мощный набор инструментов
RateLimiter API может просмотреть введение guava Ratelimiter в одновременную сеть программирования
Анализ исходного кода RateLimiter
По умолчанию наиболее основными атрибутами Ratelimiter являются два NextFreeticketMicros. Время токена может быть получено в следующий раз, а количество токенов в ведре Haterporedpermits.
Определить, получить ли токен:
Каждый раз, когда вы получаете токен, рассчитывайте самое быстрое время, чтобы получить токен в следующий раз в зависимости от количества токенов в ведре. При определении того, можно ли получить ресурс, просто сравните NextFreeticketMicros с текущим временем.
Получите операцию вдали:
Для получения токена вычислите количество новых токенов на основе NextFreeticketMicros и текущего времени, напишите текущий номер токена токена и пересчитывайте NextFreeticketMicros. Если в ведре есть токен, напишите текущее время и уменьшите количество токенов, полученных по этому запросу.
Как и класс AQS в Java, ядро RateLimiter - это метод TryAcquire
Public Boolean TryAcquire (int разрешения, длительный тайм -аут, время Unit) {// Попробуйте получить максимальное время ожидания длительное время Timeoutmicros = max (unit.tomicros (Timeout), 0); // Проверьте, является ли количество полученных ресурсов правильными проверками (разрешениями); Длинный микростовайт; // блокировка синхронизирована (mutex ()) {// текущее время nowmicros = spectwatch.readmicros (); // судить, можно ли получить ресурс в течение времени, если (! Canacquire (nowmicros, timeoutmicros)) {return false; } else {// ресурс может быть получен, пересчитал ресурс и возвращал время сна, требуемое текущим потоком MicroStowait = ReselaNdAndgetWaitLength (разрешения, nowmicros); }} // Sleep Spectwatch.sleepmicrosunintertaill (Microstowait); вернуть истину; }Определить, получить ли токен:
Частный логический Canacquire (Long Nowmicros, Long Timeoutmicros) {// можно получить в самое раннее время ресурса - Время ожидания <= текущее время можно получить до получения ресурса, который можно получить QueryEarliestableable (nowmicros) - Timeoutmicros <= nowmicros;}Ratelimiter по умолчанию класс Класс Запрос
Получите токен и рассчитайте необходимую работу времени ожидания:
Окончательный длинный ReserveAndgetWaitLength (int разрешения, Long Nowmicros) {// Получите время, чтобы получить в следующий раз MomentAbleBailable = ReserveArliestableable (разрешения, nowmicros); // Рассчитайте время сна, необходимое для возврата текущего потока, чтобы вернуть макс (MomentAvailable - nowmicros, 0);} Окончательный длинный RaverLiestAbleable (int требуется, long nowmicros) {// пересчитывать количество токенов в ведре Storedpermits resync (nowmicros); long returnvalue = nextfreeticketmicros; // количество токенов, потребляемых на это время, двойное соблюдение // пересчитывать время, чтобы получить в следующий раз, когда следующий фреэтикетмикрос двойной свежиеперамиты = обязательный человек - StoredPermitStospend; Long Waitmicros = StoredPermitStowaitTime (this.storedPermits, StoredPermitStospend) + (Long) (FreshPermits * stableIntervalmicros); this.nextfreeticketmicros = longmath.satustratedadd (nextfreeticketmicros, waitmicros); // уменьшить количество токенов в ведре this.storedpermits -= StoredPermitStospend; returnValue; }Реализовать простой перехватчик ограничения тока MVC Spring MVC
Реализуйте HandlerInterceptor, создайте ограничитель тока RateLimiter в конструкторе
public simpleeratelimitInterceptor (int rate) {if (rate> 0) globalratelimiter = ratelimiter.create (rate); иначе бросить новое runtimeexception («скорость должна превышать нуль»);}Вызовите метод TryAcquire текущего ограничителя в Prehandle, чтобы определить, превысила ли его предельная скорость
Public Boolean Prehandle (httpservlectrequest, httpservletresponse ответ, обработчик объекта) выбрасывает исключение {if (! globalratelimiter.tryacquire ()) {loggerutil.log (request.getRequesturi ()+"Запрос превышает текущую ограниченную скорость"); вернуть ложь; } вернуть true; }Настройка текущего ограниченного перехватчика в диспетчере-servlet.xml
<MVC: Interceptors> <!-Turning Limit Interceptor-> <MVC: Interceptor> <mvc: mapping path = "/**"/> <bean> <constructor-arg index = "0" value = "$ {totalrate}"/> </bean> </mvc: receptor> </mvc: interceptors>Сложная версия Spring MVC Tccure Limit Interceptor
Используйте свойства для прохождения в перехваченном выражении URL -> скорость скорости
<MVC: Interceptor> <MVC: PATH MAPPAPION = "/**"/> <Bean> <!-Ограничение тока единого URL-> <name = "urlproperties"> <props> <prop key = "/get/{id}"> 1 </prop> <prop = "/post"> 2 </prop> </props> <//propor> </bean> </bean> </bean> </bean> </bean> </bean> </bean> </bean> </bean> </bean> </bean> </bean> </bean> </bean Создайте соответствующий ограничитель тока RateLimiter для каждого выражения URL. Выражение URL инкапсулируется как org.springframework.web.servlet.mvc.condition.patternsrequestcondition. PatternSrequestCondition - это класс, используемый в SpringMVC DispatcherServlet в соответствии с запросами и контроллерами. Это может определить, соответствует ли запрос этим выражениям URL.
В методе перехватчика
// текущий путь пути запроса строка Lookuppath = urlpathhelper.getLookupPathforRequest (request); // итерация над PatternSRequestCondition, соответствующим всем выражениям URL (PatternSrequestCondition PatternSrequestCondition: urlratemap.keyset () {// Сделать списку сопоставления <строки> matches = = PatternSrequestCondition.getMatchingPatterns (LookUppath); if (! Matches.isempty ()) {// Если совпадение успешно, получите токен соответствующего ограничителя тока if (urlratemap.get (patternsrequestcondition) .tryacquire ()) {loggerutil.log (lookuppath + «Запрос, сопоставляемый с" + oaner.on (", uptance"). ограничитель "); } else {// не удалось получить token loggerutil.log (lookuppath + "запрос превышает" + joiner.on (","). Join (patternSrequestCondition.getPatterns ()) + "Скорость тока");); вернуть ложь; }}}Конкретные классы реализации
Пожалуйста, смотрите GitHub
Выше всего содержание этой статьи. Я надеюсь, что это будет полезно для каждого обучения, и я надеюсь, что все будут поддерживать Wulin.com больше.