Guia do desenvolvedor do PowerShell do Azure Functions

Veja neste artigo detalhes de como escrever no Azure Functions usando o PowerShell.

Uma função do Azure PowerShell é representada como um script do PowerShell executado quando disparado. Cada script de função tem um arquivo function.json relacionado que define como a função se comporta, por exemplo, como é disparada e seus parâmetros de entrada e saída. Para saber mais, confira o artigo Gatilhos e associação.

Assim como outros tipos de funções, as funções de script do PowerShell assumem parâmetros que correspondem aos nomes de todas as associações de entrada definidas no arquivo function.json. Um parâmetro TriggerMetadata também é transmitido e contém informações adicionais sobre o gatilho que iniciou a função.

Este artigo pressupõe que você já tenha lido a Referência do desenvolvedor do Azure Functions. Você também precisa ter concluído o Início rápido de funções para o PowerShell para criar sua primeira função no PowerShell.

Estrutura de pastas

A estrutura de pastas necessária para um projeto do PowerShell é semelhante à mostrada a seguir. Este padrão pode ser alterado. Para mais informações, consulte a seção scriptArquivo abaixo.

PSFunctionApp
 | - MyFirstFunction
 | | - run.ps1
 | | - function.json
 | - MySecondFunction
 | | - run.ps1
 | | - function.json
 | - Modules
 | | - myFirstHelperModule
 | | | - myFirstHelperModule.psd1
 | | | - myFirstHelperModule.psm1
 | | - mySecondHelperModule
 | | | - mySecondHelperModule.psd1
 | | | - mySecondHelperModule.psm1
 | - local.settings.json
 | - host.json
 | - requirements.psd1
 | - profile.ps1
 | - extensions.csproj
 | - bin

Na raiz do projeto, há um arquivo host.json compartilhado que pode ser usado para configurar o aplicativo de funções. Cada função tem uma pasta com o próprio arquivo de código (.ps1) e o arquivo de configuração de associação (function.json). O nome do diretório pai do arquivo function.json é sempre o nome da sua função.

Determinadas associações exigem a presença de um arquivo extensions.csproj. As extensões de associação necessárias na versão 2.x e posteriores do runtime do Functions são definidas no arquivo extensions.csproj, com os arquivos de biblioteca reais na pasta bin. Ao desenvolver localmente, você precisa registrar as extensões de associação. Ao desenvolver funções no portal do Azure, esse registro é feito para você.

Em aplicativos de funções do PowerShell, existe a opção de ter um profile.ps1 que é executado quando um aplicativo de funções começa a ser executado (também conhecido como inicialização a frio). Para saber mais, confira Perfil do PowerShell.

Definir um script do PowerShell como função

Por padrão, o runtime de Funções procura sua função em run.ps1, onde run.ps1 compartilha o mesmo diretório pai que o function.json correspondente.

Seu script é recebe vários argumentos na execução. Para lidar com esses parâmetros, adicione um bloco param à parte superior do seu script, como no seguinte exemplo:

# $TriggerMetadata is optional here. If you don't need it, you can safely remove it from the param block
param($MyFirstInputBinding, $MySecondInputBinding, $TriggerMetadata)

Parâmetro TriggerMetadata

O parâmetro TriggerMetadata é usado para fornecer informações adicionais sobre o gatilho. Os metadados adicionais entre as associações, mas todos contêm uma propriedade sys com os seguintes dados:

$TriggerMetadata.sys
Propriedade Descrição Type
UtcNow Quando a função foi disparada em UTC Datetime
MethodName O nome da função que foi disparada string
RandGuid um GUID exclusivo para esta execução da função string

Cada tipo de gatilho tem um conjunto diferente de metadados. Por exemplo, $TriggerMetadata para QueueTrigger contém InsertionTime, Id, DequeueCount, entre outros. Para saber mais sobre os metadados do gatilho da fila, acesse a documentação oficial dos gatilhos de fila. Verifique a documentação sobre gatilhos para ver o que acontece nos metadados de gatilho.

