Руководство по анализу устойчивых текстов с подключенной общей папкой файлов Azure

В этом руководстве вы развернете приложение Функции Azure на Python, которое использует Устойчивые функции для оркестрации параллельного анализа текстовых файлов. Приложение-функция подключает общее файловое хранилище Azure, анализирует несколько текстовых файлов параллельно (распараллеливание), агрегирует результаты (объединение) и возвращает их вызывающему. Этот подход демонстрирует ключевое преимущество монтирования хранилища: общий доступ к файлам в нескольких экземплярах функций без сетевых накладных расходов на каждый запрос.

Изучив это руководство, вы:

  • Разверните приложение Устойчивые функции в Flex Consumption план с подключенной общей папкой файлов Azure с помощью интерфейса командной строки Azure Developer.
  • Активация оркестрации для параллельной обработки примеров текстовых файлов
  • Проверка агрегированных результатов анализа

Note

Примеры кода, приведенные в этой статье, доступны в репозитории GitHub Функции Azure Flex Consumption with Файлы Azure OS Mount Samples.

Необходимые условия

Примеры интерфейса командной строки в этом руководстве используют синтаксис Bash и тестируются в терминалах Azure Cloud Shell (Bash) и Linux/macOS.

Инициализация примера проекта

Вы можете найти пример кода для этого руководства в репозитории GitHub Функции Azure Flex Consumption with Файлы Azure OS Mount Samples. Папка durable-text-analysis содержит код приложения-функции, шаблон Bicep, который подготавливает необходимые ресурсы Azure и скрипт после развертывания, который отправляет примеры текстовых файлов.

  1. Откройте терминал и перейдите в каталог, в котором нужно клонировать репозиторий.

  2. Клонируйте репозиторий:

    git clone https://github.com/Azure-Samples/Azure-Functions-Flex-Consumption-with-Azure-Files-OS-Mount-Samples.git
    
  3. Перейдите в папку проекта:

    cd Azure-Functions-Flex-Consumption-with-Azure-Files-OS-Mount-Samples/durable-text-analysis
    
  4. Инициализируйте azd среду. При появлении запроса введите имя среды, например durable-text:

    azd init
    

Просмотр кода

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

Во время исполнения оркестрация следует этой последовательности:

  1. HTTP POST для /api/start-analysis запускает оркестрацию Устойчивые функции.
  2. Оркестратор вызывает list_text_files действие, чтобы найти все .txt файлы на смонтированном диске.
  3. Оркестратор распределяет задачи, вызывая analyse_text_file для каждого файла в параллельном режиме.
  4. После завершения всех параллельных задач, оркестратор вызывает aggregate_results, чтобы объединить метрики отдельных файлов в одну сводную таблицу.
  5. Общий результат возвращается как выходные данные оркестрации.

Модуль mounts.bicep настраивает подключение SMB файлов Azure к приложению-функции. Значение mountPath определяет локальный путь, по которому файлы отображаются во время выполнения. Вы передаете ключ доступа к учетной записи хранения в качестве параметра, а платформа разрешает его во время выполнения с помощью ссылки на Key Vault.

@description('Function app name')
param functionAppName string

@description('Storage account name')
param storageAccountName string

@description('Storage account access key or app setting reference for Azure Files SMB mount')
param accessKey string

@description('Array of mount configurations')
param mounts array

// Function app reference
resource functionApp 'Microsoft.Web/sites@2023-12-01' existing = {
  name: functionAppName
}

// Azure Files OS mount configuration
// Deploys azureStorageAccounts site config with all mounts in one shot
resource mountConfig 'Microsoft.Web/sites/config@2023-12-01' = {
  parent: functionApp
  name: 'azurestorageaccounts'
  properties: reduce(mounts, {}, (cur, mount) => union(cur, {
    '${mount.name}': {
      type: 'AzureFiles'
      shareName: mount.shareName
      mountPath: mount.mountPath
      accountName: storageAccountName
      accessKey: accessKey
    }
  }))
}

output mountPaths array = [for mount in mounts: mount.mountPath]

