Amazon Web Services - одна из наиболее часто используемых инфраструктур при разработке программного обеспечения. Большое количество сервисов и инструментов делает эту систему предпочтительной. Несмотря на то, что она считается одной из самых дорогих, постоянное обслуживание и улучшение системы печально известны качеством и поддержкой утилит, которые выделяют ее среди остальных конкурентов.

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

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

Первый этап: все на месте

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

Для удаленного доступа к системе обычно используются виртуальные машины в облаке, или, как я люблю их называть: чужие компьютеры, которые настроены так же, как если бы они были нашими, устанавливая контроль над SSH-соединением. В AWS они называются инстансами EC2. Мы можем назначить этим машинам конфигурацию оборудования, выбирая от количества ядер до емкости хранилища, мы также можем установить необходимое программное обеспечение в качестве операционной системы и зависимостей, используемых нашим приложением, в конечном итоге мы добавляем базу данных, и мы также можем предоставить фиксированный адрес доступа через услугу Эластичный IP. В случае, если мы хотим приобрести домен и настроить его свойства, мы также можем сделать это через сервис Route 53.

За 10 долларов в месяц наше приложение будет работать в облаке. На диаграмме ниже представлены вышеупомянутые концепции. В случае, если мы работаем с несколькими средами, AWS позволяет создавать экземпляры EC2 из образов или реплик других существующих, что означает, что всего за несколько щелчков мышью у нас будут готовы соответствующие среды.

Вторая фаза: серьезно

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

  • Отказоустойчивость
  • Резервные копии базы данных
  • Представление
  • Масштабируемость

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

AWS предлагает услуги, специально предназначенные для управления большинством известных баз данных. Он имеет AWS RDS для управления реляционными базами данных, а также сервис под названием DynamoDB для баз данных NoSQL. Если мы полагаемся на использование кеширования, Amazon предоставляет Elastic Cache для его обработки. Этими службами можно полностью управлять с веб-консоли, где можно масштабировать уровень данных по вертикали, выбирая, например, тип и пространство для хранения или оптимизированный объем ОЗУ для чтения / записи. А также по горизонтали за счет увеличения количества читаемых реплик.

После применения этой первой развязки архитектура будет представлена ​​следующим образом:

Давайте сосредоточимся на ранее созданном экземпляре EC2. Если мы настроили очень маленький экземпляр, в котором выполняется большая обработка, и несколько пользователей одновременно решают использовать нашу систему, очевидно, что будет превышение емкости ресурсов, и система выйдет из строя. Простым способом решения этой проблемы может быть вертикальное масштабирование нашего экземпляра, обеспечивающее большую мощность оборудования с несколькими ГБ памяти, лучшим процессором, и с этим мы будем жить. Теперь предположим, что наш экземпляр EC2 подвергается неожиданному падению из-за неправильного развертывания или неожиданного перезапуска, или мы просто забыли увеличить план сервера, и экземпляр превышает его емкость. Это сделает всю нашу систему недоступной для пользователей, что недопустимо для производственного ПО. Нам нужно, чтобы наша система была отказоустойчивой.

Мы добавим в формулу новые экземпляры, так что они будут точными копиями работающего кода, и любой из них сможет выполнить запрос, помимо совместного использования одного уровня базы данных, новые экземпляры будут обрабатывать один и тот же набор информации.
С точки зрения потребителя, потребляющего данные, мы не хотим иметь адрес для каждого экземпляра, поэтому создается единая точка доступа с помощью балансировщика нагрузки. Эта функция, предоставляемая AWS Load Balancer, распределяет трафик через настроенные экземпляры, а также отвечает за определение статуса каждого из них, чтобы отправлять запросы только тем экземплярам, ​​которые кажутся работоспособными.

Если мы не знакомы со средой Amazon, такое количество услуг может вызвать множество проблем. Поэтому, чтобы не сбиться с ритма, мы добавим к этому последнему этапу еще один сервис: AWS Elastic Beanstalk. Этот сервис является связующим звеном всего вышеупомянутого и обеспечивает мониторинг и управление средой, где можно управлять различными компонентами, а также контролировать версии и выпуски. Нам просто нужно настроить стек нашей системы, а AWS позаботится обо всем остальном.
Если добавить эти новые концепции, диаграмма будет выглядеть так:

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

Третий этап: это уже успех

В соответствии с предыдущей моделью наша система в большинстве случаев будет подготовлена ​​для поддержки больших объемов данных и тысяч пользователей. Но это еще не все, он, естественно, будет продолжать расти, и если мы будем следовать той же схеме ссылок на пользователей, давайте посмотрим, что нам нужно сделать для поддержки примерно 100–500 тысяч пользователей.

Возникает вопрос: как определить необходимое количество экземпляров? Мы не хотим без надобности добавлять новые экземпляры и переносить расходы на облака. Чтобы контролировать эту ситуацию, Amazon предлагает услугу Auto Scaling, которая отвечает за поддержание минимального количества инстансов для обеспечения производительности, необходимой для нашей системы. Для этого настраиваются определенные показатели, которые работают как условия для добавления или удаления экземпляров сервера, например, использование ЦП и потребление сети. Таким образом, несколько экземпляров используются, когда серверы простаивают, и их количество увеличивается, когда потребность в обработке высока.

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

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

В инфраструктуре Amazon есть кое-что интересное: ее серверы расположены в нескольких странах мира, что позволяет предоставлять их услуги более чем в одном месте одновременно. Именно здесь вступает в игру концепция зон доступности, которая позволяет реплицировать наши серверы и компоненты баз данных по всему миру. К счастью, достаточно простой настройки, чтобы все заработало.

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

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

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

