Горизонтальное масштабирование

Самый простой и всем известный пункт. Условно, наиболее часто встречаются две схемы распределения нагрузки — горизонтальное и вертикальное масштабирования. В первом случае вы позволяете сервисам работать параллельно, тем самым распределяя нагрузку между ними. Во втором вы заказываете более мощные серверы или оптимизируете код.

Для примера я возьму абстрактное облачное хранилище файлов, то есть некоторый аналог OwnCloud, OneDrive и так далее.

Стандартная картинка подобной схемы ниже, однако она лишь демонстрирует сложность системы. Ведь нам необходимо как-то синхронизовать сервисы. Что будет, если с планшета пользователь сохранил файл, а потом хочет его посмотреть с телефона?

Разница между подходами: в вертикальном масштабировании мы готовы наращивать мощность узлов, а в горизонтальном — добавлять новые узлы, чтобы распределить нагрузку.

CQRS

Command Query Responsibility Segregation довольно важный паттерн, так как он позволяет разным клиентам не только подключаться к разным сервисам, но и также получать одинаковые потоки событий. Его бонусы не столь очевидны для простого приложения, однако он крайне важен (и прост) для нагруженного сервиса. Его суть: входящие и исходящие потоки данных не должны пересекаться. То есть вы не можете отправить запрос и ожидать ответ, вместо этого вы отправляете запрос в сервис A, однако получаете ответ в сервисе Б.

Первый бонус этого подхода — возможность разрыва соединения (в широком смысла этого слова) в процессе выполнения долгого запроса. Для примера возьмем более-менее стандартную последовательность:

  1. Клиент отправил запрос на сервер.
  2. Сервер запустил долгую обработку.
  3. Сервер ответил клиенту результатом.

Представим, что в пункте 2 произошел обрыв связи (или сеть переподключилась, или пользователь перешёл на другую страницу, оборвав соединение). В этом случае серверу будет сложно отправить ответ пользователю с информацией, что именно обработалось. Применяя CQRS, последовательность будет немного иной:

  1. Клиент подписался на обновления.
  2. Клиент отправил запрос на сервер.
  3. Сервер ответил «запрос принят».
  4. Сервер ответил результатом через канал из пункта «1».