Поскольку точки монтирования SMB для Файлы Azure еще не поддерживают проверку подлинности с использованием управляемых удостоверений, вам необходим ключ учетной записи хранения. Рекомендуется сохранить этот ключ в Azure Key Vault и использовать ссылку Key Vault в параметре приложения. Конфигурация монтирования ссылается на этот параметр приложения, используя @AppSettingRef(), так что ключ никогда не появляется в шаблонах Bicep. Модуль keyvault.bicep создает хранилище, сохраняет ключ и назначает роли RBAC:

@description('Key Vault name')
param name string

@description('Location')
param location string

@description('Tags')
param tags object = {}

@description('Storage account name')
param storageAccountName string

@description('Principal ID of the function app identity (receives Key Vault Secrets User role)')
param functionAppPrincipalId string

@description('Principal ID of the deploying user (receives Key Vault Secrets Officer role)')
param deployerPrincipalId string = ''

// Storage account reference
resource storage 'Microsoft.Storage/storageAccounts@2023-05-01' existing = {
  name: storageAccountName
}

// Key Vault with RBAC authorization
resource keyVault 'Microsoft.KeyVault/vaults@2023-07-01' = {
  name: name
  location: location
  tags: tags
  properties: {
    sku: {
      family: 'A'
      name: 'standard'
    }
    tenantId: tenant().tenantId
    enableRbacAuthorization: true
    enabledForTemplateDeployment: true
    enableSoftDelete: true
    softDeleteRetentionInDays: 7
  }
}

// Store storage account key as a secret (Azure Files mounts require shared key)
resource storageKeySecret 'Microsoft.KeyVault/vaults/secrets@2023-07-01' = {
  parent: keyVault
  name: 'storageAccountKey'
  properties: {
    value: storage.listKeys().keys[0].value
    contentType: 'Storage account access key for Azure Files SMB mount'
  }
}

// Built-in Key Vault RBAC role IDs
var roles = {
  KeyVaultSecretsOfficer: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b86a8fe4-44ce-4948-aee5-eccb2c155cd7')
  KeyVaultSecretsUser: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4633458b-17de-408a-b874-0445c86b69e6')
}

// Grant the function app identity read access to secrets
resource functionAppSecretsUser 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
  name: guid(keyVault.id, functionAppPrincipalId, roles.KeyVaultSecretsUser)
  scope: keyVault
  properties: {
    roleDefinitionId: roles.KeyVaultSecretsUser
    principalId: functionAppPrincipalId
    principalType: 'ServicePrincipal'
  }
}

// Grant the deployer manage access to secrets
resource deployerSecretsOfficer 'Microsoft.Authorization/roleAssignments@2022-04-01' = if (!empty(deployerPrincipalId)) {
  name: guid(keyVault.id, deployerPrincipalId, roles.KeyVaultSecretsOfficer)
  scope: keyVault
  properties: {
    roleDefinitionId: roles.KeyVaultSecretsOfficer
    principalId: deployerPrincipalId
    principalType: 'User'
  }
}

output name string = keyVault.name
output uri string = keyVault.properties.vaultUri
output storageKeySecretUri string = storageKeySecret.properties.secretUri

Файл main.bicep вызывает модули монтирования и Key Vault:


// Key Vault for secure storage of Azure Files access key
module keyVault './app/keyvault.bicep' = {
  name: 'keyVault'
  scope: rg
  params: {
    name: !empty(keyVaultName) ? keyVaultName : '${abbrs.keyVaultVaults}${resourceToken}'
    location: location
    tags: tags
    storageAccountName: storage.outputs.name
    functionAppPrincipalId: processorIdentity.outputs.principalId
    deployerPrincipalId: principalId
  }
}

// Azure Files mount configuration (access key resolved via Key Vault reference)
module azureFilesMount './app/mounts.bicep' = {
  name: 'azureFilesMount'
  scope: rg
  params: {
    functionAppName: functionApp.outputs.name
    storageAccountName: storage.outputs.name
    accessKey: '@AppSettingRef(MOUNT_SECRET_REFERENCE)'
    mounts: [
      {
        name: 'data'
        shareName: 'data'
        mountPath: '/mounts/data/'
      }
    ]
  }
  dependsOn: [
    functionAppRoleAssignments
  ]

Развертывание с помощью Интерфейса командной строки разработчика Azure

Этот пример представляет собой шаблон интерфейса командной строки разработчика Azure (azd). azd up Одна команда подготавливает инфраструктуру, развертывает код функции и отправляет примеры текстовых файлов в общую папку файлов Azure.