Используя S3, мы достигаем другого уровня развязки, инкапсулируя статическую информацию в отдельную среду, при этом путь к файлам является тем, что мы должны сохранить в качестве точки доступа от других компонентов. Он также часто используется в сочетании с AWS Cloudfront, поэтому файлы, о которых идет речь, доставляются с использованием самых быстрых политик доставки.
Со всеми этими новыми компонентами наша обновленная архитектура, показанная на диаграмме ниже, должна быть достаточно прочной, чтобы поддерживать 500 КБ. пользователей.

Четвертый этап: и что теперь!

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

Что касается внутреннего мониторинга системы, Amazon предлагает CloudWatch для ретрансляции информации о работе каждой службы. Предоставляет метрики, соответствующие каждой ситуации, которые позволяют пользователю определять действия, которые необходимо предпринять, или просто поддерживать контроль состояния. Например, для экземпляров EC2 вы можете в любое время просмотреть использование ЦП и потребление сети, и с помощью этой информации мы можем лучше адаптировать тип экземпляра, который нам нужен для обработки запросов. Также можно определить поведение, посмотрев на графики, созданные при определенных обстоятельствах.

Другой аспект, который должен нас беспокоить на данном этапе, - это постоянные данные. Очень вероятно, что системе придется обрабатывать миллионы записей из базы данных, создавая новое узкое место в потоке информации. Наступит время, когда ни один из самых дорогих экземпляров не приведет к значительным изменениям во времени выполнения запросов, чего и следовало ожидать. К тому времени мы должны рассматривать информацию с помощью концепции BigData, и, если мы еще не сделали этого раньше, самое время перенести данные в нереляционную модель. Как упоминалось ранее, Amazon предоставляет DynamoDB в качестве официальной системы баз данных NoSQL.

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

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

Пятый этап: мы можем пойти еще дальше

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

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

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

При переводе на инфраструктуру Amazon мы включим сервис под названием AWS SQS (Simple Queue Service), обеспечивающий работу описанных выше очередей сообщений. С веб-консоли создаются и отслеживаются очереди и сообщения. SQS обеспечивает устойчивость и надежность, а также важные меры безопасности, так что сообщения могут содержать любую конфиденциальную информацию. С другой стороны, процессы, которые выполняют задачи в фоновом режиме, могут быть настроены для работы очень простым способом через среду Elastic Beanstalk, которая связывает экземпляры, которые были ранее созданы с этими демонами. Вдобавок Beanstalk также обрабатывает связь между ними и очередями. Наша работа будет просто заключаться в том, чтобы запрограммировать действия, которые необходимо предпринять при обработке сообщения из очереди.

Если операция и логика, связанные с использованием очередей сообщений и демонов, не соответствуют нашим целям или, может быть, мы ищем более конкретные действия, в облаке Amazon есть еще один отличный продукт, который может быть полезен: AWS Lambda. Это служба, цель которой - запускать запланированные задачи, подпрограммы, сценарии или аналогичные действия на основе возникновения событий, вызывающих выполнение асинхронно с работой главного сервера. Пока что звучит очень похоже на SQS, но идея состоит в том, чтобы выполнять вычисления немедленно, а не накапливать их, кроме того, конфигурация и связь с другими компонентами намного более прямолинейны. Основное использование продукта - загрузка определенного кода в облако Amazon, а AWS Lambda отвечает за предоставление инфраструктуры, необходимой для правильной работы нашего кода. Затем событие, которое может происходить из нашей собственной системы или извне, вызовет рассматриваемый код. Его также можно использовать в качестве конечной точки API при объединении с Amazon API Gateway, где при отправке простого HTTP-сообщения также будут выполняться функции.

На следующем изображении показана обновленная архитектура с новыми последствиями.

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

Цель состоит в том, чтобы интегрировать концепции федерации и сегментирования в базу данных. Первый - разделить одну модель данных на несколько, чтобы она могла работать с отдельными базами данных и, таким образом, разделить операции записи между несколькими узлами. Запросы могут выполняться через одну систему или включать несколько, при этом в обоих случаях необходимо соблюдать соединение каждого компонента. Несомненно, предстоит большая работа как по выполнению этого разделения, так и по сбору информации из разных источников, но каждую подсистему можно масштабировать независимо, и мы будем устранять узкие места в основном во время вставки данных.
Вкратце вторая концепция сегментирования словами разбиение таблиц по строкам. Из исходной таблицы будет создано несколько таблиц, каждая из которых будет содержать часть общих данных. На практике создается справочная таблица, содержащая «shardId», который указывает раздел, содержащий остальные данные. Это гарантирует выполнение запросов к меньшим наборам данных за счет оптимизации времени чтения в инфраструктуре.

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

На этом мы завершаем статью о масштабируемости в Amazon Web Services. Как было разъяснено изначально, цель заключалась не в том, чтобы углубляться в концепции, языки, инструменты или конкретные проблемы, а просто в том, чтобы упорядочить этапы, которые пересекают архитектуру программной системы в общих чертах. Несомненно, будут ситуации, в которых все будет применяться по-другому, и решение придется адаптировать к конкретному случаю. Если этот текст вам интересен, вы имеете или имели опыт работы с этими сервисами в облаке AWS и рассматривали различные подходы к архитектуре или масштабируемости, не стесняйтесь поделиться им.

Спасибо за чтение!