Associações

No PowerShell, associações são configuradas e definidas na função function.json. As funções interagem com as ligações de várias maneiras.

Gatilho de leitura e dados de entrada

As associações de entrada e gatilho são lidas como parâmetros passados para a sua função. As associações de entrada têm um direction definido como in em function.json. A propriedade name definida em function.json é o nome do parâmetro, no bloco param. Como o PowerShell usa parâmetros nomeados para associação, a ordem dos parâmetros não importa. No entanto, é uma melhor prática seguir a ordem das associações definidas em function.json.

param($MyFirstInputBinding, $MySecondInputBinding)

Gravar dados de saída

No Functions, uma associação de saída tem um direction definido como out em function.json. É possível gravar em uma associação de saída usando o cmdlet Push-OutputBinding, que está disponível para o runtime do Functions. Em todos os casos, a propriedade name da associação, conforme definido em function.json, corresponde ao parâmetro Name do cmdlet Push-OutputBinding.

Veja abaixo como chamar Push-OutputBinding no script da função:

param($MyFirstInputBinding, $MySecondInputBinding)

Push-OutputBinding -Name myQueue -Value $myValue

Também é possível passar um valor para uma associação específica por meio do pipeline.

param($MyFirstInputBinding, $MySecondInputBinding)

Produce-MyOutputValue | Push-OutputBinding -Name myQueue

Push-OutputBinding se comporta de modo diferente com base no valor especificado para -Name:

  • Quando o nome especificado não puder ser resolvido para uma associação de saída válida, um erro será gerado.

  • Quando a associação de saída aceita uma coleção de valores, chame Push-OutputBinding repetidamente para efetuar push de vários valores.

  • Quando a associação de saída aceita apenas um valor singleton, chamar Push-OutputBinding uma segunda vez gera um erro.

Sintaxe Push-OutputBinding

Estes são parâmetros válidos para chamar Push-OutputBinding:

Nome Tipo Posição Descrição
-Name String 1 O nome da associação de saída que você quer definir.
-Value Objeto 2 O valor da associação de saída que você quer definir, que é aceita no pipeline ByValue.
-Clobber SwitchParameter nomeado (Opcional) Quando especificado, força o valor a ser definido para uma associação de saída especificada.

Estes parâmetros comuns também são compatíveis:

  • Verbose
  • Debug
  • ErrorAction
  • ErrorVariable
  • WarningAction
  • WarningVariable
  • OutBuffer
  • PipelineVariable
  • OutVariable

Para saber mais, confira Sobre CommonParameters.

Exemplo de Push-OutputBinding: respostas HTTP

Um gatilho HTTP retorna uma resposta usando uma associação de saída denominada response. No seguinte exemplo, a associação de saída de response tem o valor de "saída 1":

PS >Push-OutputBinding -Name response -Value ([HttpResponseContext]@{
    StatusCode = [System.Net.HttpStatusCode]::OK
    Body = "output #1"
})

Como a saída é para HTTP, que aceita apenas um valor singleton, um erro é gerado quando Push-OutputBinding é chamado pela segunda vez.

PS >Push-OutputBinding -Name response -Value ([HttpResponseContext]@{
    StatusCode = [System.Net.HttpStatusCode]::OK
    Body = "output #2"
})

Para saídas que aceitam só valores singleton, use o parâmetro -Clobber para substituir o valor antigo em vez de tentar adicionar a uma coleção. O exemplo a seguir pressupõe que você já adicionou um valor. Usando -Clobber, a resposta do seguinte exemplo substitui o valor existente para retornar um valor de "saída 3":

PS >Push-OutputBinding -Name response -Value ([HttpResponseContext]@{
    StatusCode = [System.Net.HttpStatusCode]::OK
    Body = "output #3"
}) -Clobber

Exemplo de Push-OutputBinding: associação de saída de fila

