Распределенные системы стали проще

Эта статья изначально была опубликована на моей домашней странице - https://www.kislayverma.com/post/for-the-layman-ep-1-what-is-a-distributed-system

Привет, народ!

Я начинаю новую серию статей под названием «Для непрофессионала», чтобы охватить некоторые часто встречающиеся концепции программной инженерии для не разработчиков или новичков. В статьях с попыткой объяснить эти концепции простым языком, используя как можно меньше жаргона.

В этой первой статье серии давайте разберемся в распределенных системах.

Как следует из названия, распределенная система - это система, компоненты которой распределены. Давайте посмотрим на оба эти слова по отдельности.

Что такое система?

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

Монолиты: нераспределенные системы

Большинство механических систем не распространяются и не могут быть распределены. Компоненты в большинстве аппаратных систем предполагают локальную доступность их партнерских компонентов. Штоки поршней должны быть приварены к коленчатым валам, клавиатуры должны быть подключены к процессорам и т. Д. Созданную на их основе программную систему иногда называют монолитом.

Вертикальное масштабирование

Побочным эффектом размещения всех компонентов рядом друг с другом является то, что для создания более мощной системы нам нужно разместить больше компонентов на одном шасси (так сказать). Если мы хотим добавить больше двигателей, чтобы наша машина могла ехать быстрее, нам нужно добавить двигатель большего размера с большим количеством цилиндров. Это, в свою очередь, требует большой машины и так далее.

Вы также можете подумать о том, чтобы попытаться увеличить мощность своего ноутбука, добавив больше процессоров или больше памяти. Это можно сделать, но ноутбук становится все больше и больше - в конечном итоге мы получаем настольный компьютер, а не ноутбук. Этот процесс увеличения мощности одной физической системы называется вертикальным масштабированием. Это важная стратегия (закон Мура, по сути, касается вертикального масштабирования), но она имеет жесткие физические ограничения, которые очень трудно преодолеть.

Соединение местоположения

Механические системы также предполагают определенную гарантию взаимодействия друг с другом. Не ожидается никакой ненадежности между поворотом шестерни и поворотом стрелки часов (могут быть ошибки точности, но вопрос не в этом). Часы разработаны с предположением, что определенные вещи вызывают определенные события, и если это не так, часы считаются сломанными. Функционирование всей системы сильно зависит от того, что все компоненты всегда физически присутствуют в определенном месте в определенное время. Этот тип шаблона зависимости называется формой тесной связи между компонентами.

Глобально согласованное состояние

Эта жесткая зависимость от всех частей, строго работающих вместе, имеет интересное значение. Это означает, что если мы знаем, в каком состоянии (например, положение, местоположение) находится один компонент, мы обязательно также знаем состояния всех других компонентов. Если компонент A находится не в том положении, которое ожидает компонент B, то у нас есть проблема. В результате наши знания о системе в любой момент времени являются полными и последовательными. Это называется глобальным состоянием.

Как вы уже могли видеть, сложно построить очень большие системы, когда все должно быть размещено в одном месте и должно работать все время. Большая система, построенная с использованием этих принципов, является хрупкой - любой небольшой сбой может привести к полному отключению. Он также не масштабируемый - по мере роста размера мы не только должны постоянно устанавливать все рядом друг с другом (представьте двигатель с тысячами цилиндров, все из которых должны быть рядом друг с другом и должны полностью координироваться), но и должны всегда иметь полное представление обо всех компонентах, чтобы понимать, правильно ли работает система. Когнитивная нагрузка, которую создает такая система, огромна и увеличивается экспоненциально с каждым новым компонентом.

Современная программная архитектура - это не только решение беспрецедентных масштабов, но и решение бизнес-задач. Будь то миллиарды людей, использующих Facebook, или всплеск онлайн-покупателей в День холостяков, сегодня ожидается, что программные системы будут обеспечивать потрясающую производительность и продолжать работать, даже когда части выходят из строя. Для выполнения этих требований распределенные системы возникли как альтернативная парадигма построения систем, построенных из многих компонентов.

Что такое распределенная система?

Сервер: компьютер, подключенный к Интернету или другой сети.

Распределенные системы состоят из «независимых» компонентов, которые не обязательно расположены рядом друг с другом.

Это, казалось бы, простое определение распределенных систем имеет огромные разветвления и придает этим системам их уникальные сильные и слабые стороны. Давайте рассмотрим некоторые из них подробнее.

Прозрачность местоположения

Компоненты в распределенной системе взаимодействуют друг с другом через методы / протоколы, которые не требуют, чтобы вызывающий компонент знал, где находится вызываемый компонент. Таким образом, двигатель потенциально может находиться дома, даже когда вы ведете машину. Каким-то образом при нажатии на акселератор двигатель вырабатывает больше мощности, которая каким-то образом передается на колеса. Другая аналогия - стиль удаленной работы, который мы сейчас видим повсюду. Члены команды физически не находятся вместе, но все же сотрудничают, выполняя свою работу для достижения общей цели.

