Rate limiting в системном дизайне: один пользователь или сервис не должен слишком часто дергать API и завалить его.
В Spring Boot для этого можно использовать библиотеку Bucket4j и сделать Rate Limit Filter.
Она умеет:
▪️ защищать от примитивных DDoS-атак
▪️ отсеивать кривых клиентов, которые шлют запросы в цикле
▪️ ограничивать число запросов за единицу времени
▪️ делать доступ чуть более честным: понемногу всем, а не все одному
Очень просто, быстро и потокобезопасно.
▪️ На каждый запрос проверяет, есть ли в кэше ключ клиента (например IP). Если нет, создает для него bucket с токенами.
▪️ Каждый раз пытается забрать из bucket один токен, то есть право выполнить запрос.
▪️ Если токен в bucket есть, проходишь. Если токены закончились, получаешь HTTP 429 и ждешь пополнения.
Заметки:
-> request.getRemoteAddr() ищет корректный способ получить IP клиента, возможно через request.getHeader("X-Forwarded-For")
-> new ConcurrentHashMap<>() сам по себе не чистится, продумай, как долго хранить данные и как их вычищать, если запросов много
-> лимит задается одинаковый для всех эндпоинтов. Часто у разных API разная нагрузка, поэтому логично ставить разные лимиты (по URL, HTTP-методу или типу операции)
-> refillGreedy() это всего лишь один из вариантов пополнения токенов. Есть и другие стратегии (плавное пополнение, фиксированные интервалы), которые дают более точный контроль нагрузки
-> вынеси все настройки в application.yaml, чтобы менять лимиты без правок кода
Простая реализация, чтобы понять, как работает библиотека, приложена
👉 Java Portal
В Spring Boot для этого можно использовать библиотеку Bucket4j и сделать Rate Limit Filter.
Она умеет:
Очень просто, быстро и потокобезопасно.
Заметки:
-> request.getRemoteAddr() ищет корректный способ получить IP клиента, возможно через request.getHeader("X-Forwarded-For")
-> new ConcurrentHashMap<>() сам по себе не чистится, продумай, как долго хранить данные и как их вычищать, если запросов много
-> лимит задается одинаковый для всех эндпоинтов. Часто у разных API разная нагрузка, поэтому логично ставить разные лимиты (по URL, HTTP-методу или типу операции)
-> refillGreedy() это всего лишь один из вариантов пополнения токенов. Есть и другие стратегии (плавное пополнение, фиксированные интервалы), которые дают более точный контроль нагрузки
-> вынеси все настройки в application.yaml, чтобы менять лимиты без правок кода
Простая реализация, чтобы понять, как работает библиотека, приложена
Please open Telegram to view this post
VIEW IN TELEGRAM
❤8🔥4
This media is not supported in your browser
VIEW IN TELEGRAM
Совет для IntelliJ: Alt+Enter можно использовать, чтобы быстро чинить ошибки и предупреждения, но список вариантов там довольно ограничен.
Вместо этого используй автодополнение команд (..), чтобы выполнять нужные действия прямо в редакторе.
👉 Java Portal
Вместо этого используй автодополнение команд (..), чтобы выполнять нужные действия прямо в редакторе.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7❤3🔥2
Spring Boot: не используй
✗ Помечая связь как
✗ В этом примере каждый раз, когда ты загружаешь
✗ И ещё: если не делать явный fetch, получаешь классический эффект N+1:
1. Один запрос на все
2. По одному запросу на каждый
👉 Java Portal
FetchType.EAGER, если реально нет необходимости.✗ Помечая связь как
EAGER, ты говоришь ORM подгружать её каждый раз вместе с сущностью, даже если ты вообще не обращаешься к этой связи (не вызываешь геттер/метод отношения).✗ В этом примере каждый раз, когда ты загружаешь
Order, ORM автоматически подтянет и Customer:@Entity
class Order {
@ManyToOne(fetch = FetchType.EAGER)
private Customer customer;
}
✗ И ещё: если не делать явный fetch, получаешь классический эффект N+1:
1. Один запрос на все
Orders2. По одному запросу на каждый
Order для CustomersPlease open Telegram to view this post
VIEW IN TELEGRAM
👍7❤2
HTTP/2 через TCP против HTTP/3 через QUIC
▪️ HTTP/2
▪️ HTTP/3
👉 Java Portal
Мультиплексирование на уровне HTTP, сериализация на уровне TCP
Общий порядок доставки и контроль перегрузки (TCP)
Одна TCP-сессия
HTTP/2 фреймы (мультиплексированные)
* HEADERS (поток 1)
* HEADERS (поток 3)
* HEADERS (поток 2)
* DATA (поток 1)
* DATA (поток 3)
* DATA (поток 2)
TCP-пакеты: P1, P2, P3, P4, P5
TCP-пакеты смешивают данные из разных потоков
HoL-блокировка в TCP (Head-of-Line): потеря одного пакета блокирует все потоки
Клиент -> Сервер
Мультиплексирование на транспортном уровне (QUIC)
* Независимые потоки
* Независимый порядок доставки и восстановление
QUIC-соединение (поверх UDP)
QUIC Stream 1: QUIC Packet, QUIC Packet, QUIC Packet
QUIC Stream 2: QUIC Packet, QUIC Packet
QUIC Stream 3: QUIC Packet, QUIC Packet
Нет HoL-блокировки: потеря пакета влияет только на один поток
Клиент -> Сервер
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥3
Java tip: для точных расчетов времени используй Duration и Instant.
✅ Instant представляет конкретный момент времени в UTC с точностью до наносекунд. Получить можно так:
✅ Duration показывает временной интервал между двумя
Вот пример:
👉 Java Portal
Instant.now(). Instant (в секундах, миллисекундах, наносекундах). Вот пример:
Instant start = Instant.now();
...
Instant end = Instant.now();
Duration elapsed = Duration.between(start, end);
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8
Изучение Spring Boot у новичков часто вызывает перегруз 😵💫
Поэтому автор сделал Spring Boot Self Learning Guide: короткий гайд с упором на примеры, который покрывает самые часто используемые фичи Spring Boot.
👉 Java Portal
Поэтому автор сделал Spring Boot Self Learning Guide: короткий гайд с упором на примеры, который покрывает самые часто используемые фичи Spring Boot.
Please open Telegram to view this post
VIEW IN TELEGRAM
GitHub
GitHub - sivaprasadreddy/spring-boot-self-learning-guide: Spring Boot Self Learning Guide
Spring Boot Self Learning Guide. Contribute to sivaprasadreddy/spring-boot-self-learning-guide development by creating an account on GitHub.
👍7❤5🔥4