Push-OutputBinding é usado para enviar dados para associações de saída, como uma associação de saída do Armazenamento de Filas do Azure. No seguinte exemplo, a mensagem gravada na fila tem um valor de "saída 1":

PS >Push-OutputBinding -Name outQueue -Value "output #1"

A associação de saída para uma fila do Armazenamento aceita vários valores de saída. Nesse caso, chamar o exemplo a seguir após o primeiro grava na fila em uma lista com dois itens: "saída 1" e "saída 2".

PS >Push-OutputBinding -Name outQueue -Value "output #2"

O seguinte exemplo, quando chamado após os dois anteriores, adiciona mais dois valores à coleção de saída:

PS >Push-OutputBinding -Name outQueue -Value @("output #3", "output #4")

Quando gravada na fila, a mensagem contém estes quatro valores: "saída 1", "saída 2", "saída 3" e "saída 4".

Cmdlet Get-OutputBinding

Use o cmdlet Get-OutputBinding para recuperar os valores definidos atualmente para as associações de saída. Esse cmdlet recupera uma tabela de hash que contém os nomes das associações de saída com seus respectivos valores.

Veja abaixo um exemplo de como usar Get-OutputBinding para retornar os valores de associação atuais:

Get-OutputBinding
Name                           Value
----                           -----
MyQueue                        myData
MyOtherQueue                   myData

Get-OutputBinding também contém um parâmetro chamado -Name, que pode ser usado para filtrar a associação retornada, como no seguinte exemplo:

Get-OutputBinding -Name MyQ*
Name                           Value
----                           -----
MyQueue                        myData

Caracteres curinga (*) são compatíveis com Get-OutputBinding.

Log

O registro em log funciona normalmente nas funções do PowerShell. Use os cmdlets de registro em log para gravar em cada fluxo de saída. Cada cmdlet é mapeado em um nível de registro usado pelo Functions.

Nível de registros em log do Functions Cmdlet de registro em log
Erro Write-Error
Aviso Write-Warning
Informações do Write-Information
Write-Host
Write-Output
Grava no nível de log Information.
Depurar Write-Debug
Trace Write-Progress
Write-Verbose

Além desses cmdlets, qualquer coisa gravada no pipeline é redirecionada para o nível de registro Information e exibida com a formatação padrão do PowerShell.

Importante

Usar os cmdlets Write-Verbose ou Write-Debug não é suficiente para ver o registro em log detalhado e no nível de depuração. É preciso configurar o limite do nível de registro em log, que declara o nível de registros que realmente importa. Para saber mais, confira Configurar o nível de registro em log do aplicativo de funções.

Configurar o nível de registro em log do aplicativo de funções

O Azure Functions permite definir o nível de limite para facilitar o controle da maneira como o Functions grava os registros. Para definir o limite para todos os rastreamentos gravados no console, use a propriedade logging.logLevel.default no host.jsonarquivo. Essa configuração se aplica a todas as funções em seu aplicativo de função.

O exemplo seguinte define o limite para habilitar o registro detalhado de todas as funções, mas também para habilitar o registro em log de depuração de uma função chamada MyFunction:

{
    "logging": {
        "logLevel": {
            "Function.MyFunction": "Debug",
            "default": "Trace"
        }
    }
}  

Para obter mais informações, consulte a referência para host.json.

Ver os registros

Se o aplicativo de funções estiver em execução no Azure, use o Application Insights para monitorá-lo. Leia Monitorado o Azure Functions para saber mais sobre como exibir e consultar logs de função.

Se o aplicativo de funções estiver em execução no local para desenvolvimento, os registros terão como padrão o sistema de arquivos. Para ver os registros no console, defina a variável de ambiente AZURE_FUNCTIONS_ENVIRONMENT como Development antes de iniciar o aplicativo de funções.

Tipos de gatilhos e associações

Há vários gatilhos e associações disponíveis para usar com o aplicativo de funções. A lista completa de gatilhos e associações pode ser encontrada aqui.

