Latest posts

Канал Андрея про бекенд
26 Dec 2025, 09:03edited
🐢🚶🏼♂️🚶🏻♀️🚶🏻 Как HTTP2 решает проблему HOL (head of line) blocking📌 Итак, HTTP1 “блокирует” TCP подключение для каждого запроса. То есть в HTTP1 существует соотношение: 1 TCP коннекция - 1 HTTP запрос в текущий момент времени. Соответственно, способность к масштабированию сводится к увеличению количества подключений.🧲 HTTP2 идет иным путем: он позволяет использовать одно TCP подключение для одновременной передачи данных множества запросов.⬇️ Попробую объяснить на простом примере: У нас есть три HTTP запроса в очереди и одно TCP подключение.|Queue|3|2|1| —> (___TCP__connect__() —>На стороне отправителя я пронумерую эти запросы в порядке поступления - 1, 2, 3. Далее я запишу их в TCP подключение, но не просто так, а добавив “метаинформацию”, а именно присвоенный мной порядковый номер.—> (__TCP__connect|3|_|2|_|1|__() —>На стороне получателя HTTP клиент сможет
Канал Андрея про бекенд
3 Nov 2025, 12:13
Head of line blocking🔒 На собеседовании вас могут спросить, чем протокол HTTP2 лучше HTTP1. В этом посте я опишу проблему Head of line blocking (блокировка головы очереди), которая снижает потенциальную производительность HTTP1 и которую эффективно решает протокол следующей версии.🐢🚶🏼♂️🚶🏻♀️🚶🏻 Опишем суть явления. Скажем, у вас есть очередь задач, которые должны выполняться последовательно друг за другом. Тогда, любая задача, требующая много времени на выполнение задерживает (на это же время) все последующие задачи в очереди. Это кажется очевидным? Но как это связано с HTTP и вообще, зачем это знать?HTTP1 HOL (head of line) blocking🚥 Запросы в HTTP1 обрабатываются в порядке FIFO: записываем запрос в TCP подключение, ждем, пока придет ответ и только получив его записываем следующий запрос. Можно сказать, что подключение “блокируется” на все время выполнения запроса.🐢 П
Канал Андрея про бекенд
18 Sept 2025, 14:54
К посту выше 📤Вспомнил давний случай из практики, когда моя любовь к таймаутам на взятие лока вышла мне боком.🚦 Понадобился мне для чего-то семафор. Напомню, semaphore - это такой мьютекс, который позволяет получать доступ к критической секции одновременно нескольким (N) потокам.Поскольку проект на Kotlin coroutines, я использовал специальный корутиновый семафор и обнаружил, что в его API отсутствует метод, который позволяет передать таймаут и не блокироваться вечно на acquire(). Остановить меня таким невозможно, поэтому я накидал какого-то крокодила-декоратора семафора, где метод acquire выглядел похоже на: suspend fun acquire() { while (true) { try { withTimeout(1000) { semaphoreDelegate.acquire() } return } catch (e: TimeoutCancellationException) { tracer.warn("Bla-bla, long wait...") } } }
Канал Андрея про бекенд
18 Aug 2025, 10:42
Ждать вечно не лучший выбор☠️ Помните задачку про перевод денег с одного аккаунта на другой? Одно из проблемных мест там - возможность взаимной блокировки (deadlock), когда первый поток выполняет перевод с аккаунта с id = 1 на аккаунт с id = 2, а второй поток переводит наоборот со второго на первый аккаунт. Соответственно, может возникнуть ситуация захвата ресурса “крест-накрест”. Один поток захватил блокировку на аккаунт 1 и ждет аккаунта 2, второй поток захватил второй аккаунт и ждет первого.📌 На собеседовании могут спросить, как разрешить данную ситуацию. Каноничным ответом будет: “использовать иерархическую блокировку”. Суть подхода заключается в том, чтобы всегда захватывать и освобождать блокировки в одинаковом порядке. В данном случае, мы могли бы всегда сначала захватывать блокировку для аккаунта с меньшим ID, потом с большим. Это гарантирует отсутствие взаимной блокировки.
Канал Андрея про бекенд
2 Jul 2025, 14:16
Батчинг (пакетная обработка). Часть 2.🌐 Аналогично батчинг применяют для уменьшения сетевых расходов при HTTP взаимодействии (aka REST API). Проектируя свои сервисы и имея высокие требования по пропускной способности/времени отклика, вы можете предусмотреть использование батчинга. Скажем, у вас есть API для обновления статуса заказа по его id:POST /orders/{orderId}/status Content-Type: application/json{ "status": "delivered", "timestamp": "2021-08-01T00:00:00Z" }🌪 Давайте изменим API таким образом, чтобы можно было обновить статусы сразу для нескольких заказов в рамках одного запроса.POST /orders/status Content-Type: application/json{ "statuses": [ {
Канал Андрея про бекенд
11 Jun 2025, 13:03
Батчинг (пакетная обработка). Часть 1.🏛 Ситуация: в моменты повышенной нагрузки время выполнения запросов к БД начинает расти и сказываться на производительности. Профайлер показывает вам, что значительную часть длительности операции занимает ожидание получения JDBC соединения. У вашего приложения уже 20 подключений к базе и больше подключений вам выделять не хотят. Что делать?🏕 Осознаем природу проблемы:🎼 Паттерн работы с JDBC подключением следующий 1. Запрашиваем свободное подключение из пула 2. Посылаем в него команду 3. Ожидаем, когда придет ответ из этого же подключения 4. Возвращаем его в пул🛑 То есть коннекция блокируется на все время выполнения одного конкретного запроса. Давайте представим, что время на доставку запроса до базы по сети составляет 40 ms, еще 40 ms занимает доставка ответа от базы. И только 20 ms занимает сам запрос. Получается из 100 ms мы тратим 80%
Канал Андрея про бекенд
28 May 2025, 10:59
🚰 Разбавлю немного череду постов про метрики.💪 Может быть, вам будет интересно посмотреть доклад Андрея Паньгина о своем детище: профайлере для JVM-based приложений Async-profiler.🔥 Это не какой-то пет-проект, это развитый тул с большим количеством пользователей. Он много раз помогал нашей команде находить узкие места в рабочих проектах. Дополнительный плюс в том, что async-profiler потребляет сравнительно немного ресурсов. В общем, крутая штукаYouTubeAdvanced performance analysis with async-profiler by Andrei PanginFor updates and more, join our community 👉 https://www.linkedin.com/company/devoxx-united-kingdom Thanks to its accuracy and low overhead, Async-profiler became a go-to tool for Java performance engineers. Besides regular CPU and heap allocation sampling…
Канал Андрея про бекенд
17 May 2025, 11:59edited
🟢 Metrics basics - часть 3🔼 В прошлом посте под вторым пунктом плана значилось "Данные с каждого инстанса помещаются в некое хранилище".❓ Но как именно метрики "помещаются" в хранилище? Есть два основных пути, по которому идут разработчики:1️⃣ Клиент (ваш сервис, с которого вы хотите собирать метрики) устанавливает соединение с хранилищем и отправляет ему собранные данные.2️⃣ Сервис выстявляет (expose) наружу API, с помощью которого можно получить собранные на текущий момент данные, а хранилище умеет опрашивать (poll) сервисы с некой регулярностью, "забирать" данные и сохранять у себя.💡 Первый способ является стандартным для общения с базами данных, вероятно, поэтому большинство хранилищ работают именно по этому принципу. Но Prometheus не
Канал Андрея про бекенд
23 Apr 2025, 11:02edited
📌 Metrics basics - часть 2🔆 Что такое метрики мы немного обсудили. Но как собираемые нами измерения превращаются в полезные графики?🦊 Представим, что у нас есть несколько инстансов (экземпляров) одного приложения. Само приложение обслуживает http-запросы от клиентов. И мы хотим где-то видеть график, который показывал бы нам сколько запросов в секунду обслуживает наш сервис.🧵 Итак, цепочка выглядит следующем образом1. Каждый инстанс ведет подсчет выполненных им запросов2. Данные с каждого инстанса помещаются в некое хранилище3. Мы создаем запрос к хранилищу, который подходит под наши требования (скажем, "сколько запросов в секунду обрабатывало наше приложение последние 3 часа")4. Выполняя этот запрос в каком-либо инструменте для визуализации данных, получаем соответствующий график.Конечно, реализация каждого пункта зависит от конкретных технологий, которые вы
Канал Андрея про бекенд
16 Apr 2025, 11:59edited
📊 Metrics basics - часть 1. Что такое метрики?🔬 Метрики - числовые данные, отражающие какой-то аспект вашего приложения. Они формируются путем регулярных подсчетов и замеров интересующих параметров сервиса. Это могут быть размеры очередей, количество потоков, количество совершенных http запросов или отправленных / полученных байтов.📌 У метрики есть название, обычно отражающее предмет измерения (task completed / request served). Кроме того, к метрике могут прикрепляться метаданные, которые представляют из себя набор пар ключ-значение.💡 Пример: метрика с названием http_requests_served_total.- Отражает общее количество http запросов, которые были обслужены- Обычный счетчик ⏱️, который увеличивается каждый раз, когда очередной запрос обслужен. Скажем, в начале их было 0, через минуту 5, еще через минуту 10.❓ Чт
Канал Андрея про бекенд
9 Apr 2025, 14:38

Канал Андрея про бекенд
9 Apr 2025, 14:37
Observability🔍 Конечно, мы хотим, чтобы наше приложение было "наблюдаемым" (observable). Что мы вкладываем в это понятие и так ли это нам необходимо?🔦 Под observability обычно понимается способность системы продюсировать достаточное количество информативных данных о себе, по которым мы можем делать обоснованные выводы о ее состоянии.📝 Такие данные еще называют телеметрией. Это могут быть метрики приложения, логи, трейсы и другие данные, полезные для:- Понимания состояния системы и ее здоровья - Понимания соответствия ее поведения ожидаемому, корректности - Понимания уровня производительности системы - Поиска и локализации неисправностей - Установления хронологии событий при траблшутинге, временных промежутков инцидентов, простоев, отказов - Установления начальной, корневой причины (root cause) неисправностей - Установления длительностей взаимодействия между компонентами
Канал Андрея про бекенд
7 Apr 2025, 10:04
Все еще в шоке, от того что моя аудитория по большей части не пишет на котлин 😁 Но для тех, кто пишет, продолжу делать посты о нем и о корутинах, очень сильно их люблю.📝 Напишите в коментах, почему так сложилось, что не используете котлин или корутины в разработке: может быть что-то понравилось / в компании используют другой язык / просто не было возможности попробовать?
Канал Андрея про бекенд
26 Mar 2025, 08:24

Канал Андрея про бекенд
26 Mar 2025, 08:23
Аналог блокирующей очереди для корутин⛓ В одном из предыдущих постов мы обсуждали удобство использования блокирующий очереди (интерфейс java.util.concurrent.BlockingQueue), для коммуникации между потоками. Одна группа потоков помещают данные в хвост очереди, другая группа получает данные из ее головы.Почему бы нам не использовать такую же очередь для общения корутин друг с другом?🏈 Дело в том, что операции BlockingQueue могут заблокировать поток исполнения:- Получение элемента блокируется, если очередь пуста- Вставка в очередь может блокироваться, если максимальный размер очереди уже достигнут🧨 Но использовать внутри корутин операции, блокирующие поток, антипаттерн. Поэтому, например, существует отдельный набор мьютексов, которые не блокируют поток, а реализуют взаимное исключение именно для корутин.🥁 Есть ли неблокирующий аналог для BlockingQueue в мире корутин? Да,
Канал Андрея про бекенд
5 Mar 2025, 09:04
Последний пост из серии "как ускорить функцию task" 😁⬆️ Напоминаю, мы с вами задавались вопросом, сколько потребуется потоков, чтобы в 10 раз ускорить функцию task, где 5% кода выполняется под локом. Вычисленный с помощью закона Амдала ответ в 20 потоков был позже поставлен под сомнение практическими экспериментами. Сегодня ставим точку в этой серии постов.🧱 Предлагаю немного переработать архитектуру данного нам кода:1. Выделить один отдельный поток, который будет заниматься исключительно препроцессингом данных (функцией prepareData, которая требует исполнения под локом).2. Выделить группу потоков, которая будет заниматься параллельной обработкой подготовленных данных.💡 Какие у нас ожидания производительности от данного рефакторинга?🔎 Вся функция task целиком требует 100ms на выполнение. Функция prepareData занимает 5% этого времени (5ms). Получается, что если поток будет
Канал Андрея про бекенд
19 Feb 2025, 10:36
⬆️ В прошлом посте мы с помощью закона Амдала выясняли, сколько нужно потоков, чтобы ускорить наш код в 10 раз. Полученный ответ, 20 потоков, занял второе место в нашем опросе, но все еще может казаться довольно удивительным.🧑💻 Как и обещал, я провел небольшой эксперимент для проверки теоретических расчетов и постарался найти объяснение полученным на практике результатам.Подробнее об этом, а также о выводах и практических рекомендациях читайте по ссылкеTelegraphПроводим экспериментЧтобы проверить на практике, сколько потребуется потоков в предыдущем кейсе, я написал такой кусочек кода: class Test { private val lock = ReentrantLock(true) private val parallelWorkers = Executors.newFixedThreadPool(1) fun task() { parallelWorkers.submit…
Канал Андрея про бекенд
13 Feb 2025, 13:52
Ответ 20 на предыдущий опрос может быть не очевидным с первого взгляда. Мы получаем его, воспользовшись законом Амдала🧶 Итак, в этом посте будем вычислять ответ ответ, опираясь только на теорию.🎯 Нам нужно увеличить пропускную способность в 10 раз (с 10 операций в секунду до 100). Кажется, что, если один поток может выполнять 10 операций в секунду, то нам нужно увеличить количество потоков пропорционально, до 10.🔩 Однако, в данной задаче есть нюанс, который делает рост производительности не линейным относительно количества потоков. Иными словами, увеличение потоков в 10 раз не дает пропорциональный выигрыш в производительности.🔓 Этим нюансом является наличие функции prepareData, которая требует выполнения под локом. Фактически, функция не параллелизуется. Сколько бы потоков мы не добавили, у нас не получится получить для нее никакой выигрыш, говорит закон Амдала. То есть
Канал Андрея про бекенд
12 Feb 2025, 09:41

Канал Андрея про бекенд
12 Feb 2025, 09:40
🗒 У нас есть следующий фрагмент кода:fun task() { val data = prepareData() process(data) }👀 Функция prepareData производит получение и подготовку данных для их последующей обработки функцией process.🎃 При исполнении на одном потоке функция prepareData занимает 5% времени выполнения, process 95%. Единственный поток позволяет выполнять 10 операций в секунду. Важно отметить, что функция prepare работает с разделяемыми данными и должна выполняться под локом в многопоточной среде.🐌 Наша задача: увеличить пропускную способность, чтобы функция task могла выполняться 100 раз в секунду. Сколько потоков понадобится, чтобы достичь желаемого прироста?🎈 На эту задачу есть несколько правильных ответов. Какие-то можно обосновать теоретическими расчетами, какие-то практическим экспериментом. Но гораздо интереснее, как бы вы стали рассуждать, если бы получили такую задачу на собеседовании.
Related Channels
Other channels in the same section of the catalogue.
