HTML Diff
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