Todos os gatilhos e associações são representados no código como alguns tipos de dados reais:

  • Hashtable
  • string
  • byte[]
  • INT
  • double
  • HttpRequestContext
  • HttpResponseContext

Os cinco primeiros tipos nessa lista são tipos .NET padrão. Os dois últimos são usados somente pelo gatilho HttpTrigger.

Cada parâmetro de associação em suas funções deve ser um desses tipos.

Gatilhos e associações HTTP

HTTP e gatilhos de webhook e associações de saída HTTP usam objetos de solicitação e resposta para representar as mensagens HTTP.

Objeto da solicitação

O objeto de solicitação que é passado para o script é do tipo HttpRequestContext, que tem as seguintes propriedades:

Propriedade Descrição Type
Body Um objeto que contém o corpo da solicitação. Body é serializado no melhor tipo com base nos dados. Por exemplo, se os dados forem JSON, ele será passado como uma tabela de hash. Se os dados forem uma cadeia de caracteres, serão passados como uma cadeia de caracteres. objeto
Headers Um dicionário que contém os cabeçalhos de solicitação. <Cadeia de caracteres,cadeia de caracteres>* de dicionário
Method O método HTTP da solicitação. string
Params Um objeto que contém os parâmetros de roteamento da solicitação. <Cadeia de caracteres,cadeia de caracteres>* de dicionário
Query Um objeto que contém os parâmetros da consulta. <Cadeia de caracteres,cadeia de caracteres>* de dicionário
Url A URL da solicitação. string

* Nenhuma das teclas Dictionary<string,string> diferenciam maiúsculas e minúsculas.

Objeto de resposta

O objeto de resposta que você deve enviar de volta é do tipo HttpResponseContext, que tem as seguintes propriedades:

Propriedade Descrição Type
Body Um objeto que contém o corpo da resposta. objeto
ContentType Um atalho para configurar o tipo de conteúdo da resposta. string
Headers Um objeto que contém os cabeçalhos da resposta. Dicionário ou tabela de hash
StatusCode O código de status HTTP da resposta. cadeia de caracteres ou inteiro

Acessar a solicitação e a resposta

Ao trabalhar com gatilhos HTTP, você pode acessar a solicitação HTTP do mesmo jeito que faria com qualquer outra associação de entrada. Ela fica no bloco param.

Use um objeto HttpResponseContext para retornar uma resposta, conforme mostrado abaixo:

function.json

{
  "bindings": [
    {
      "type": "httpTrigger",
      "direction": "in",
      "authLevel": "anonymous"
    },
    {
      "type": "http",
      "direction": "out",
      "name": "Response"
    }
  ]
}

run.ps1

param($req, $TriggerMetadata)

$name = $req.Query.Name

Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
    StatusCode = [System.Net.HttpStatusCode]::OK
    Body = "Hello $name!"
})

O resultado da invocação dessa função seria:

PS > irm http://localhost:5001?Name=Functions
Hello Functions!

Conversão de tipo para gatilhos e associações

Em determinadas associações, como a associação de blobs, é possível especificar o tipo do parâmetro.

Por exemplo, para fornecer dados do Armazenamento de Blobs como uma cadeia de caracteres, adicione a seguinte conversão de tipo ao bloco param:

param([string] $myBlob)

Perfil do PowerShell

No PowerShell, há o conceito de perfil do PowerShell. Se você não conhece os perfis do PowerShell, confira Sobre os perfis.

Nas funções do PowerShell, o script do perfil é executado uma vez por instância de trabalho do PowerShell na primeira implantação do aplicativo e após ele ficar ocioso (inicialização a frio). Quando a simultaneidade é habilitada por meio da definição do valor PSWorkerInProcConcurrencyUpperBound, o script do perfil é executado para cada runspace criado.

Ao criar um aplicativo de funções usando ferramentas como o Visual Studio Code e o Azure Functions Core Tools, um profile.ps1 padrão é criado para você. O perfil padrão é mantido no repositório GitHub do Core Tools e contém:

  • Autenticação automática de MSI para o Azure.
  • Capacidade de ativar os aliases AzureRM do Azure PowerShell se você quiser.

