From 60c252c339a43c2b43c881fdf09445a999fe73dc Mon Sep 17 00:00:00 2001 From: Struchkov Mark Date: Wed, 2 Oct 2024 21:27:43 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9E=D0=B1=D0=BD=D0=BE=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5=20dev=20=D0=B7=D0=B0=D0=BC=D0=B5=D1=82=D0=BE?= =?UTF-8?q?=D0=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dev/architecture/Event Loop.md | 31 ++++++++--- dev/architecture/Архитектурная концепция.md | 8 +++ dev/architecture/Блокирующий вызов.md | 13 +++-- dev/architecture/Бэкенд.md | 2 +- .../Много клиентов — один поток.md | 45 ++++++++++++++++ dev/architecture/Один клиент — один поток.md | 52 +++++++++++++++++++ dev/fundamental/Переключение контекста.md | 3 ++ meta/people/Стручков Марк.md | 8 ++- meta/zero/00 HighLoad.md | 3 ++ 9 files changed, 151 insertions(+), 14 deletions(-) create mode 100644 dev/architecture/Много клиентов — один поток.md create mode 100644 dev/architecture/Один клиент — один поток.md diff --git a/dev/architecture/Event Loop.md b/dev/architecture/Event Loop.md index 650927a1..4ddb9159 100644 --- a/dev/architecture/Event Loop.md +++ b/dev/architecture/Event Loop.md @@ -1,5 +1,7 @@ --- -aliases: +aliases: + - событийного цикла + - событийный цикл tags: - maturity/🌱 date: 2023-10-26 @@ -9,16 +11,31 @@ parents: - "[[Реактивное программирование]]" linked: --- -По сути, Event Loop - это реализация [шаблона Reactor](http://design-pattern.ru/patterns/reactor.html). Является неблокирующим потоком ввода-вывода, который работает непрерывно. Его основная задача — проверка новых событий. И как только событие пришло перенаправлять его тому, кто в данный момент может его обработать. Иногда их может быть несколько для увеличения производительности. +**Event loop** (цикл событий) — это фундаментальная концепция в асинхронном программировании, которая позволяет системе обрабатывать большое количество задач без создания множества [[../fundamental/Поток процесса ОС|потоков]]. + +По сути, Event Loop - это реализация [шаблона Reactor](http://design-pattern.ru/patterns/reactor.html). Он используется в языках и фреймворках, которые должны обрабатывать большое количество операций [[../../../../_inbox/Ввод-вывод|ввода-вывода]] (I/O) эффективно, минимизируя затраты на создание и управление потоками. Цикл событий стал особенно популярным в таких технологиях, как JavaScript (Node.js), Python (asyncio), и современных реактивных фреймворках на Java (Vert.x, [[../../meta/zero/00 Quarkus|Quarkus]]). + +Цикл событий представляет собой непрерывную петлю, которая ожидает появления событий, таких как запросы клиентов, завершение операций I/O, сигналы от системных ресурсов и другие задачи. Когда событие происходит, цикл событий вызывает соответствующий обработчик, который выполняется без блокировки основной петли ([[../../../../_inbox/Не блокирующийся ввод-вывод|неблокирующийся ввод-вывод]]). ![](../../meta/files/images/Pasted%20image%2020231026115508.png) -Выше приведён абстрактный дизайн цикла событий, который представляет идеи реактивного асинхронного программирования: +Основные шаги работы event loop: +1. **Ожидание событий.** Цикл событий ожидает появления новых задач (например, клиентских запросов, ответов от базы данных, сообщений от других сервисов). +2. **Помещение задачи в очередь.** Когда событие происходит (например, пришел запрос от клиента), оно добавляется в очередь задач, ожидающих обработки. +3. **Выполнение задачи.** Цикл событий начинает обработку задачи, извлекая её из очереди и вызывая соответствующий обработчик. +4. **Завершение задачи.** Когда задача завершена (например, отправлен ответ клиенту), цикл переходит к следующему событию в очереди. + +**Преимущества** +- **Эффективное использование ресурсов.** Event loop позволяет системе обрабатывать большое количество запросов без необходимости создания множества потоков. Это снижает накладные расходы на память и процессорное время. +- **Масштабируемость.** Благодаря асинхронной модели, event loop может обрабатывать сотни тысяч запросов одновременно, что делает его идеальным решением для [[../../meta/zero/00 HighLoad|высоконагруженных систем]]. +- **Неблокирующее выполнение.** В отличие от традиционных моделей, где операции ввода-вывода блокируют поток ([[Блокирующий вызов]]), в модели event loop такие операции выполняются асинхронно, освобождая поток для выполнения других задач. +- Минимум [[../fundamental/Переключение контекста|контекстных переключений]]. Цикл событий снижает количество переключений между потоками, что снижает накладные расходы на переключение контекста и увеличивает производительность. + +**Недостатки** +- **Ограниченная поддержка CPU-ориентированных задач.** Модель event loop идеально подходит для операций ввода-вывода, но для задач, требующих интенсивных вычислений, такая модель не так эффективна. В таком случае ==поток может быть занят длительное время, блокируя выполнение других задач.== +- **Сложность управления.** Асинхронные операции требуют управления состояниями и корректной обработки событий, что усложняет разработку и отладку. ==Ошибки в одном обработчике могут затронуть другие запросы, обрабатываемые тем же циклом событий.== +- **“Заблокированный” цикл.** Если цикл событий заблокирован долгой синхронной операцией, это может затормозить выполнение всех задач, так как весь поток будет занят одной задачей. -- Цикл событий выполняется непрерывно в одном потоке, хотя у нас может быть столько циклов событий, сколько доступно [[../fundamental/Ядро процессора|ядер]]. -- Цикл событий последовательно обрабатывает события из очереди событий и возвращается сразу после регистрации [[../../../../_inbox/Callback|обратного вызова]] в платформе. -- Платформа может инициировать завершение операции, такой как вызов базы данных или вызов внешней службы. -- Цикл событий может запускать обратный вызов при уведомлении о завершении операции и отправлять результат обратно исходному вызывающему. *** ## Мета информация **Область**:: [[../../meta/zero/00 Архитектура ПО|00 Архитектура ПО]] diff --git a/dev/architecture/Архитектурная концепция.md b/dev/architecture/Архитектурная концепция.md index 47dd91ba..7666b69f 100644 --- a/dev/architecture/Архитектурная концепция.md +++ b/dev/architecture/Архитектурная концепция.md @@ -9,6 +9,8 @@ parents: linked: --- - [[Inversion of Control]] +- [[Один клиент — один поток]] +- [[Много клиентов — один поток]] *** ## Мета информация **Область**:: [[../../meta/zero/00 Архитектура ПО|00 Архитектура ПО]] @@ -21,3 +23,9 @@ linked: ### Дочерние заметки + +- [[Inversion of Control]] +- [[Паттерн программирования]] +- [[Один клиент — один поток]] +- [[Много клиентов — один поток]] + diff --git a/dev/architecture/Блокирующий вызов.md b/dev/architecture/Блокирующий вызов.md index 1ea19cec..4b3b61d8 100644 --- a/dev/architecture/Блокирующий вызов.md +++ b/dev/architecture/Блокирующий вызов.md @@ -9,11 +9,12 @@ tags: - maturity/🌱 date: - - 2024-01-28 + - - 2024-04-13 zero-link: - "[[../../meta/zero/00 Архитектура ПО|00 Архитектура ПО]]" parents: linked: - - "[[Бэкенд большую часть времени ждет]]" + - "[[Блокирующий вызов]]" --- Блокирующий вызов блокирует [поток](../fundamental/Поток%20процесса%20ОС.md) до того момента, как будут-получены данные. Во время блокировки [процесс](../fundamental/Процесс%20ОС.md) не потребляет процессорное время, но потребляет память. Например, для выполнения запроса к БД из пула потоков берётся поток, далее он ожидает, пока БД выполнит запрос и вернёт результат. @@ -24,7 +25,11 @@ linked: ## Почему простаивание потока — это проблема? Каждый поток нуждается в памяти для хранения своего стека вызовов и других связанных с ним структур данных. ==Когда поток простаивает, он продолжает потреблять ресурсы для поддержания своего состояния.== -Кроме того, процессорное время, которое выделяется неработающим потокам, могло бы быть использовано для других задач. Если большое количество потоков простаивает, это может привести к увеличению загрузки процессора и снижению производительности, так как операционная система будет тратить больше времени на переключение между потоками. +Кроме того, процессорное время, которое выделяется неработающим потокам, могло бы быть использовано для других задач. Если большое количество потоков простаивает, это может привести к увеличению загрузки процессора и снижению производительности, так как операционная система будет тратить больше времени на [[../fundamental/Переключение контекста|переключение между потоками]]. + +![](../../meta/files/images/Pasted%20image%2020240413205842.png) + +Если посмотреть на соотношение скорости [[../fundamental/Центральный процессор|процессора]] и возможности сетевых соединений, то отличия – на пару порядков. Например, на этом слайде сжатие 1 Кб данных занимает 3 мкс, в то время как round trip в одну сторону даже внутри одного дата-центра – это уже 0,5 мс. Любое сетевое взаимодействие, которое нужно бэкенду (например, отправка запроса в БД), потребует, как минимум 2х round trip-ов и по сравнению с тем процессорным временем, которое он тратит на обработку данных, – это совершенно незначительно. Большую часть времени обработки запроса [бэкенд](Бэкенд.md) ничего не делает, просто ждет. ## Заметки - Чтение с диска в linux может быть только блокирующим. *** @@ -34,7 +39,5 @@ linked: **Источник**:: **Автор**:: **Создана**:: [[2024-01-28]] -### Дополнительные материалы -- [[../../../../_inbox/Бэкенд большую часть времени ждет|Бэкенд большую часть времени ждет]] ### Дочерние заметки - + \ No newline at end of file diff --git a/dev/architecture/Бэкенд.md b/dev/architecture/Бэкенд.md index f0f92347..1defd8e7 100644 --- a/dev/architecture/Бэкенд.md +++ b/dev/architecture/Бэкенд.md @@ -26,6 +26,6 @@ linked: **Автор**:: **Создана**:: [[2024-04-13]] ### Дополнительные материалы -- [[../../../../_inbox/Бэкенд большую часть времени ждет|Бэкенд большую часть времени ждет]] +- [[Блокирующий вызов|Блокирующий вызов]] ### Дочерние заметки diff --git a/dev/architecture/Много клиентов — один поток.md b/dev/architecture/Много клиентов — один поток.md new file mode 100644 index 00000000..80c403e0 --- /dev/null +++ b/dev/architecture/Много клиентов — один поток.md @@ -0,0 +1,45 @@ +--- +aliases: +tags: + - maturity/🌱 +date: 2024-10-02 +zero-link: + - "[[../../meta/zero/00 Архитектура ПО|00 Архитектура ПО]]" +parents: + - "[[Архитектурная концепция]]" +linked: +--- +Концепция “много клиентов — один поток” предполагает, что один [[../fundamental/Поток процесса ОС|поток]] может обрабатывать множество клиентских запросов. Это возможно благодаря асинхронному или [[../../../../_inbox/Событийно-ориентированное программирование|событийно-ориентированному подходу]], где поток не привязывается к одному запросу, а может переключаться между задачами в зависимости от их состояния (например, ожидания данных). Такой подход широко используется для решения проблем масштабируемости и производительности в современных [[../../meta/zero/00 HighLoad|высоконагруженных системах]]. + +В отличие от модели “[[один клиент — один поток]]”, где для каждого запроса создается отдельный поток, в модели “много клиентов — один поток” используется один или ограниченное количество потоков для обслуживания множества клиентов. Этот подход достигается за счет использования [[../../../../_inbox/Не блокирующийся ввод-вывод|неблокирующего ввода/вывода]] (non-blocking I/O) и [[Event Loop|событийного цикла]]. Когда клиентский запрос инициирует операцию, например обращение к базе данных, поток может освободиться и перейти к следующей задаче, вместо того чтобы блокироваться и ждать завершения операции. + +Обычно используется неблокирующая модель обработки событий: когда запрос клиента инициируется, он может находиться в очереди событий и быть выполнен в момент, когда необходимые ресурсы будут готовы, при этом один поток обрабатывает множество событий последовательно или параллельно. + +**Плюсы подхода** +- **Масштабируемость.** Один из ключевых плюсов модели — значительно лучшая масштабируемость по сравнению с моделью “один клиент — один поток”. Благодаря неблокирующему вводу/выводу и использованию небольшого количества потоков, такие системы могут обрабатывать тысячи и даже миллионы клиентских запросов, не создавая избыточного потребления ресурсов. +- **Эффективное использование ресурсов.** Один поток может выполнять множество задач последовательно, освобождаясь от блокировки в ожидании внешних ресурсов (например, базы данных или сети). Это позволяет максимально эффективно использовать доступные системные ресурсы, такие как память и процессорное время. +- Меньше [[../fundamental/Переключение контекста|контекстных переключений]]. Поскольку количество потоков минимально, система тратит меньше времени на контекстные переключения, что снижает накладные расходы на процессор и повышает общую производительность. +- **Высокая производительность при высоких нагрузках.** Эта модель отлично подходит для [[../../meta/zero/00 HighLoad|высоконагруженных систем]], таких как веб-сервера, системы обработки сообщений и стриминговые платформы, где каждый клиент может генерировать множество мелких запросов. + +**Минусы подхода** +- **Сложность реализации.** Асинхронная модель требует более сложной архитектуры и управления состояниями. Разработчикам нужно работать с обратными вызовами (callbacks) или реактивными потоками, что увеличивает сложность кода и повышает риск ошибок. +- **Отладка и поддержка.** Из-за использования асинхронности и событийной обработки отладка таких систем может быть сложнее. Потоки могут переключаться между задачами в произвольные моменты времени, что затрудняет поиск и исправление ошибок. +- **Изоляция ошибок.** Если происходит ошибка в одном потоке, она может повлиять на множество запросов, поскольку один поток обслуживает сразу несколько клиентов. В таких случаях важно предусмотреть механизмы обработки ошибок и защиты от сбоев. + +**Кто использует этот подход** +- [[../../../../wiki/zero/00 Nginx|Nginx]]. Один из самых известных примеров событийно-ориентированного сервера, использующий асинхронный подход. Nginx эффективно обрабатывает множество клиентских запросов с минимальными затратами ресурсов. +- **Node.js.** Однопоточная архитектура с использованием событийной петли, которая позволяет одному потоку обрабатывать множество запросов одновременно. Node.js широко применяется для построения масштабируемых серверов и микросервисов. +- Vert.x и [[../../meta/zero/00 Quarkus|Quarkus]]. Эти фреймворки используют реактивные подходы для обработки запросов, обеспечивая высокую производительность и асинхронную обработку данных в [[../../../../wiki/zero/Микросервисная архитектура|микросервисной архитектуре]]. +- Netty. Асинхронный сетевой фреймворк, который широко используется для создания высокопроизводительных сетевых приложений на Java, таких как серверы и клиентские приложения. +*** +## Мета информация +**Область**:: [[../../meta/zero/00 Архитектура ПО|00 Архитектура ПО]] +**Родитель**:: [[Архитектурная концепция]] +**Источник**:: +**Создана**:: [[2024-10-02]] +**Автор**:: +### Дополнительные материалы +- [[Один клиент — один поток]] + +### Дочерние заметки + diff --git a/dev/architecture/Один клиент — один поток.md b/dev/architecture/Один клиент — один поток.md new file mode 100644 index 00000000..63b58efc --- /dev/null +++ b/dev/architecture/Один клиент — один поток.md @@ -0,0 +1,52 @@ +--- +aliases: +tags: + - maturity/🌱 +date: 2024-10-02 +zero-link: + - "[[../../meta/zero/00 Архитектура ПО|00 Архитектура ПО]]" +parents: + - "[[Архитектурная концепция]]" +linked: +--- +“Один клиент — один поток” — это концепция обработки запросов, в которой для каждого клиента или запроса выделяется отдельный [[../fundamental/Поток процесса ОС|поток]] выполнения. Этот подход исторически использовался в многопоточных серверных архитектурах для обработки клиентских соединений. Концепция проста в реализации и часто применяется в традиционных системах, однако с ростом нагрузки и требованиями к масштабируемости начинают проявляться ее недостатки. + +Суть концепции заключается в том, что на каждый новый клиентский запрос создается отдельный поток в системе. ==Этот поток обрабатывает запрос от начала до конца==, включая этапы получения данных, выполнения логики и возврата ответа клиенту. Как только запрос обработан, поток освобождается или завершает выполнение. Таким образом, каждый клиент имеет свой “личный” поток выполнения, изолированный от других клиентов. + +**Плюсы** +- **Простота реализации.** Каждый запрос выполняется в отдельном потоке, что делает архитектуру интуитивно понятной для разработчиков. Легче управлять состоянием внутри потока, так как нет необходимости беспокоиться о синхронизации между потоками. +- **Изоляция ошибок.** Ошибка, возникшая в одном потоке, как правило, не затрагивает другие потоки. Это снижает риск влияния одного сбойного запроса на остальные. +- **Четкое распределение ресурсов.** При каждом запросе сервер выделяет четко определённое количество ресурсов (один поток), что может упростить мониторинг и управление системой. + +**Недостатки** +- **Проблемы с масштабируемостью.** Основной недостаток концепции — это плохая масштабируемость. Потоки требуют выделения значительных системных ресурсов, таких как память и процессорное время. При увеличении числа клиентов нагрузка на процессор и оперативную память возрастает, а также увеличивается количество контекстных переключений между потоками, что снижает общую производительность системы. +- **Потребление ресурсов.** Для каждого клиента выделяется не только поток, но и сопутствующие ресурсы, такие как стеки вызовов, которые могут занимать значительное количество памяти. Системы, работающие с тысячами или миллионами клиентов, могут столкнуться с исчерпанием ресурсов. +- [[../fundamental/Переключение контекста|Переключение контекста]] Каждый раз, когда система переключается между потоками, происходит контекстное переключение, которое добавляет накладные расходы на процессор. Эти переключения могут значительно замедлять работу системы при большом количестве потоков. +- [[Блокирующий вызов|Блокирующий вызов]]. Даже если клиентский запрос простаивает (например, ожидает ответа от базы данных или другого сервиса), поток остается занятым и не может быть использован для других задач, что приводит к неэффективному использованию ресурсов. + +**Кто использует этот подход** +Подход “один клиент — один поток” использовался в ранних версиях популярных серверов и библиотек: + +- **Apache HTTP Server (классический режим работы).** В старых конфигурациях Apache каждый запрос обрабатывался отдельным потоком или процессом. +- **Tomcat (до перехода на NIO).** В классическом Tomcat для каждого HTTP-запроса создавался отдельный поток для его обработки. + +Однако с ростом числа пользователей и нагрузки такие серверы начали испытывать проблемы с производительностью. Поэтому многие современные серверы перешли к более эффективным асинхронным моделям обработки запросов. + +**Современные альтернативы** +С ростом масштабов приложений, особенно в веб-разработке, стали популярны асинхронные и реактивные подходы, где один поток может обслуживать множество клиентов, не создавая новый поток для каждого запроса. Такие подходы позволяют лучше использовать ресурсы системы: + +- **Асинхронные модели.** Серверы, такие как [[../../../../wiki/zero/00 Nginx|Nginx]], используют [[../../../../_inbox/Событийно-ориентированное программирование|событийно-ориентированную архитектуру]], где запросы обрабатываются без необходимости создавать новый поток на каждый запрос. Это снижает потребление памяти и улучшает масштабируемость. +- [[../../../../knowledge/dev/Реактивное программирование|Реактивное программирование]]. В таких фреймворках, как [[../../meta/zero/00 Quarkus|Quarkus]], Vert.x или [[../../meta/zero/00 SpringBoot|Spring]] WebFlux, запросы обрабатываются асинхронно с использованием реактивных потоков, что позволяет эффективно распределять ресурсы даже при высокой нагрузке. + +*** +## Мета информация +**Область**:: [[../../meta/zero/00 Архитектура ПО|00 Архитектура ПО]] +**Родитель**:: [[Архитектурная концепция]] +**Источник**:: +**Создана**:: [[2024-10-02]] +**Автор**:: +### Дополнительные материалы +- [[Много клиентов — один поток]] + +### Дочерние заметки + diff --git a/dev/fundamental/Переключение контекста.md b/dev/fundamental/Переключение контекста.md index 3755f164..508f4968 100644 --- a/dev/fundamental/Переключение контекста.md +++ b/dev/fundamental/Переключение контекста.md @@ -5,6 +5,9 @@ aliases: - переключение контекстов - переключения контекста - переключению контекста + - Контекстные переключения + - переключение между потоками + - контекстных переключений tags: - maturity/🌱 date: diff --git a/meta/people/Стручков Марк.md b/meta/people/Стручков Марк.md index 8e14ace5..c54bf283 100644 --- a/meta/people/Стручков Марк.md +++ b/meta/people/Стручков Марк.md @@ -8,7 +8,11 @@ description: Эта страница рассказывает обо мне, к > [!INFO] HR > Если вы HR специалист, то писать с предложениями о работе сюда [👉 Career](https://career.habr.com/upagge) -## 💼 Коротко о работе +## Короткая автобиография +Моё знакомство с миром технологий началось в раннем возрасте. С 13 лет я увлекся разработкой сайтов на платформе uCoz, что привело к самостоятельному изучению HTML и CSS. Это хобби со временем переросло в страсть к технологиям и программированию. + +В университете я продолжил своё развитие в этом направлении, начав помогать однокурсникам с лабораторными работами по программированию. Уже к концу первого курса я нашел единомышленников и запустил сайт для помощи студентам из различных вузов, который включал интернет магазин с возможностью онлайн оплаты. Но к концу третьего курса я решил завершить этот проект, чтобы сосредоточиться на своём профессиональном и карьерном росте. +## 💼 Коротко о карьере Мой основной язык программирования – Java. ==Развиваюсь в основном в направлении backend разработки и DevOps==: могу написать свой [SSO сервер с использованием Oauth2](https://struchkov.dev/blog/ru/how-oauth2-works/), написать библиотеку для реализации ABAC, написать сервис для хранения файлов с использованием MinIO S3. C декабря 2021 года активно осваиваю и [использую в работе Quarkus](https://struchkov.dev/blog/ru/tag/quarkus/) для написания микросервисов в реактивном стиле 🚀 Во фронт не лезу, не мое это, но могу немного в HTML и CSS. Также мне нравятся задачи связанные с DevOps: могу [настроить полный CI/CD](https://struchkov.dev/blog/ru/java-gitlab-cicd/), упаковать приложение в Docker и написать DockerCompose, [оптимизировать работу nginx](https://struchkov.dev/blog/ru/nginx-optimization/), или [создать собственную домашню экосистему облачных сервисов](https://struchkov.dev/blog/ru/raspberry-home-cloud-services-ecosystem/). @@ -21,6 +25,8 @@ description: Эта страница рассказывает обо мне, к > [!INFO] Подробнее о работе в резюме > [Struchkov Mark | Java Developer](https://mark.struchkov.dev/cv) + +- [[../../Мое рабочее место|Мое рабочее место]] ## Публичная активность ### ✏️ B.log В какой-то момент у меня появилось непреодолимое желание писать, а так как я умею программировать, то решил что самое время завести блог по программированию. Это мой основной блог, на него уходит большая часть творческих ресурсов. diff --git a/meta/zero/00 HighLoad.md b/meta/zero/00 HighLoad.md index 0ddd2e1c..4ef55d50 100644 --- a/meta/zero/00 HighLoad.md +++ b/meta/zero/00 HighLoad.md @@ -6,6 +6,9 @@ parents: title: HighLoad aliases: - HighLoad + - высоконагруженных системах + - высоконагруженная система + - высоконагруженных систем --- ## Что такое HighLoad? Например, один запрос в секунду – это нагрузка явно не highload, любой сервер, вроде бы, справится. Но, например, если он перекодирует видеоролики, то тут может наступить highload.