Наверняка многие бекенд программисты сталкивались с задачей ограничением запросов к некоторому источнику данных. Существует множество решений этой проблемы:

1) хранить историю во внешнем источнике данных, как redis. Для вычисления возможности отправить запрос, нужно каждый раз ходить в этот источник данных, что может быть непозволительно в некоторых сферах (так как существенно увеличивается время обработки запроса)

2) не париться с limiter и анализировать ответ от внешнего источника данных и на основе его ответов, принимать решение когда и сколько запросов можно отправить (но такие ответы есть не у каждого сервиса и существует вероятность, что будут отправлены лишние запросы, что может привести к бану)

3) хранить историю запросов локально, но использовать алгоритм leaked bucket, но это не позволяет накидать несколько запросов и ждать

4) хранить историю запросов локально, но использовать алгоритм sliding window, можно накидать запросов и ждать какое-то известное время

О реализации sliding window для java пойдет речь в этой статье

Пример сервиса, где нужно не превышать некоторый лимит по запросам

Цели стояли такие:

  • не ходить по сети куда-то во внешний сервис, чтобы узнать можно ли отправить запрос или нет (так как увеличивает время обработки запроса)

  • хотелось бы иметь библиотеку (а не создавать велосипед каждый раз)

  • можно было использовать, как в spring проектах, так и в других фреймворказ и JVM языках

Сразу хочу отметить

1) готовой библиотеки с реализацией алгоритма sliding-window для java/kotlin - не нашел

2) моя библиотека не полностью закончена (в статусе beta), но уже можно использовать в своих проектах

Хорошая статья о sliding window

Моя библиотека

Если есть какие-то советы по улучшению библиотеки, лучше сразу создавайте issues или PR.

Ставьте звезды - так буду понимать, что библиотека интересна и стоит дальше развивать.

P.S.: первая статья на Хабре.

Комментарии (10)


  1. includedlibrary
    29.08.2022 22:08
    +7

    Это не статья, а сообщение в стиле: "смотри, что я запилил". Было бы не плохо описать детали реализации и примеры использования, а не тупо кинуть ссылки на гитхаб


  1. TheNavi
    29.08.2022 22:09
    +19

    Requests, Карл! Requests!


    1. KGeist
      29.08.2022 23:21
      +4

      А бэкенд-программист пишется через дефис. В русском языке нельзя просто взять и поставить два существительных рядом, как в английском. Зело, люто негодую, когда забывают про дефисы. Считаю своим долгом в комментариях к каждой статье упоминать о них. Жар-птица, Иван-дурак, бизнес-требования, бэкенд-разработчик!


      1. neuotq
        30.08.2022 11:28

        Бэк-енд-программист
        PS простите


  1. shai_hulud
    29.08.2022 23:07
    +1

    ExecutorService cleanHistoryExecutor = Executors.newSingleThreadExecutor();

    Я конечно не сварщик. И в джаве не разбираюсь, но реализация требует 1 поток на каждый лимитер?


  1. BugM
    29.08.2022 23:17

    Реализация у вас тоже забагованная. Баги есть и в логике работы и в реализации этой логики.

    Мультипоточный конкурентный код это сложно и совсем не очевидно.


  1. V1tol
    29.08.2022 23:20
    +1

    В первую очередь в голову приходит https://github.com/Netflix/Hystrix


    1. BugM
      29.08.2022 23:25

      Оверкилл. Он довольно сложен и нормально его заиспользовать не очень тривиально. Сейчас уже есть попроще варианты.

      Что-то такое лучше подойдет https://developer.redis.com/develop/java/spring/rate-limiting/fixed-window/reactive


      1. V1tol
        29.08.2022 23:28

        Ну я не джава сварщик, просто про эту штуку знаю.


    1. dimaloop
      30.08.2022 17:01

      Hystrix в maintenance mode давно, он мертв