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

Как архитектор решений, я довольно регулярно посещаю совещания по разработке проектов.

Одна из вещей, которую я всегда слушаю на этих встречах, — это фраза «мы не можем использовать услугу X, потому что лимит услуги слишком мал».

Хотите верьте, хотите нет, но я слышу это довольно регулярно.

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

Ограничения службы существуют не просто так.

Прежде чем вы убежите и попросите увеличить лимит обслуживания, спросите себя: «Почему этот лимит вообще существует?» AWS не хочет, чтобы вы делали это по какой-то причине, и попытка обойти ограничение звучит как плохая идея.

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

Политики фильтрации SNS

Amazon SNS имеет ограничение по умолчанию в 100 000 тем на учетную запись (или 1000 тем FIFO). Однако у вас может быть только 200 политик фильтрации подписки на учетную запись.

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

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

Возьмем реальный пример.

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

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

Это работало… пока не сработало. Как только я достиг квоты службы фильтрации подписки для SNS, мне пришлось быстро переосмыслить решение.

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

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

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

Размер результата лямбда-авторизатора

Лямбда-авторизаторы — это функции Lambda, которые находятся поверх вашего шлюза API для выполнения пользовательской авторизации. Авторизатор проверяет личность пользователя и возвращает политику IAM, которая включает ARN конечных точек, к которым может получить доступ вызывающий. Размер этой политики ограничен размером 8 КБ.

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

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

Помимо сложного бремени управления этим между службами для каждой роли, он создал гигантские политики, которые в конечном итоге переросли этот предел в 8 КБ. И снова нам пришлось вернуться и реализовать наше решение по-другому, чтобы справиться с ограничением размера.

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

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

В этом сценарии мы думали, что не сможем достичь предела в 8 КБ, когда изначально разрабатывали решение. Но мы не думали о себе в будущем. В своих проектах всегда учитывайте масштаб не слишком отдаленного будущего. Будет ли этот масштаб перерастать квоту на услуги? В моем случае получилось.

Цели правила EventBridge

EventBridge направляет события в различные пункты назначения через правила. Правила определяют, что ищет EventBridge, и определяют цель или пункт назначения, который инициируется событием. Каждое правило имеет ограничение в пять целей.

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

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

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

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

Аналогично целевому пределу EventBridge существуют лучшие методы работы с потребителями в потоке DynamoDB. При обработке потоков рекомендуется иметь не более двух обработчиков, чтобы предотвратить регулирование.

Если у вас есть несколько процессов, которые необходимо запустить в результате потока DynamoDB, вы можете использовать тот же подход, что и мы, для целей правила EventBridge: разветвление с помощью SNS. Сохранение содержимого в S3 и публикация ключа объекта в сообщении SNS или передача содержимого непосредственно в сообщении позволит вам получить столько потребителей записей потока, сколько вам нужно.

Имейте в виду, что чем больше процессов одновременно работает с одними и теми же данными, тем осторожнее вам нужно быть при выполнении преобразований.

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

Ограничения размера запроса DynamoDB

На более низком уровне у DynamoDB есть предел размера запроса, который вам необходимо учитывать. При выполнении операции сканирования или запроса к таблице DynamoDB максимальный размер результата, который он может вернуть, составляет 1 МБ. Если ваш запрос соответствует более 1 МБ данных, DynamoDB вернет в ответ свойство LastEvaluatedKey, чтобы вы знали, что есть еще результаты для обработки.

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

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

Чтобы смягчить это, у вас есть несколько различных вариантов.

  • Спроектируйте свою модель данных так, чтобы запросы не превышали 1 МБ.
  • Создайте свое приложение с учетом пейджинга

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

Если вы намеренно приложили усилия к дизайну заранее, вы можете избежать ограничения запроса в 1 МБ.

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

Вы не хотите неожиданной потери данных, поэтому учитывайте дизайн (особенно при использовании API в первую очередь) заранее, а не в ответ на критическую проблему.

Заключение

Ограничения на обслуживание предназначены для использования в качестве ограждений при построении вашей инфраструктуры. Если ваше приложение сталкивается с проблемой с квотой на другом уровне масштаба, переосмысление вашего дизайна, вероятно, является правильным решением. Например, если вам нужно 10 000 фильтров подписки на SNS вместо 200.

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

Какой бы путь вы ни выбрали, убедитесь, что вы не боретесь с инфраструктурой. Ограничения существуют, чтобы удержать вас от глупостей. Не будь глупым.

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

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

Большинство сервисных лимитов можно увеличить, но для тех, которые нельзя — вы застряли с проектным решением. Если вы сделаете шаг назад и спросите себя: «Почему он такой низкий?» вы можете прийти к пониманию и немного лучше понять экосистему.

Удачи, и я надеюсь, что вы учтете это в следующий раз, когда будете создавать систему.

Удачного кодирования!