Это называется прозрачностью местоположения, которая представляет собой форму слабой связи. (Все разработчики смотрят мечтательными глазами, когда слышат это слово - попробуйте!)

Преимущества прозрачности локации очевидны. Если программные компоненты не нужно размещать в одном месте, мы можем переместить их на разные физические машины, каждую из которых затем можно масштабировать по вертикали. То есть мы можем покупать мощные станки для каждого компонента отдельно, вместо того, чтобы устанавливать все компоненты на одном станке. Это напрямую ведет к более мощной системе. Обратите внимание, что мы не требуем, чтобы компоненты располагались на отдельных серверах, просто не имеет значения, где они расположены, если есть способ их разместить.

Как эти распределенные компоненты находят друг друга? Есть много способов сделать это. Одним из самых популярных механизмов является DNS (система доменных имен), который сопоставляет имена с IP-адресами (уникальные идентификаторы серверов во всем Интернете). Основа всей сети - это возможность найти одну конкретную машину по ее IP-адресу или доменному имени. Эта, казалось бы, небольшая (но на самом деле чрезвычайно сложная) техника позволила программному обеспечению поглотить мир.

Режим частичного отказа

Следствием распределенной природы является то, что наш режим отказа больше не является принципом «все или ничего». Компонент устройства чтения карт мог выйти из строя, но компонент управления учетной записью может быть запущен. Это означает, что некоторые функции, связанные с управлением учетной записью, могут по-прежнему быть доступны, даже если наши пользователи, считывающие карты, недовольны.

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

Еще одно следствие прозрачности местоположения состоит в том, что не обязательно должен быть только еще один экземпляр компонента. Если не имеет значения, где расположен двигатель, теперь мы можем добавить десять или более независимых двигателей, чтобы добавить гораздо больше мощности.

При необходимости даже можно добавлять и снимать двигатели с автомобиля. Эта возможность добавлять больше экземпляров компонента называется горизонтальным масштабированием и в настоящее время является предпочтительным механизмом для масштабирования программных систем, поскольку он позволяет обойти физические ограничения, связанные с тем, насколько мощным может быть отдельный сервер - мы просто добавляем ниже -мощность серверов для компенсации.

Итак, у нас есть набор компонентов, находящихся на разных серверах (машинах) и обменивающихся данными по сети (Интернет / LAN). Это оно?

Конечная последовательность

Здесь нужно понять еще одну интересную вещь: сеть ненадежная и медленная.

Если ваш звонок Zoom когда-либо зависал на середине предложения или YouTube буферизовал, вы понимаете, о чем я говорю. Данные передаются от одного компонента к другому, но иногда не достигают его или достигают его через некоторое заметное время. Может быть, провод оборван, может быть, другой компонент считывает данные, но дает сбой, прежде чем он сможет что-нибудь с ними сделать, может быть, по проводу передавалось много данных, и, следовательно, все зависло.

Каким бы образом это ни происходило, это приводит к тому, что разные части системы не имеют полной информации друг о друге. Это происходит постоянно в системах, с которыми мы сталкиваемся в Интернете - платеж был принят, но заказ не может быть размещен (компонент платежа не может взаимодействовать с компонентом заказа), денежный перевод инициируется, но будет отражен через 24 часа (перевод компонент знает, что должен быть перевод, но компонент учетной записи еще не сообщил).

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

Это называется несогласованностью и является другой стороной глобального состояния, с которым мы сталкиваемся в нераспределенных системах. Средством защиты от этого в распределенных системах является конечная согласованность, что означает, что мы должны реализовать механизмы, которые будут гарантировать, что все компоненты в конечном итоге согласятся друг с другом в отношении общего состояния системы. Обратите внимание, что это игра-догонялка, и компоненты рассинхронизированы не по ошибке, а по дизайну. Это дает нам некоторое буферное время, в течение которого мы можем осуществлять передачу знаний вместо того, чтобы мгновенно информировать каждый компонент обо всем (физическая невозможность в распределенном мире, учитывая, что ничто не может двигаться быстрее скорости света).

Плохие части

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

Первая проблема - это пользовательский опыт. Невозможно скрыть от пользователей непротиворечивый характер системы. Поскольку мгновенное удовлетворение становится все более распространенной нормой, иногда может потребоваться много умного UX, чтобы система была распределена и пользователь был доволен.

Распределенная система обязательно намного сложнее монолитной (все в одном месте), чтобы компенсировать ошибки распределенных вычислений. Было разработано множество новых инструментов, помогающих разработчикам создавать надежные распределенные системы, но это все еще далеко не простая или решаемая проблема.

Надеюсь, из этой статьи вы получили общее представление о распределенных системах. Если вы новичок и обнаружили, что некоторые части статьи все еще слишком технические для понимания, дайте мне знать в комментариях, и я постараюсь изложить все проще.

Подпишитесь на мой список рассылки, чтобы получать больше статей из этой серии (и других новостей от меня) прямо в свой почтовый ящик.