Versões do PowerShell

Veja na seguinte tabela as versões do PowerShell disponíveis para cada versão principal do runtime do Functions e a versão do .NET exigida:

Versão do Functions Versão do PowerShell Versão do .NET
4.x PowerShell 7.2 .NET 6

Veja a versão atual imprimindo $PSVersionTable em qualquer função.

Para saber mais sobre a política de suporte do Azure Functions Runtime, veja esteartigo

Execução local em uma versão específica

O suporte para o PowerShell 7.0 no Azure Functions terminou em 3 de dezembro de 2022. Para usar o PowerShell 7.2 ao executar localmente, é preciso adicionar a configuração "FUNCTIONS_WORKER_RUNTIME_VERSION" : "7.2" à matriz Values no arquivo local.setting.json na raiz do projeto. Ao executar localmente no PowerShell 7.2, seu arquivo local.settings.json é semelhante ao seguinte exemplo:

{
  "IsEncrypted": false,
  "Values": {
    "AzureWebJobsStorage": "",
    "FUNCTIONS_WORKER_RUNTIME": "powershell",
    "FUNCTIONS_WORKER_RUNTIME_VERSION" : "7.2"
  }
}

Observação

No PowerShell Functions, o valor "~7" para FUNCTIONS_WORKER_RUNTIME_VERSION refere-se a "7.0.x". Não atualizamos automaticamente os aplicativos de funções do PowerShell que têm "~7" para "7.2". Daqui para frente, para Aplicativos de Funções do PowerShell, exigiremos que os aplicativos especifiquem a versão principal e secundária que eles desejam direcionar. Portanto, será necessário mencionar "7.2" se você quiser direcionar "7.2.x"

Alterar a versão do PowerShell

O suporte para o PowerShell 7.0 no Azure Functions terminou em 3 de dezembro de 2022. Para atualizar seu Aplicativo de Funções para o PowerShell 7.2, verifique se o valor de FUNCTIONS_EXTENSION_VERSION está definido como ~4. Para saber como fazer isso, confira Ver e atualizar a versão atual do runtime.

Siga estas etapas para alterar a versão do PowerShell usada pelo seu aplicativo de funções. É possível fazer isso no portal do Azure ou no PowerShell.

  1. No portal do Azure, navegue até o aplicativo de funções.

  2. Em Configurações, escolha Configuração. Na guia Configurações gerais, localize a Versão do PowerShell.

    image

  3. Escolha a versão do PowerShell Core desejada e clique em Salvar. Clique em Continuar quando a mensagem de reinicialização pendente for exibida. O aplicativo de funções é reiniciado na versão escolhida do PowerShell.

O aplicativo de funções é reiniciado depois que a alteração é feita na configuração.

Gerenciamento de dependência

O Functions permite usar a Galeria do PowerShell para gerenciar dependências. Com o gerenciamento de dependência habilitado, o arquivo requirements.psd1 é usado para baixar automaticamente os módulos necessários. Habilite esse comportamento definindo a propriedade managedDependency como true na raiz do arquivo host.json, como no seguinte exemplo:

{
  "managedDependency": {
          "enabled": true
       }
}

Quando você cria um projeto de funções no PowerShell, o gerenciamento de dependência é habilitado por padrão, com o módulo Az do Azure incluído. O número máximo de módulos compatíveis no momento é 10. A sintaxe compatível é uma MajorNumber.* ou a versão de módulo exata, conforme mostrado no exemplo seguinte do requirements.psd1:

@{
	Az = '1.*'
	SqlServer = '21.1.18147'
}

Quando você atualiza o arquivo requirements.psd1, os módulos atualizados são instalados após uma reinicialização.

Versões específicas de destino

Talvez você queira direcionar uma versão específica de um módulo no arquivo requirements.psd1. Por exemplo, se você quisesse usar uma versão mais antiga do Az.Accounts que a do módulo Az incluído, você precisaria direcionar uma versão específica, conforme mostrado no exemplo a seguir:

