Параллелизм в Функциях Azure

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

Модель размещения для Функций позволяет одновременно выполнять несколько вызовов функций на одном вычислительном экземпляре. Например, рассмотрим случай, когда в приложении-функции есть три разных функции, которые масштабируются и выполняются на нескольких экземплярах. В этом сценарии каждая функция обрабатывает вызовы на каждом экземпляре виртуальной машины, на котором выполняется приложение-функция. Вызовы функций в одном экземпляре совместно используют одни и те же вычислительные ресурсы виртуальной машины, такие как память, ЦП и подключения. Если приложение размещено в динамическом плане ("Потребление" или "Премиум"), платформа масштабирует количество экземпляров приложения-функции вверх или вниз на основе количества входящих событий. Дополнительные сведения см. в статье о масштабировании на основе событий. При размещении функций в плане "Выделенный" (Служба приложений) вы вручную настраиваете свои экземпляры или настраиваете схему автомасштабирования.

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

Статический параллелизм

Многие триггеры поддерживают статическую модель конфигурации уровня узла, которая используется для настройки параллелизма отдельных экземпляров для данного типа триггера. Например, у триггера служебной шины есть как параметр MaxConcurrentCalls, так и параметр MaxConcurrentSessions в файле host.json. Эти параметры вместе управляют максимальным количеством сообщений, которые каждая функция одновременно обрабатывает на каждом экземпляре. У других типов триггеров есть встроенные механизмы балансировки нагрузки вызовов между экземплярами. Например, Центры событий и Azure Cosmos DB используют схему на основе секционирования.

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

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

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

Динамический параллелизм

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

Примечание.

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

Льготы

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

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

Конфигурация динамического параллелизма

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

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

Вы можете включить динамический параллелизм в приложении-функции, добавив следующие параметры в файл host.json:

    { 
        "version": "2.0", 
        "concurrency": { 
            "dynamicConcurrencyEnabled": true, 
            "snapshotPersistenceEnabled": true 
        } 
    } 

Если SnapshotPersistenceEnabled равно true (это значение по умолчанию), определенные значения параллелизма периодически сохраняются в хранилище, и новые экземпляры начинают работу именно с этих значений, а не с 1 с последующим повторным обучением.

Диспетчер параллелизма

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

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

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

Поддержка расширений.

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

Azure Queues

У триггера хранилища очередей Azure есть собственный цикл опроса сообщений. При использовании статической конфигурации параллелизм регулируется параметрами конфигурации BatchSize/NewBatchThreshold. В режиме динамического параллелизма эти значения конфигурации игнорируются. Динамический параллелизм интегрируется в цикл обработки сообщений, поэтому количество сообщений, получаемых в каждой итерации, корректируется динамически. При включении регуляторов (перегрузке узла) обработка сообщений приостанавливается до момента их отключения. При отключении регуляторов параллелизм увеличивается.

Для применения динамического параллелизма с очередями необходимо использовать версию 5.x расширения хранилища.

Большие двоичные объекты Azure

На внутреннем уровне триггер хранилища BLOB-объектов Azure использует ту же инфраструктуру, что и триггер очереди Azure. При обработке новых или обновленных BLOB-объектов сообщения записываются в управляемую платформой очередь управления, и эта очередь обрабатывается с применением той же логики, что и для триггера очереди. Когда включен динамический параллелизм, управление параллелизмом для обработки этой очереди управления осуществляется динамически.

Для применения динамического параллелизма с большими двоичными объектами необходимо использовать версию 5.x расширения хранилища.

Cлужебная шина

Сейчас триггер служебной шины поддерживает три модели выполнения. Динамический параллелизм затрагивает эти модели выполнения следующим образом:

  • Обработка одного раздела или очереди отправки: каждый вызов функции обрабатывает одно сообщение. При использовании статической конфигурации параллелизм регулируется параметром MaxConcurrentCalls конфигурации. При использовании динамического параллелизма это значение конфигурации игнорируется, а параллелизм корректируется динамически.
  • Обработка одного раздела или очереди отправки на основе сеансов: каждый вызов функции обрабатывает одно сообщение. В зависимости от количества активных сеансов для раздела или очереди каждый экземпляр арендует один или несколько сеансов. Сообщения в каждом сеансе обрабатываются последовательно, чтобы гарантировать определенный порядок в сеансе. Если динамический параллелизм не используется, для регулирования параллелизма применяется параметр MaxConcurrentSessions. Если динамический параллелизм включен, параметр MaxConcurrentSessions игнорируется, а количество сеансов, обрабатываемых каждым экземпляром, корректируется динамически.
  • Пакетная обработка: каждый вызов функции обрабатывает пакет сообщений, управляемый параметром MaxMessageCount. Поскольку пакетные вызовы осуществляются последовательно, параллелизм для функции с пакетной активацией всегда работает на уровне 1, а динамический параллелизм не применяется.

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

Следующие шаги

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