  1. Войдите в Azure. Скрипт после развертывания использует команды Azure CLI, поэтому необходимо пройти проверку подлинности с помощью обоих средств:

    azd auth login
    az login
    
  2. Подготовка и развертывание всего:

    azd up
    

    При появлении запроса выберите подписку Azure и расположение для использования. Затем выполните следующую команду:

    • Создает группу ресурсов, учетную запись хранения, Key Vault, приложение-функцию Flex Consumption с конфигурацией устойчивых функций, экземпляром Application Insights и управляемым удостоверением
    • Развертывание кода функции Python
    • Отправка примеров текстовых файлов в общую папку файлов Azure
    • Выполняет проверку работоспособности

    Note

    Поскольку точки монтирования SMB для Файлы Azure еще не поддерживают проверку подлинности с использованием управляемых удостоверений, вам необходим ключ учетной записи хранения. В качестве рекомендации развертывание сохраняет этот ключ в Azure Key Vault и использует ссылку Key Vault, чтобы ключ никогда не предоставлялся в настройках приложения. Этот подход обеспечивает централизованное управление секретами, аудит и поддержку смены ключей.

    Развертывание занимает несколько минут. По завершении вы увидите сводку по созданным ресурсам.

  3. Сохраните имена ресурсов в виде переменных оболочки для оставшихся шагов:

    RESOURCE_GROUP=$(azd env get-value AZURE_RESOURCE_GROUP)
    FUNCTION_APP_NAME=$(azd env get-value AZURE_FUNCTION_APP_NAME)
    FUNCTION_APP_URL=$(azd env get-value AZURE_FUNCTION_APP_URL)
    

Запустите оркестрацию

  1. Получите ключ узла функции:

    HOST_KEY=$(az functionapp keys list \
      --resource-group $RESOURCE_GROUP \
      --name $FUNCTION_APP_NAME \
      --query "functionKeys.default" \
      -o tsv)
    
  2. Запустите оркестрацию. При необходимости можно передать тело JSON, чтобы переопределить точку монтирования по умолчанию: {"mount_path": "/mounts/data/"}

    curl -s -X POST "${FUNCTION_APP_URL}/api/start-analysis?code=${HOST_KEY}" | jq .
    

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

    {
      "id": "abc123def456",
      "statusQueryGetUri": "https://<your-app>.azurewebsites.net/...",
      "sendEventPostUri": "https://...",
      "terminatePostUri": "https://..."
    }
    

Проверка результатов

  1. Проверьте состояние оркестрации с помощью ответа триггера statusQueryGetUri :

    STATUS_URL="<statusQueryGetUri-from-trigger-response>"
    
    curl -s "${STATUS_URL}" | jq .
    

    В то время как оркестрация выполняется, runtimeStatus имеет значение Running. По завершении ответ выглядит следующим образом:

    {
      "instanceId": "abc123def456",
      "runtimeStatus": "Completed",
      "output": {
        "total_files": 3,
        "total_words": 45,
        "total_lines": 12,
        "total_chars": 303,
        "overall_avg_word_length": 4.82,
        "overall_top_characters": [["e", 42], ["t", 38], ["a", 35]],
        "per_file": [
          {
            "file_path": "/mounts/data/sample1.txt",
            "word_count": 15,
            "line_count": 4,
            "char_count": 98,
            "avg_word_length": 5.1,
            "top_characters": [["e", 14], ["t", 12]]
          },
          {
            "file_path": "/mounts/data/sample2.txt",
            "word_count": 18,
            "line_count": 5,
            "char_count": 120,
            "avg_word_length": 4.6,
            "top_characters": [["a", 16], ["e", 15]]
          },
          {
            "file_path": "/mounts/data/sample3.txt",
            "word_count": 12,
            "line_count": 3,
            "char_count": 85,
            "avg_word_length": 4.9,
            "top_characters": [["e", 13], ["t", 11]]
          }
        ]
      }
    }
    

    Приложение также предоставляет удобную конечную точку /api/status/{instance_id} , которая возвращает упрощенный ответ состояния.

Tip

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

Очистите ресурсы

Чтобы избежать текущих расходов, удалите все ресурсы, созданные этим руководством:

azd down --purge

Предупреждение

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