@{
	'Az.Accounts' = '1.9.5'
}

Nesse caso, você também precisa adicionar uma instrução de importação na parte superior do arquivo de profile.ps1, que deve ter a seguinte aparência:

Import-Module Az.Accounts -RequiredVersion '1.9.5'

Dessa forma, a versão mais antiga do módulo Az.Account é carregada primeiro quando a função é iniciada.

Considerações sobre o gerenciamento de dependência

As seguintes considerações se aplicam ao usar o gerenciamento de dependência:

  • As dependências gerenciadas exigem acesso ao https://www.powershellgallery.com para baixar módulos. Ao executar localmente, verifique se o runtime pode acessar essa URL adicionando as regras de firewall necessárias.

  • No momento, as dependências gerenciadas não são compatíveis com os módulos que exigem que o usuário aceite uma licença, seja aceitando a licença interativamente ou fornecendo a opção -AcceptLicense ao invocar Install-Module.

Configurações do aplicativo de gerenciamento de dependência

As configurações de aplicativo a seguir podem ser usadas para alterar o modo como as dependências gerenciadas são baixadas e instaladas.

Configuração do aplicativo de funções Valor padrão Descrição
MDMaxBackgroundUpgradePeriod 7.00:00:00 (sete dias) Controla o período de atualização em segundo plano para aplicativos de funções do PowerShell. Para saber mais, consulte MDMaxBackgroundUpgradePeriod.
MDNewSnapshotCheckPeriod 01:00:00 (uma hora) Especifica com que frequência cada trabalho do PowerShell verifica se as atualizações de dependência gerenciada foram instaladas. Para saber mais, consulte MDNewSnapshotCheckPeriod.
MDMinBackgroundUpgradePeriod 1.00:00:00 (um dia) O período de tempo após uma verificação de atualização anterior, antes de outra verificação de atualização ser iniciada. Para saber mais, consulte MDMinBackgroundUpgradePeriod.

Essencialmente, a atualização do aplicativo é iniciada em MDMaxBackgroundUpgradePeriod e o processo de atualização é concluído em aproximadamente MDNewSnapshotCheckPeriod.

Módulos personalizados

Aproveitar seus próprios módulos personalizados no Azure Functions difere de como você faria normalmente para o PowerShell.

No computador local, o módulo é instalado em uma das pastas disponíveis globalmente no seu $env:PSModulePath. Ao executar no Azure, você não tem acesso aos módulos instalados no computador. Isso significa que o $env:PSModulePath de um aplicativo de funções do PowerShell é diferente do $env:PSModulePath em um script regular do PowerShell.

No Functions, PSModulePath contém dois caminhos:

  • Uma pasta Modules que existe na raiz do seu aplicativo de funções.
  • Um caminho para uma pasta Modules que é controlada pelo trabalho de linguagem do PowerShell.

Pasta dos módulos de nível do aplicativo de funções

Para usar módulos personalizados, coloque os módulos de que suas funções dependem em uma pasta Modules. Nessa pasta, os módulos ficam automaticamente disponíveis para o runtime de funções. Qualquer função no aplicativo de funções pode usar esses módulos.

Observação

Os módulos especificados no arquivo requirements.psd1 são baixados e incluídos automaticamente no caminho para que você não precise incluí-los na pasta de módulos. Eles são armazenados localmente na pasta $env:LOCALAPPDATA/AzureFunctions e na pasta /data/ManagedDependencies quando executados na nuvem.

Para aproveitar o recurso de módulo personalizado, crie uma pasta Modules na raiz do seu aplicativo de funções. Copie os módulos que você deseja usar em suas funções para essa localização.

mkdir ./Modules
Copy-Item -Path /mymodules/mycustommodule -Destination ./Modules -Recurse

Com uma pasta Modules, seu aplicativo de funções deve ter a seguinte estrutura de pastas:

