0 added
0 removed
Original
2026-01-01
Modified
2026-03-10
1
<p>Не секрет, что сегодня интернет-сервисы подвергаются усиленной нагрузке. Случается, что торговые сети даже<a>останавливают сайты</a>с заказами по причине нехватки имеющихся мощностей. Но если запросы клиентов не обрабатывать или обрабатывать с перебоями, клиенты, разумеется, уйдут к конкурентам. Избежать этого помогут<strong>архитектурные практики</strong>, позволяющие создавать быстрые и отказоустойчивые сервисы. Рассмотрим некоторые из таких паттернов.</p>
1
<p>Не секрет, что сегодня интернет-сервисы подвергаются усиленной нагрузке. Случается, что торговые сети даже<a>останавливают сайты</a>с заказами по причине нехватки имеющихся мощностей. Но если запросы клиентов не обрабатывать или обрабатывать с перебоями, клиенты, разумеется, уйдут к конкурентам. Избежать этого помогут<strong>архитектурные практики</strong>, позволяющие создавать быстрые и отказоустойчивые сервисы. Рассмотрим некоторые из таких паттернов.</p>
2
<h2>Горизонтальное масштабирование</h2>
2
<h2>Горизонтальное масштабирование</h2>
3
<p>Хорошо известное решение. При горизонтальном распределении нагрузки сервисы могут работать параллельно, то есть нагрузку можно распределять. При вертикальном масштабировании в случае повышения нагрузки вам надо заказывать более мощные серверы либо оптимизировать код.</p>
3
<p>Хорошо известное решение. При горизонтальном распределении нагрузки сервисы могут работать параллельно, то есть нагрузку можно распределять. При вертикальном масштабировании в случае повышения нагрузки вам надо заказывать более мощные серверы либо оптимизировать код.</p>
4
<p>Для примера можно взять абстрактное облачное хранилище файлов:</p>
4
<p>Для примера можно взять абстрактное облачное хранилище файлов:</p>
5
<p>Думаю, разница между подходами очевидна: в вертикальном масштабировании мы наращиваем мощность имеющихся узлов, в горизонтальном - добавляем новые узлы, позволяющие распределять нагрузку.</p>
5
<p>Думаю, разница между подходами очевидна: в вертикальном масштабировании мы наращиваем мощность имеющихся узлов, в горизонтальном - добавляем новые узлы, позволяющие распределять нагрузку.</p>
6
<p>Все бы ничего, но горизонтальное масштабирование имеет свои системные сложности. Например, в плане<strong>синхронизации сервисов</strong>. Что будет, когда пользователь сохранит файл с планшета, а потом захочет посмотреть этот файл со смартфона? И так далее.</p>
6
<p>Все бы ничего, но горизонтальное масштабирование имеет свои системные сложности. Например, в плане<strong>синхронизации сервисов</strong>. Что будет, когда пользователь сохранит файл с планшета, а потом захочет посмотреть этот файл со смартфона? И так далее.</p>
7
<h2>CQRS</h2>
7
<h2>CQRS</h2>
8
<p>Command Query Responsibility Segregation - важный архитектурный паттерн, позволяющий различным клиентам как подключаться к разным сервисам, так и получать<strong>одинаковые потоки событий</strong>. Для простого приложения бонусы CQRS могут быть не так очевидны, а вот для нагруженного все с точностью да наоборот. Суть следующая:<strong>входящие и исходящие потоки данных пересекаться не должны</strong>. Грубо говоря, вы отправляете запрос в сервис A, а ответ получаете в сервисе B.</p>
8
<p>Command Query Responsibility Segregation - важный архитектурный паттерн, позволяющий различным клиентам как подключаться к разным сервисам, так и получать<strong>одинаковые потоки событий</strong>. Для простого приложения бонусы CQRS могут быть не так очевидны, а вот для нагруженного все с точностью да наоборот. Суть следующая:<strong>входящие и исходящие потоки данных пересекаться не должны</strong>. Грубо говоря, вы отправляете запрос в сервис A, а ответ получаете в сервисе B.</p>
9
<p>Бонус № 1 - возможность разрыва соединения во время выполнения долгого запроса.</p>
9
<p>Бонус № 1 - возможность разрыва соединения во время выполнения долгого запроса.</p>
10
<p>Возьмем для примера классическую последовательность: 1. Клиент отправляет запрос на сервер. 2. Сервер запускает долгую обработку. 3. Сервер отвечает клиенту, предоставляя результат.</p>
10
<p>Возьмем для примера классическую последовательность: 1. Клиент отправляет запрос на сервер. 2. Сервер запускает долгую обработку. 3. Сервер отвечает клиенту, предоставляя результат.</p>
11
<p>Допустим, в пункте № 2 произошел обрыв связи (или, к примеру, сеть переподключилась либо пользователь перешел на другую страницу, оборвав при этом соединение). В обычной ситуации серверу будет непросто отправить ответ пользователю с данными, что именно обработалось. Если же использовать CQRS, последовательность слегка изменится: 1. Клиент подписывается на обновления. 2. Клиент отправляет запрос на сервер. 3. Сервер отвечает, что "запрос принят". 4. Сервер отвечает результатом, используя для этого канал из пункта "1".</p>
11
<p>Допустим, в пункте № 2 произошел обрыв связи (или, к примеру, сеть переподключилась либо пользователь перешел на другую страницу, оборвав при этом соединение). В обычной ситуации серверу будет непросто отправить ответ пользователю с данными, что именно обработалось. Если же использовать CQRS, последовательность слегка изменится: 1. Клиент подписывается на обновления. 2. Клиент отправляет запрос на сервер. 3. Сервер отвечает, что "запрос принят". 4. Сервер отвечает результатом, используя для этого канал из пункта "1".</p>
12
<p>Эта схема уже сложнее. Мало того, здесь отсутствует интуитивный подход request-response. Зато обрыв связи во время обработки запроса не станет причиной ошибки, что немаловажно. Мало того, если пользователь действительно подключен к сервису сразу с нескольких устройств (к примеру, со смартфона и ПК), то можно сделать так, дабы ответ приходил сразу на 2 устройства.</p>
12
<p>Эта схема уже сложнее. Мало того, здесь отсутствует интуитивный подход request-response. Зато обрыв связи во время обработки запроса не станет причиной ошибки, что немаловажно. Мало того, если пользователь действительно подключен к сервису сразу с нескольких устройств (к примеру, со смартфона и ПК), то можно сделать так, дабы ответ приходил сразу на 2 устройства.</p>
13
<p>Если посмотреть на это с практической точки зрения, мы получим дополнительные бонусы, которые связаны с тем, что однонаправленный поток можно будет<strong>обрабатывать в функциональном стиле</strong>(применяя RX и аналоги). А вот это уже является существенным плюсом, ведь, по сути, программное приложение можно сделать реактивным, причем еще и с использованием функционального подхода. Что уже может сэкономить ресурсы на разработку и техподдержку.</p>
13
<p>Если посмотреть на это с практической точки зрения, мы получим дополнительные бонусы, которые связаны с тем, что однонаправленный поток можно будет<strong>обрабатывать в функциональном стиле</strong>(применяя RX и аналоги). А вот это уже является существенным плюсом, ведь, по сути, программное приложение можно сделать реактивным, причем еще и с использованием функционального подхода. Что уже может сэкономить ресурсы на разработку и техподдержку.</p>
14
<p>Объединив данный подход с горизонтальным масштабированием, мы получим очередной бонус: возможность, позволяющую отправлять запросы на один сервер, а ответы получать от другого сервиса. В результате клиент сможет самостоятельно выбирать более удобный для него сервис, а уже система внутри все равно корректно обработает события.</p>
14
<p>Объединив данный подход с горизонтальным масштабированием, мы получим очередной бонус: возможность, позволяющую отправлять запросы на один сервер, а ответы получать от другого сервиса. В результате клиент сможет самостоятельно выбирать более удобный для него сервис, а уже система внутри все равно корректно обработает события.</p>
15
<p>По материалам<a>блога компании "Технологический Центр Дойче Банка"</a>.</p>
15
<p>По материалам<a>блога компании "Технологический Центр Дойче Банка"</a>.</p>
16
16