PSFunctionApp
 | - MyFunction
 | | - run.ps1
 | | - function.json
 | - Modules
 | | - MyCustomModule
 | | - MyOtherCustomModule
 | | - MySpecialModule.psm1
 | - local.settings.json
 | - host.json
 | - requirements.psd1

Quando você inicia o aplicativo de funções, o trabalho de linguagem do PowerShell adiciona a pasta Modules a $env:PSModulePath para que você use o carregamento automático de módulo do mesmo jeito que faria em um script normal do PowerShell.

Pasta de módulos de nível de trabalho do idioma

Vários módulos são usados comumente pelo trabalho de linguagem do PowerShell. Esses módulos são definidos na última posição de PSModulePath.

A lista de módulos atual é a seguinte:

  • Microsoft.PowerShell.Archive: módulo usado para trabalhar com arquivos, como .zip, .nupkg e outros.
  • ThreadJob: uma implementação baseada em thread das APIs de trabalho do PowerShell.

Por padrão, o Functions usa a versão mais recente desses módulos. Para usar uma versão de módulo específica, coloque-a na pasta Modules do aplicativo de funções.

Variáveis de ambiente

Em funções, configurações do aplicativo, como conexão de serviço cadeias de caracteres, são expostas como variáveis de ambiente durante a execução. Acesse essas configurações usando $env:NAME_OF_ENV_VAR, conforme mostrado no exemplo seguinte:

param($myTimer)

Write-Host "PowerShell timer trigger function ran! $(Get-Date)"
Write-Host $env:AzureWebJobsStorage
Write-Host $env:WEBSITE_SITE_NAME

Há várias maneiras de adicionar, atualizar e excluir configurações do aplicativo de funções:

As alterações nas configurações do aplicativo de funções exigem que o seu aplicativo de funções seja reiniciado.

Ao executar localmente, as configurações do aplicativo são lidos a partir de Settings arquivo de projeto.

Simultaneidade

Por padrão, o runtime das Funções do PowerShell só pode processar uma invocação de uma função por vez. No entanto, o nível de simultaneidade pode não ser suficiente nestas situações:

  • Quando você tenta lidar com muitas invocações ao mesmo tempo.
  • Quando você tem funções que invocam outras funções dentro do mesmo aplicativo de funções.

Existem alguns modelos de simultaneidade que você pode usar de acordo com o tipo de carga de trabalho:

  • Aumentar FUNCTIONS_WORKER_PROCESS_COUNT. Assim é possível processar invocações de função em vários processos com a mesma instância, o que gera certa sobrecarga de CPU e memória. Em geral, as funções associadas a E/S não são afetadas por essa sobrecarga. Para funções associadas à CPU, o impacto pode ser significativo.

  • Aumentar o valor PSWorkerInProcConcurrencyUpperBound de configuração do aplicativo. Assim é possível criar vários runspaces dentro do mesmo processo, o que reduz significativamente a sobrecarga de CPU e memória.

Defina essas variáveis de ambiente nas configurações do aplicativo de funções.

Dependendo do seu caso de uso, o Durable Functions pode aprimorar significativamente a escalabilidade. Para saber mais, confira Padrões de aplicativo do Durable Functions.

Observação

Talvez você receba avisos de "solicitações estão sendo colocadas na fila porque não há runspaces disponíveis". Isso não é um erro. A mensagem está informando que as solicitações estão sendo colocadas na fila e serão processadas quando as solicitações anteriores forem concluídas.

Considerações sobre o uso da simultaneidade

O PowerShell é uma linguagem de script single_threaded por padrão. No entanto, a simultaneidade pode ser adicionada usando vários runspaces do PowerShell no mesmo processo. O número de runspaces criados e, portanto, o número de threads simultâneos por trabalho, é limitada pela configuração do aplicativo PSWorkerInProcConcurrencyUpperBound. Por padrão, o número de runspaces é definido como 1.000 na versão 4.x do runtime do Functions. Nas versões 3.x e inferiores, o número máximo de runspaces é definido como 1. A taxa de transferência será afetada pela quantidade de CPU e memória disponíveis no plano selecionado.

O Azure PowerShell usa alguns contextos de nível de processo e um estado para ajudar você a evitar a digitação de excesso de tipos. No entanto, se você ativar a simultaneidade no aplicativo de funções e invocar ações que alteram o estado, poderá acabar com condições de corrida. Essas condições de corrida são difíceis de depurar porque uma invocação depende de um determinado estado e a outra invocação alterou o estado.

Há um grande valor na simultaneidade com o Azure PowerShell, já que algumas operações podem levar um tempo considerável. No entanto, você deve continuar com cautela. Caso suspeite que está experimentando uma condição de corrida, defina a configuração de aplicativo PSWorkerInProcConcurrencyUpperBound como 1 e use o isolamento de nível do processo de trabalho de linguagem para simultaneidade.

Configurar a função scriptfile

Por padrão, uma função do PowerShell é executada do run.ps1, um arquivo que compartilha o mesmo diretório pai que seu function.json correspondente.

A propriedade scriptFile em function.json pode ser usada para obter uma estrutura de pastas semelhante a este exemplo:

FunctionApp
 | - host.json
 | - myFunction
 | | - function.json
 | - lib
 | | - PSFunction.ps1

Nesse caso, o function.json de myFunction tem uma propriedade scriptFile que faz referência ao arquivo com a função exportada a ser executada.

{
  "scriptFile": "../lib/PSFunction.ps1",
  "bindings": [
    // ...
  ]
}

Usar módulos do PowerShell configurando um entryPoint

Este artigo mostrou as funções do PowerShell no arquivo de script run.ps1 padrão gerado pelos modelos. No entanto, também é possível incluir suas funções nos módulos do PowerShell. É possível referenciar seu código de função específico no módulo usando os campos scriptFile e entryPoint no arquivo de configuração function.json`.

Nesse caso, entryPoint é o nome de uma função ou cmdlet no módulo do PowerShell referenciado em scriptFile.

Considere a seguinte estrutura de pastas:

FunctionApp
 | - host.json
 | - myFunction
 | | - function.json
 | - lib
 | | - PSFunction.psm1

Em que PSFunction.psm1 contém:

function Invoke-PSTestFunc {
    param($InputBinding, $TriggerMetadata)

    Push-OutputBinding -Name OutputBinding -Value "output"
}

Export-ModuleMember -Function "Invoke-PSTestFunc"

Neste exemplo, a configuração de myFunction inclui uma propriedade scriptFile que faz referência a PSFunction.psm1, que é um módulo do PowerShell em outra pasta. A propriedade entryPoint faz referência à função Invoke-PSTestFunc, que é o ponto de entrada no módulo.

{
  "scriptFile": "../lib/PSFunction.psm1",
  "entryPoint": "Invoke-PSTestFunc",
  "bindings": [
    // ...
  ]
}

Com essa configuração, o Invoke-PSTestFunc é executado exatamente como run.ps1.

Considerações sobre as funções do PowerShell

Ao trabalhar com as funções do PowerShell, lembre-se das considerações nas seções a seguir.

Inicialização a frio

No desenvolvimento do Azure Functions no modelo de hospedagem sem servidor, as inicializações a frio são uma realidade. Inicialização a frio é o tempo que leva para um aplicativo de funções iniciar a execução para processar uma solicitação. Ela acontece com mais frequência no plano de consumo porque o aplicativo de funções é desligado durante períodos de inatividade.

Empacotar módulos em vez de usar Install-Module

O script é executado em cada invocação. Evite usar Install-Module no seu script. Em vez disso, use Save-Module antes de publicar para que a função não perca tempo baixando o módulo. Se as inicializações a frio estiverem afetando suas funções, considere implantar seu aplicativo de funções em um Plano do Serviço de Aplicativo definido como Always On ou em um plano Premium.

Próximas etapas

Para saber mais, consulte os recursos a seguir: