How to use the Azure WebJobs SDK for event-driven background processing (Como utilizar o SDK de WebJobs do Azure para processamento em segundo plano condicionado por eventos)
Este artigo fornece orientação sobre como trabalhar com o SDK do Azure WebJobs. Para começar a usar WebJobs imediatamente, consulte Introdução ao SDK do Azure WebJobs.
Versões do SDK de WebJobs
Estas são as principais diferenças entre a versão 3.x e versão 2.x do SDK WebJobs:
- Versão 3.x adiciona suporte para .NET Core.
- Na versão 3.x, você instalará a extensão de vinculação de armazenamento exigida pelo SDK WebJobs. Na versão 2.x, as associações de armazenamento estão incluídas no SDK.
- Ferramentas do Visual Studio 2019 para .NET Core (3.x) os projetos diferem das ferramentas para o .NET Framework (2.x) projetos. Para saber mais, consulte Desenvolver e implantar WebJobs usando o Visual Studio - Serviço de Aplicativo do Azure.
Várias descrições neste artigo fornecem exemplos para ambos WebJobs versão 3.x e WebJobs versão 2.x.
O Azure Functions é baseado no SDK de WebJobs.
- Azure Functions versão 2.x é construído em WebJobs SDK versão 3.x.
- Azure Functions versão 1.x é construído em WebJobs SDK versão 2.x.
Os repositórios de código-fonte para o SDK do Azure Functions e WebJobs usam a numeração do SDK do WebJobs. Várias seções deste artigo de instruções têm link para a documentação do Azure Functions.
Para obter mais informações, consulte Comparar o SDK de WebJobs e o Azure Functions
Anfitrião WebJobs
O host é um contêiner de tempo de execução para funções. O Host escuta as funções de gatilhos e chamadas. Na versão 3.x, o host é uma implementação do IHost
. Na versão 2.x, você usa o JobHost
objeto. Você cria uma instância de host em seu código e escreve código para personalizar seu comportamento.
Essa é uma diferença fundamental entre usar o SDK de WebJobs diretamente e usá-lo indiretamente por meio do Azure Functions. No Azure Functions, o serviço controla o host e você não pode personalizá-lo escrevendo código. O Azure Functions permite personalizar o comportamento do host por meio de configurações no arquivo host.json. Essas configurações são strings, não código, e o uso dessas strings limita os tipos de personalizações que você pode fazer.
Conexões de host
O SDK WebJobs procura conexões do Armazenamento do Azure e do Barramento de Serviço do Azure no arquivo local.settings.json quando você executa localmente ou no ambiente do WebJob quando executa no Azure. Por padrão, o SDK WebJobs requer uma conexão de armazenamento com o nome AzureWebJobsStorage
.
Quando o nome da conexão é resolvido para um único valor exato, o tempo de execução identifica o valor como uma cadeia de conexão, que normalmente inclui um segredo. Os detalhes de uma cadeia de conexão dependem do serviço ao qual você se conecta. No entanto, um nome de conexão também pode se referir a uma coleção de vários itens de configuração, úteis para configurar conexões baseadas em identidade. As variáveis de ambiente podem ser tratadas como uma coleção usando um prefixo compartilhado que termina em sublinhados __
duplos. O grupo pode então ser referenciado definindo o nome da conexão para esse prefixo.
Por exemplo, a propriedade para uma definição de gatilho connection
de Blob do Azure pode ser Storage1
. Contanto que não haja um único valor de cadeia de caracteres configurado por uma variável de ambiente chamada Storage1
, uma variável de ambiente nomeada Storage1__blobServiceUri
pode ser usada para informar a blobServiceUri
propriedade da conexão. As propriedades de conexão são diferentes para cada serviço. Consulte a documentação do componente que usa a conexão.
Conexões baseadas em identidade
Para usar conexões baseadas em identidade no SDK WebJobs, certifique-se de estar usando as versões mais recentes dos pacotes WebJobs em seu projeto. Você também deve garantir que tenha uma referência a Microsoft.Azure.WebJobs.Host.Storage. A seguir está um exemplo de como seu arquivo de projeto pode parecer depois de fazer essas atualizações:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net48</TargetFramework>
<IsWebJobProject>true</IsWebJobProject>
<WebJobName>$(AssemblyName)</WebJobName>
<WebJobType>Continuous</WebJobType>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Azure.WebJobs" Version="3.0.41" />
<PackageReference Include="Microsoft.Azure.WebJobs.Extensions.Storage.Queues" Version="5.3.1" />
<PackageReference Include="Microsoft.Azure.WebJobs.Host.Storage" Version="5.0.1" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="2.1.1" />
</ItemGroup>
<ItemGroup>
<None Update="appsettings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>
Ao configurar WebJobs em seu HostBuilder, certifique-se de incluir uma chamada para AddAzureStorageCoreServices
, pois é isso que permite AzureWebJobsStorage
que outros gatilhos e associações de armazenamento usem identidade:
builder.ConfigureWebJobs(b =>
{
b.AddAzureStorageCoreServices();
// other configurations...
});
Em seguida, você pode configurar a conexão definindo variáveis de AzureWebJobsStorage
ambiente (ou Configurações do Aplicativo quando hospedado no Serviço de Aplicativo):
Variável de ambiente | Description | Valor de exemplo |
---|---|---|
AzureWebJobsStorage__blobServiceUri |
O URI do plano de dados do serviço de blob da conta de armazenamento, usando o esquema HTTPS. | https://< storage_account_name.blob.core.windows.net> |
AzureWebJobsStorage__queueServiceUri |
O URI do plano de dados do serviço de fila da conta de armazenamento, usando o esquema HTTPS. | https://< storage_account_name.queue.core.windows.net> |
Se você fornecer sua configuração por qualquer meio que não seja variáveis de ambiente, como com um appsettings.json
, em vez disso, você precisará fornecer configuração estruturada para a conexão e suas propriedades:
{
"AzureWebJobsStorage": {
"blobServiceUri": "https://<storage_account_name>.blob.core.windows.net",
"queueServiceUri": "https://<storage_account_name>.queue.core.windows.net"
}
}
Você pode omitir a queueServiceUri
propriedade se não planeja usar gatilhos de blob.
Quando seu código é executado localmente, o padrão é usar sua identidade de desenvolvedor de acordo com o comportamento descrito para DefaultAzureCredential.
Quando seu código é hospedado no Serviço de Aplicativo do Azure, a configuração mostrada acima será padrão para a identidade gerenciada atribuída pelo sistema para o recurso. Para usar uma identidade atribuída ao usuário que foi atribuída ao aplicativo, você precisa adicionar propriedades adicionais para sua conexão que especifiquem qual identidade deve ser usada. A credential
propriedade (AzureWebJobsStorage__credential
como uma variável de ambiente) deve ser definida como a string "managedidentity". A clientId
propriedade (AzureWebJobsStorage__clientId
como uma variável de ambiente) deve ser definida como a ID do cliente da identidade gerenciada atribuída pelo usuário a ser usada. Como configuração estruturada, o objeto completo seria:
{
"AzureWebJobsStorage": {
"blobServiceUri": "https://<storage_account_name>.blob.core.windows.net",
"queueServiceUri": "https://<storage_account_name>.queue.core.windows.net",
"credential": "managedidentity",
"clientId": "<user-assigned-identity-client-id>"
}
}
A identidade usada para AzureWebJobsStorage
deve ter atribuições de função que lhe concedam as funções de Proprietário de Dados de Blob de Armazenamento, Colaborador de Dados da Fila de Armazenamento e Colaborador de Conta de Armazenamento . Você pode omitir o Colaborador de Dados da Fila de Armazenamento e o Colaborador da Conta de Armazenamento se não planeja usar gatilhos de blob.
A tabela a seguir mostra funções internas que são recomendadas ao usar gatilhos em associações em operação normal. Seu aplicativo pode exigir permissões adicionais com base no código que você escreve.
Enlace | Exemplo de funções internas |
---|---|
Blob trigger | Proprietário de dados de Blob de armazenamento e contribuidor de dados da fila de armazenamento Veja acima os requisitos também AzureWebJobsStorage . |
Blob (entrada) | Leitor de Dados do Armazenamento de Blobs |
Blob (saída) | Proprietário dos Dados do Armazenamento de Blobs |
Queue trigger | Leitor de dados da fila de armazenamento, processador de mensagens de dados da fila de armazenamento |
Fila (saída) | Contribuidor de dados da fila de armazenamento, remetente de mensagem de dados da fila de armazenamento |
Gatilho doService Bus 1 | Recetor de Dados do Barramento de Serviço do Azure, Proprietário de Dados do Barramento de Serviço do Azure |
Service Bus (saída) | Remetente de dados do Barramento de Serviço do Azure |
1 Para acionar a partir de tópicos do Service Bus, a atribuição de função precisa ter escopo efetivo sobre o recurso de assinatura do Service Bus. Se apenas estiver incluído o tópico, ocorrerá um erro. Alguns clientes, como o portal do Azure, não expõem o recurso de subscrição do Service Bus como um âmbito para atribuição de função. Nesses casos, a CLI do Azure pode ser usada. Para saber mais, consulte Funções internas do Azure para o Barramento de Serviço do Azure.
Cadeias de conexão na versão 2.x
Versão 2.x do SDK não requer um nome específico. Versão 2.x permite que você use seus próprios nomes para essas cadeias de conexão e permite armazená-los em outro lugar. Você pode definir nomes no código usando o JobHostConfiguration
, como este:
static void Main(string[] args)
{
var _storageConn = ConfigurationManager
.ConnectionStrings["MyStorageConnection"].ConnectionString;
//// Dashboard logging is deprecated; use Application Insights.
//var _dashboardConn = ConfigurationManager
// .ConnectionStrings["MyDashboardConnection"].ConnectionString;
JobHostConfiguration config = new JobHostConfiguration();
config.StorageConnectionString = _storageConn;
//config.DashboardConnectionString = _dashboardConn;
JobHost host = new JobHost(config);
host.RunAndBlock();
}
Nota
Porque a versão 3.x usa as APIs de configuração padrão do .NET Core, não há nenhuma API para alterar nomes de cadeia de conexão. Consulte Desenvolver e implantar WebJobs usando o Visual Studio
Configurações de desenvolvimento do host
Você pode executar o host no modo de desenvolvimento para tornar o desenvolvimento local mais eficiente. Aqui estão algumas das configurações que mudam automaticamente quando você executa no modo de desenvolvimento:
Property | Configuração de desenvolvimento |
---|---|
Tracing.ConsoleLevel |
TraceLevel.Verbose para maximizar a saída do log. |
Queues.MaxPollingInterval |
Um valor baixo para garantir que os métodos de fila sejam acionados imediatamente. |
Singleton.ListenerLockPeriod |
15 segundos para ajudar no rápido desenvolvimento iterativo. |
O processo para habilitar o modo de desenvolvimento depende da versão do SDK.
Versão 3.x
Versão 3.x usa o padrão ASP.NET Core APIs. Chame HostBuilder
o UseEnvironment
método na instância. Passe uma cadeia de caracteres chamada development
, como neste exemplo:
static async Task Main()
{
var builder = new HostBuilder();
builder.UseEnvironment("development");
builder.ConfigureWebJobs(b =>
{
b.AddAzureStorageCoreServices();
});
var host = builder.Build();
using (host)
{
await host.RunAsync();
}
}
Versão 2.x
A JobHostConfiguration
classe tem um método que permite o UseDevelopmentSettings
modo de desenvolvimento. O exemplo a seguir mostra como usar as configurações de desenvolvimento. Para retornar config.IsDevelopment
true
quando ele for executado localmente, defina uma variável de ambiente local nomeada AzureWebJobsEnv
com o valor Development
.
static void Main()
{
config = new JobHostConfiguration();
if (config.IsDevelopment)
{
config.UseDevelopmentSettings();
}
var host = new JobHost(config);
host.RunAndBlock();
}
Gerenciando conexões simultâneas (versão 2.x)
Na versão 3.x, o limite de conexão padrão para conexões infinitas. Se, por algum motivo, você precisar alterar esse limite, poderá usar a MaxConnectionsPerServer
WinHttpHandler
propriedade da classe.
Na versão 2.x, você controla o número de conexões simultâneas com um host usando a API ServicePointManager.DefaultConnectionLimit . Em 2.x, você deve aumentar esse valor a partir do padrão de 2 antes de iniciar seu host WebJobs.
Todas as solicitações HTTP de saída feitas a partir de uma função usando HttpClient
o fluxo através ServicePointManager
do . Depois de atingir o valor definido em DefaultConnectionLimit
, ServicePointManager
começa a enfileirar solicitações antes de enviá-las. Suponha que seu DefaultConnectionLimit
está definido como 2 e seu código faz 1.000 solicitações HTTP. Inicialmente, apenas duas solicitações são permitidas através do sistema operacional. Os outros 998 estão na fila até que haja espaço para eles. Isso significa que você HttpClient
pode atingir o tempo limite porque parece ter feito a solicitação, mas a solicitação nunca foi enviada pelo sistema operacional para o servidor de destino. Assim, você pode ver um comportamento que não parece fazer sentido: seu local HttpClient
está levando 10 segundos para concluir uma solicitação, mas seu serviço está retornando todas as solicitações em 200 ms.
O valor padrão para aplicativos ASP.NET é Int32.MaxValue
, e é provável que funcione bem para WebJobs em execução em um Plano de Serviço de Aplicativo Básico ou superior. Os WebJobs normalmente precisam da configuração Always On , e isso é suportado apenas pelos Planos de Serviço de Aplicativo Básicos e superiores.
Se o WebJob estiver sendo executado em um Plano de Serviço de Aplicativo Gratuito ou Compartilhado, seu aplicativo será restrito pela área restrita do Serviço de Aplicativo, que atualmente tem um limite de conexão de 300. Com um limite de conexão não acoplada no ServicePointManager
, é mais provável que o limite de conexão de área restrita seja atingido e o site seja encerrado. Nesse caso, definir DefaultConnectionLimit
para algo mais baixo, como 50 ou 100, pode impedir que isso aconteça e ainda permitir uma taxa de transferência suficiente.
A configuração deve ser configurada antes que qualquer solicitação HTTP seja feita. Por esse motivo, o host WebJobs não deve ajustar a configuração automaticamente. Pode haver solicitações HTTP que ocorrem antes do host iniciar, o que pode levar a um comportamento inesperado. A melhor abordagem é definir o valor imediatamente em seu Main
método antes de inicializar JobHost
, como mostrado aqui:
static void Main(string[] args)
{
// Set this immediately so that it's used by all requests.
ServicePointManager.DefaultConnectionLimit = Int32.MaxValue;
var host = new JobHost();
host.RunAndBlock();
}
Acionadores
O SDK de WebJobs dá suporte ao mesmo conjunto de gatilhos e associações usados pelo Azure Functions. Observe que no SDK do WebJobs, os gatilhos são específicos da função e não estão relacionados ao tipo de implantação do WebJob. WebJobs com funções acionadas por eventos criadas usando o SDK devem sempre ser publicados como um WebJob contínuo , com Always on habilitado.
As funções devem ser métodos públicos e devem ter um atributo trigger ou o NoAutomaticTrigger
atributo.
Gatilhos automáticos
Os gatilhos automáticos chamam uma função em resposta a um evento. Considere este exemplo de uma função acionada por uma mensagem adicionada ao armazenamento de filas do Azure. A função responde lendo um blob do armazenamento de Blob do Azure:
public static void Run(
[QueueTrigger("myqueue-items")] string myQueueItem,
[Blob("samples-workitems/{queueTrigger}", FileAccess.Read)] Stream myBlob,
ILogger log)
{
log.LogInformation($"BlobInput processed blob\n Name:{myQueueItem} \n Size: {myBlob.Length} bytes");
}
O QueueTrigger
atributo diz ao tempo de execução para chamar a função sempre que uma mensagem de fila aparecer no myqueue-items
. O Blob
atributo diz ao tempo de execução para usar a mensagem de fila para ler um blob no contêiner sample-workitems . O nome do item de blob no samples-workitems
contêiner é obtido diretamente do gatilho de fila como uma expressão de ligação ({queueTrigger}
).
Nota
Um aplicativo Web pode atingir o tempo limite após 20 minutos de inatividade, e somente solicitações para o aplicativo Web real podem redefinir o temporizador. Exibir a configuração do aplicativo no portal do Azure ou fazer solicitações para o site de ferramentas avançadas (https://<app_name>.scm.azurewebsites.net
) não redefine o temporizador. Se você definir o aplicativo Web que hospeda seu trabalho para ser executado continuamente, executado em uma agenda ou usar gatilhos controlados por eventos, habilite a configuração Sempre ligado na página Configuração do Azure do seu aplicativo Web. A configuração Sempre ligado ajuda a garantir que esses tipos de WebJobs sejam executados de forma confiável. Esse recurso está disponível apenas nos níveis de preços Basic, Standard e Premium.
Gatilhos manuais
Para acionar uma função manualmente, use o atributo NoAutomaticTrigger
, como mostrado aqui:
[NoAutomaticTrigger]
public static void CreateQueueMessage(
ILogger logger,
string value,
[Queue("outputqueue")] out string message)
{
message = value;
logger.LogInformation("Creating queue message: ", message);
}
O processo para acionar manualmente a função depende da versão do SDK.
Versão 3.x
static async Task Main(string[] args)
{
var builder = new HostBuilder();
builder.ConfigureWebJobs(b =>
{
b.AddAzureStorageCoreServices();
b.AddAzureStorage();
});
var host = builder.Build();
using (host)
{
var jobHost = host.Services.GetService(typeof(IJobHost)) as JobHost;
var inputs = new Dictionary<string, object>
{
{ "value", "Hello world!" }
};
await host.StartAsync();
await jobHost.CallAsync("CreateQueueMessage", inputs);
await host.StopAsync();
}
}
Versão 2.x
static void Main(string[] args)
{
JobHost host = new JobHost();
host.Call(typeof(Program).GetMethod("CreateQueueMessage"), new { value = "Hello world!" });
}
Ligações de entrada e saída
As associações de entrada fornecem uma maneira declarativa de disponibilizar dados do Azure ou de serviços de terceiros para seu código. As ligações de saída fornecem uma maneira de atualizar dados. O artigo Introdução mostra um exemplo de cada um.
Você pode usar um valor de retorno de método para uma associação de saída aplicando o atributo ao valor de retorno do método. Veja o exemplo em Usando o valor de retorno da Função do Azure.
Tipos de vinculação
O processo de instalação e gerenciamento de tipos de vinculação depende se você está usando a versão 3.x ou versão 2.x do SDK. Você pode encontrar o pacote a ser instalado para um tipo de associação específico na seção "Pacotes" do artigo de referência do Azure Functions desse tipo de associação. Uma exceção é o gatilho e a associação de arquivos Arquivos (para o sistema de arquivos local), que não é suportado pelo Azure Functions.
Versão 3.x
Na versão 3.x, as ligações de armazenamento estão incluídas no Microsoft.Azure.WebJobs.Extensions.Storage
pacote. Chame ConfigureWebJobs
o AddAzureStorage
método de extensão no método, como mostrado aqui:
static async Task Main()
{
var builder = new HostBuilder();
builder.ConfigureWebJobs(b =>
{
b.AddAzureStorageCoreServices();
b.AddAzureStorage();
});
var host = builder.Build();
using (host)
{
await host.RunAsync();
}
}
Para usar outros tipos de gatilho e ligação, instale o pacote NuGet que os contém e chame o Add<binding>
método de extensão implementado na extensão. Por exemplo, se você quiser usar uma associação do Azure Cosmos DB, instale Microsoft.Azure.WebJobs.Extensions.CosmosDB
e chame AddCosmosDB
, desta forma:
static async Task Main()
{
var builder = new HostBuilder();
builder.ConfigureWebJobs(b =>
{
b.AddAzureStorageCoreServices();
b.AddCosmosDB();
});
var host = builder.Build();
using (host)
{
await host.RunAsync();
}
}
Para usar o gatilho de Timer ou a associação de arquivos, que fazem parte dos serviços principais, chame os AddTimers
métodos de extensão ou AddFiles
.
Versão 2.x
Esses tipos de gatilho e vinculação estão incluídos na versão 2.x do Microsoft.Azure.WebJobs
pacote:
- Armazenamento de Blobs
- Armazenamento de filas
- Armazenamento de tabelas
Para usar outros tipos de gatilho e ligação, instale o pacote NuGet que os contém e chame JobHostConfiguration
um Use<binding>
método no objeto. Por exemplo, se você quiser usar um gatilho de Timer, instale Microsoft.Azure.WebJobs.Extensions
e chame UseTimers
o Main
método, conforme mostrado aqui:
static void Main()
{
config = new JobHostConfiguration();
config.UseTimers();
var host = new JobHost(config);
host.RunAndBlock();
}
Para usar a ligação Arquivos, instale Microsoft.Azure.WebJobs.Extensions
e chame UseFiles
o .
ExecutionContext
WebJobs permite que você se associe a um ExecutionContext
arquivo . Com essa ligação, você pode acessar o ExecutionContext
como um parâmetro em sua assinatura de função. Por exemplo, o código a seguir usa o objeto de contexto para acessar a ID de invocação, que você pode usar para correlacionar todos os logs produzidos por uma determinada chamada de função.
public class Functions
{
public static void ProcessQueueMessage([QueueTrigger("queue")] string message,
ExecutionContext executionContext,
ILogger logger)
{
logger.LogInformation($"{message}\n{executionContext.InvocationId}");
}
}
O processo de vinculação ao depende da sua versão do ExecutionContext
SDK.
Versão 3.x
Chame ConfigureWebJobs
o AddExecutionContextBinding
método de extensão no método, como mostrado aqui:
static async Task Main()
{
var builder = new HostBuilder();
builder.ConfigureWebJobs(b =>
{
b.AddAzureStorageCoreServices();
b.AddExecutionContextBinding();
});
var host = builder.Build();
using (host)
{
await host.RunAsync();
}
}
Versão 2.x
O Microsoft.Azure.WebJobs.Extensions
pacote mencionado anteriormente também fornece um tipo de vinculação especial que você pode registrar chamando o UseCore
método. Essa associação permite definir um parâmetro na assinatura da ExecutionContext
função, que é habilitada da seguinte forma:
class Program
{
static void Main()
{
config = new JobHostConfiguration();
config.UseCore();
var host = new JobHost(config);
host.RunAndBlock();
}
}
Configuração de vinculação
Você pode configurar o comportamento de alguns gatilhos e associações. O processo para configurá-los depende da versão do SDK.
- Versão 3.x: Defina a configuração quando o
Add<Binding>
método for chamado emConfigureWebJobs
. - Versão 2.x: Defina a configuração definindo propriedades em um objeto de configuração para o qual você passa para
JobHost
.
Essas configurações específicas de associação são equivalentes às configurações no arquivo de projeto host.json no Azure Functions.
Você pode configurar as seguintes associações:
- Gatilho do Azure Cosmos DB
- Os Hubs de Eventos disparam
- Gatilho de armazenamento em fila
- Vinculação SendGrid
- Gatilho do Service Bus
Configuração de gatilho do Azure Cosmos DB (versão 3.x)
Este exemplo mostra como configurar o gatilho do Azure Cosmos DB:
static async Task Main()
{
var builder = new HostBuilder();
builder.ConfigureWebJobs(b =>
{
b.AddAzureStorageCoreServices();
b.AddCosmosDB(a =>
{
a.ConnectionMode = ConnectionMode.Gateway;
a.Protocol = Protocol.Https;
a.LeaseOptions.LeasePrefix = "prefix1";
});
});
var host = builder.Build();
using (host)
{
await host.RunAsync();
}
}
Para obter mais informações, consulte o artigo de vinculação do Azure Cosmos DB.
Os Hubs de Eventos acionam a configuração (versão 3.x)
Este exemplo mostra como configurar o gatilho Hubs de Eventos:
static async Task Main()
{
var builder = new HostBuilder();
builder.ConfigureWebJobs(b =>
{
b.AddAzureStorageCoreServices();
b.AddEventHubs(a =>
{
a.BatchCheckpointFrequency = 5;
a.EventProcessorOptions.MaxBatchSize = 256;
a.EventProcessorOptions.PrefetchCount = 512;
});
});
var host = builder.Build();
using (host)
{
await host.RunAsync();
}
}
Para obter mais informações, consulte o artigo de vinculação de Hubs de Eventos.
Configuração do gatilho de armazenamento em fila
Os exemplos a seguir mostram como configurar o gatilho de armazenamento de fila.
Versão 3.x
static async Task Main()
{
var builder = new HostBuilder();
builder.ConfigureWebJobs(b =>
{
b.AddAzureStorageCoreServices();
b.AddAzureStorage(a => {
a.BatchSize = 8;
a.NewBatchThreshold = 4;
a.MaxDequeueCount = 4;
a.MaxPollingInterval = TimeSpan.FromSeconds(15);
});
});
var host = builder.Build();
using (host)
{
await host.RunAsync();
}
}
Para obter mais informações, consulte o artigo Vinculação de armazenamento em fila.
Versão 2.x
static void Main(string[] args)
{
JobHostConfiguration config = new JobHostConfiguration();
config.Queues.BatchSize = 8;
config.Queues.NewBatchThreshold = 4;
config.Queues.MaxDequeueCount = 4;
config.Queues.MaxPollingInterval = TimeSpan.FromSeconds(15);
JobHost host = new JobHost(config);
host.RunAndBlock();
}
Para obter mais informações, consulte a referência host.json v1.x.
Configuração de vinculação do SendGrid (versão 3.x)
Este exemplo mostra como configurar a ligação de saída SendGrid:
static async Task Main()
{
var builder = new HostBuilder();
builder.ConfigureWebJobs(b =>
{
b.AddAzureStorageCoreServices();
b.AddSendGrid(a =>
{
a.FromAddress.Email = "samples@functions.com";
a.FromAddress.Name = "Azure Functions";
});
});
var host = builder.Build();
using (host)
{
await host.RunAsync();
}
}
Para obter mais informações, consulte o artigo de vinculação SendGrid.
Configuração de gatilho do Service Bus (versão 3.x)
Este exemplo mostra como configurar o gatilho do Service Bus:
static async Task Main()
{
var builder = new HostBuilder();
builder.ConfigureWebJobs(b =>
{
b.AddAzureStorageCoreServices();
b.AddServiceBus(sbOptions =>
{
sbOptions.MessageHandlerOptions.AutoComplete = true;
sbOptions.MessageHandlerOptions.MaxConcurrentCalls = 16;
});
});
var host = builder.Build();
using (host)
{
await host.RunAsync();
}
}
Para obter mais detalhes, consulte o artigo de vinculação do Service Bus.
Configuração para outras ligações
Alguns tipos de gatilho e associação definem seus próprios tipos de configuração personalizada. Por exemplo, o gatilho File permite especificar o caminho raiz a ser monitorado, como nos exemplos a seguir.
Versão 3.x
static async Task Main()
{
var builder = new HostBuilder();
builder.ConfigureWebJobs(b =>
{
b.AddAzureStorageCoreServices();
b.AddFiles(a => a.RootPath = @"c:\data\import");
});
var host = builder.Build();
using (host)
{
await host.RunAsync();
}
}
Versão 2.x
static void Main()
{
config = new JobHostConfiguration();
var filesConfig = new FilesConfiguration
{
RootPath = @"c:\data\import"
};
config.UseFiles(filesConfig);
var host = new JobHost(config);
host.RunAndBlock();
}
Expressões de enlace
Em parâmetros do construtor de atributos, você pode usar expressões que resolvem para valores de várias fontes. Por exemplo, no código a seguir, o caminho para o BlobTrigger
atributo cria uma expressão chamada filename
. Quando usado para a ligação de saída, filename
resolve para o nome do blob de acionamento.
public static void CreateThumbnail(
[BlobTrigger("sample-images/{filename}")] Stream image,
[Blob("sample-images-sm/{filename}", FileAccess.Write)] Stream imageSmall,
string filename,
ILogger logger)
{
logger.Info($"Blob trigger processing: {filename}");
// ...
}
Para obter mais informações sobre expressões de associação, consulte Vinculando expressões e padrões na documentação do Azure Functions.
Expressões de vinculação personalizadas
Às vezes, você deseja especificar um nome de fila, um nome de blob ou contêiner ou um nome de tabela no código em vez de codificá-lo. Por exemplo, talvez você queira especificar o nome da fila para o QueueTrigger
atributo em um arquivo de configuração ou variável de ambiente.
Você pode fazer isso passando um resolvedor de nome personalizado durante a configuração. Você inclui espaços reservados em parâmetros do construtor de atributos de gatilho ou vinculação, e seu código de resolvedor fornece os valores reais a serem usados no lugar desses espaços reservados. Você identifica espaços reservados cercando-os com sinais de porcentagem (%), conforme mostrado aqui:
public static void WriteLog([QueueTrigger("%logqueue%")] string logMessage)
{
Console.WriteLine(logMessage);
}
Esse código permite que você use uma fila nomeada logqueuetest
no ambiente de teste e uma chamada logqueueprod
na produção. Em vez de um nome de fila codificado, especifique o nome de uma entrada na appSettings
coleção.
Há um resolvedor padrão que entra em vigor se você não fornecer um personalizado. O padrão obtém valores de configurações de aplicativo ou variáveis de ambiente.
A partir do .NET Core 3.1, o ConfigurationManager
uso requer o pacote NuGet System.Configuration.ConfigurationManager. O exemplo requer a seguinte using
instrução:
using System.Configuration;
Sua NameResolver
classe obtém o nome da fila nas configurações do aplicativo, conforme mostrado aqui:
public class CustomNameResolver : INameResolver
{
public string Resolve(string name)
{
return ConfigurationManager.AppSettings[name].ToString();
}
}
Versão 3.x
Configure o resolvedor usando a injeção de dependência. Esses exemplos exigem a seguinte using
instrução:
using Microsoft.Extensions.DependencyInjection;
Você adiciona o resolvedor chamando o ConfigureServices
método de extensão no HostBuilder
, como neste exemplo:
static async Task Main(string[] args)
{
var builder = new HostBuilder();
var resolver = new CustomNameResolver();
builder.ConfigureWebJobs(b =>
{
b.AddAzureStorageCoreServices();
});
builder.ConfigureServices(s => s.AddSingleton<INameResolver>(resolver));
var host = builder.Build();
using (host)
{
await host.RunAsync();
}
}
Versão 2.x
Passe sua NameResolver
classe para o JobHost
objeto, conforme mostrado aqui:
static void Main(string[] args)
{
JobHostConfiguration config = new JobHostConfiguration();
config.NameResolver = new CustomNameResolver();
JobHost host = new JobHost(config);
host.RunAndBlock();
}
O Azure Functions implementa INameResolver
para obter valores das configurações do aplicativo, conforme mostrado no exemplo. Ao usar o SDK WebJobs diretamente, você pode escrever uma implementação personalizada que obtém valores de substituição de espaço reservado de qualquer fonte de sua preferência.
Vinculação em tempo de execução
Se você precisar fazer algum trabalho em sua função antes de usar um atributo de vinculação como Queue
, Blob
ou Table
, você pode usar a IBinder
interface.
O exemplo a seguir pega uma mensagem de fila de entrada e cria uma nova mensagem com o mesmo conteúdo em uma fila de saída. O nome da fila de saída é definido por código no corpo da função.
public static void CreateQueueMessage(
[QueueTrigger("inputqueue")] string queueMessage,
IBinder binder)
{
string outputQueueName = "outputqueue" + DateTime.Now.Month.ToString();
QueueAttribute queueAttribute = new QueueAttribute(outputQueueName);
CloudQueue outputQueue = binder.Bind<CloudQueue>(queueAttribute);
outputQueue.AddMessageAsync(new CloudQueueMessage(queueMessage));
}
Para obter mais informações, consulte Vinculação em tempo de execução na documentação do Azure Functions.
Informações de referência vinculativas
A documentação do Azure Functions fornece informações de referência sobre cada tipo de associação. Você encontrará as seguintes informações em cada artigo de referência de vinculação. (Este exemplo é baseado na fila de armazenamento.)
- Embalagens. O pacote que você precisa instalar para incluir suporte para a associação em um projeto SDK WebJobs.
- Exemplos. Exemplos de código. O exemplo de biblioteca de classes C# se aplica ao SDK WebJobs. Basta omitir o
FunctionName
atributo. - Atributos. Os atributos a serem usados para o tipo de vinculação.
- Configuração. Explicações das propriedades do atributo e parâmetros do construtor.
- Utilização. Os tipos aos quais você pode vincular e informações sobre como a associação funciona. Por exemplo: algoritmo de sondagem, processamento de fila de veneno.
Nota
As ligações HTTP, Webhooks e Grade de Eventos são suportadas apenas pelo Azure Functions, não pelo SDK WebJobs.
Para obter uma lista completa das associações suportadas no tempo de execução do Azure Functions, consulte Associações suportadas.
Atributos para Desativar, Tempo Limite e Singleton
Com esses atributos, você pode controlar o acionamento de funções, cancelar funções e garantir que apenas uma instância de uma função seja executada.
Desativar atributo
O Disable
atributo permite controlar se uma função pode ser acionada.
No exemplo a seguir, se a configuração Disable_TestJob
do aplicativo tiver um valor de ou True
(sem distinção entre maiúsculas e 1
minúsculas), a função não será executada. Nesse caso, o tempo de execução cria uma mensagem de log A função 'Functions.TestJob' está desativada.
[Disable("Disable_TestJob")]
public static void TestJob([QueueTrigger("testqueue2")] string message)
{
Console.WriteLine("Function with Disable attribute executed!");
}
Quando você altera os valores de configuração do aplicativo no portal do Azure, o WebJob é reiniciado para pegar a nova configuração.
O atributo pode ser declarado no nível do parâmetro, método ou classe. O nome da configuração também pode conter expressões de ligação.
Atributo Tempo limite
O Timeout
atributo faz com que uma função seja cancelada se ela não for concluída dentro de um período de tempo especificado. No exemplo a seguir, a função seria executada por um dia sem o atributo Timeout. O tempo limite faz com que a função seja cancelada após 15 segundos. Quando o parâmetro "throwOnError" do atributo Timeout é definido como "true", a invocação da função é encerrada por ter uma exceção lançada pelo SDK de webjobs quando o intervalo de tempo limite é excedido. O valor padrão de "throwOnError" é "false". Quando o atributo Timeout é usado, o comportamento padrão é cancelar a invocação da função definindo o token de cancelamento enquanto permite que a invocação seja executada indefinidamente até que o código da função retorne ou lance uma exceção.
[Timeout("00:00:15")]
public static async Task TimeoutJob(
[QueueTrigger("testqueue2")] string message,
CancellationToken token,
TextWriter log)
{
await log.WriteLineAsync("Job starting");
await Task.Delay(TimeSpan.FromDays(1), token);
await log.WriteLineAsync("Job completed");
}
Você pode aplicar o atributo Timeout no nível de classe ou método e pode especificar um tempo limite global usando JobHostConfiguration.FunctionTimeout
. Os tempos limite de nível de classe ou de método substituem os tempos limite globais.
Atributo Singleton
O Singleton
atributo garante que apenas uma instância de uma função seja executada, mesmo quando há várias instâncias do aplicativo Web host. O atributo Singleton usa bloqueio distribuído para garantir que uma instância seja executada.
Neste exemplo, apenas uma única instância da função é executada ProcessImage
a qualquer momento:
[Singleton]
public static async Task ProcessImage([BlobTrigger("images")] Stream image)
{
// Process the image.
}
SingletonMode.Listener
Alguns gatilhos têm suporte interno para gerenciamento de simultaneidade:
- QueueTrigger. Defina
JobHostConfiguration.Queues.BatchSize
como1
. - ServiceBusTrigger. Defina
ServiceBusConfiguration.MessageOptions.MaxConcurrentCalls
como1
. - FileTrigger. Defina
FileProcessor.MaxDegreeOfParallelism
como1
.
Você pode usar essas configurações para garantir que sua função seja executada como um singleton em uma única instância. Para garantir que apenas uma única instância da função esteja em execução quando o aplicativo Web for expandido para várias instâncias, aplique um bloqueio singleton no nível do ouvinte na função ([Singleton(Mode = SingletonMode.Listener)]
). Os bloqueios de ouvinte são adquiridos quando o JobHost é iniciado. Se três instâncias dimensionadas forem iniciadas ao mesmo tempo, apenas uma das instâncias adquirirá o bloqueio e apenas um ouvinte será iniciado.
Nota
Consulte este repositório GitHub para saber mais sobre como o SingletonMode.Function funciona.
Valores de escopo
Você pode especificar uma expressão/valor de escopo em um singleton. A expressão/valor garante que todas as execuções da função em um escopo específico serão serializadas. Implementar um bloqueio mais granular dessa maneira pode permitir algum nível de paralelismo para sua função enquanto serializa outras invocações conforme ditado por seus requisitos. Por exemplo, no código a seguir, a expressão de escopo se liga ao Region
valor da mensagem de entrada. Quando a fila contém três mensagens nas regiões Leste, Leste e Oeste, as mensagens com região Leste são executadas em série. A mensagem com a região Oeste é executada em paralelo com as da região Leste.
[Singleton("{Region}")]
public static async Task ProcessWorkItem([QueueTrigger("workitems")] WorkItem workItem)
{
// Process the work item.
}
public class WorkItem
{
public int ID { get; set; }
public string Region { get; set; }
public int Category { get; set; }
public string Description { get; set; }
}
SingletonScope.Host
O escopo padrão para um bloqueio é SingletonScope.Function
, o que significa que o escopo de bloqueio (o caminho de concessão de blob) está vinculado ao nome da função totalmente qualificada. Para bloquear entre funções, especifique SingletonScope.Host
e use um nome de ID de escopo que seja o mesmo em todas as funções que você não deseja executar simultaneamente. No exemplo a seguir, apenas uma instância de ou RemoveItem
é executada AddItem
de cada vez:
[Singleton("ItemsLock", SingletonScope.Host)]
public static void AddItem([QueueTrigger("add-item")] string message)
{
// Perform the add operation.
}
[Singleton("ItemsLock", SingletonScope.Host)]
public static void RemoveItem([QueueTrigger("remove-item")] string message)
{
// Perform the remove operation.
}
Visualizando blobs de leasing
O SDK de WebJobs usa concessões de blob do Azure sob as capas para implementar o bloqueio distribuído. Os blobs de leasing usados pela Singleton podem ser encontrados no azure-webjobs-host
contêiner na AzureWebJobsStorage
conta de armazenamento sob o caminho "locks". Por exemplo, o caminho do blob de concessão para o primeiro ProcessImage
exemplo mostrado anteriormente pode ser locks/061851c758f04938a4426aa9ab3869c0/WebJobs.Functions.ProcessImage
. Todos os caminhos incluem o ID JobHost, neste caso 061851c758f04938a4426aa9ab3869c0.
Funções assíncronas
Para obter informações sobre como codificar funções assíncronas, consulte a documentação do Azure Functions.
Tokens de cancelamento
Para obter informações sobre como lidar com tokens de cancelamento, consulte a documentação do Azure Functions sobre tokens de cancelamento e desligamento normal.
Múltiplas instâncias
Se seu aplicativo Web for executado em várias instâncias, um WebJob contínuo será executado em cada instância, ouvindo gatilhos e chamando funções. As várias associações de gatilho são projetadas para compartilhar eficientemente o trabalho de forma colaborativa entre instâncias, de modo que o dimensionamento para mais instâncias permita que você lide com mais carga.
Embora alguns gatilhos possam resultar em processamento duplo, os gatilhos de armazenamento de fila e blob impedem automaticamente que uma função processe uma mensagem de fila ou blob mais de uma vez. Para obter mais informações, consulte Projetando para entrada idêntica na documentação do Azure Functions.
O gatilho do temporizador garante automaticamente que apenas uma instância do temporizador seja executada, para que você não tenha mais de uma instância de função em execução em um determinado horário agendado.
Se quiser garantir que apenas uma instância de uma função seja executada mesmo quando houver várias instâncias do aplicativo Web host, você poderá usar o Singleton
atributo.
Filtros
Os Filtros de Função (visualização) fornecem uma maneira de personalizar o pipeline de execução de WebJobs com sua própria lógica. Os filtros são semelhantes aos filtros ASP.NET Core. Você pode implementá-los como atributos declarativos que são aplicados às suas funções ou classes. Para obter mais informações, consulte Filtros de função.
Registos e monitorização
Recomendamos a estrutura de registro em log que foi desenvolvida para ASP.NET. O artigo Introdução mostra como usá-lo.
Filtragem de logs
Cada log criado por uma ILogger
instância tem um associado Category
e Level
. LogLevel
é uma enumeração e o código inteiro indica importância relativa:
Nível de Registo | Código |
---|---|
Rastreio | 0 |
Depurar | 1 |
Informação | 2 |
Aviso | 3 |
Erro | 4 |
Crítico | 5 |
Nenhuma | 6 |
Você pode filtrar de forma independente cada categoria para um arquivo LogLevel
. Por exemplo, você pode querer ver todos os logs para processamento de gatilho de blob, mas apenas Error
e superior para todo o resto.
Versão 3.x
Versão 3.x do SDK depende da filtragem incorporada no .NET Core. A LogCategories
classe permite definir categorias para funções, gatilhos ou usuários específicos. Ele também define filtros para estados de host específicos, como Startup
e Results
. Isso permite que você ajuste a saída de log. Se nenhuma correspondência for encontrada dentro das categorias definidas, o filtro retornará ao Default
valor ao decidir se deseja filtrar a mensagem.
LogCategories
requer a seguinte instrução using:
using Microsoft.Azure.WebJobs.Logging;
O exemplo a seguir constrói um filtro que, por padrão, filtra todos os Warning
logs no nível. As Function
e results
categorias (equivalente à Host.Results
versão 2.x) são filtrados ao Error
nível. O filtro compara a categoria atual com todos os níveis registrados na LogCategories
instância e escolhe a correspondência mais longa. Isto significa que o nível registado Debug
para Host.Triggers
as partidas Host.Triggers.Queue
ou Host.Triggers.Blob
. Isso permite que você controle categorias mais amplas sem precisar adicionar cada uma.
static async Task Main(string[] args)
{
var builder = new HostBuilder();
builder.ConfigureWebJobs(b =>
{
b.AddAzureStorageCoreServices();
});
builder.ConfigureLogging(logging =>
{
logging.SetMinimumLevel(LogLevel.Warning);
logging.AddFilter("Function", LogLevel.Error);
logging.AddFilter(LogCategories.CreateFunctionCategory("MySpecificFunctionName"),
LogLevel.Debug);
logging.AddFilter(LogCategories.Results, LogLevel.Error);
logging.AddFilter("Host.Triggers", LogLevel.Debug);
});
var host = builder.Build();
using (host)
{
await host.RunAsync();
}
}
Versão 2.x
Na versão 2.x do SDK, você usa a classe para controlar a LogCategoryFilter
filtragem. O LogCategoryFilter
tem uma Default
propriedade com um valor inicial de Information
, o que significa que todas as Information
mensagens nos níveis , Warning
, Error
ou Critical
são registradas, mas todas as mensagens nos Debug
níveis ou Trace
são filtradas.
Tal como na LogCategories
versão 3.x, a CategoryLevels
propriedade permite especificar níveis de log para categorias específicas para que você possa ajustar a saída de log. Se nenhuma correspondência for encontrada no CategoryLevels
dicionário, o filtro retornará ao Default
valor ao decidir se deseja filtrar a mensagem.
O exemplo a seguir constrói um filtro que, por padrão, filtra todos os logs no Warning
nível. As Function
categorias e Host.Results
são filtradas no Error
nível. O LogCategoryFilter
compara a categoria atual com todos os inscritos CategoryLevels
e escolhe a partida mais longa. Assim, o nível registado Debug
para Host.Triggers
irá corresponder ou Host.Triggers.Queue
Host.Triggers.Blob
. Isso permite que você controle categorias mais amplas sem precisar adicionar cada uma.
var filter = new LogCategoryFilter();
filter.DefaultLevel = LogLevel.Warning;
filter.CategoryLevels[LogCategories.Function] = LogLevel.Error;
filter.CategoryLevels[LogCategories.Results] = LogLevel.Error;
filter.CategoryLevels["Host.Triggers"] = LogLevel.Debug;
config.LoggerFactory = new LoggerFactory()
.AddApplicationInsights(instrumentationKey, filter.Filter)
.AddConsole(filter.Filter);
Telemetria personalizada para o Application Insights
O processo de implementação da telemetria personalizada para o Application Insights depende da versão do SDK. Para saber como configurar o Application Insights, consulte Adicionar log do Application Insights.
Versão 3.x
Porque a versão 3.x do SDK WebJobs depende do host genérico .NET Core, uma fábrica de telemetria personalizada não é mais fornecida. Mas você pode adicionar telemetria personalizada ao pipeline usando a injeção de dependência. Os exemplos nesta seção exigem as seguintes using
instruções:
using Microsoft.ApplicationInsights.Extensibility;
using Microsoft.ApplicationInsights.Channel;
A seguinte implementação personalizada do ITelemetryInitializer
permite que você adicione o seu próprio ITelemetry
ao padrão TelemetryConfiguration
.
internal class CustomTelemetryInitializer : ITelemetryInitializer
{
public void Initialize(ITelemetry telemetry)
{
// Do something with telemetry.
}
}
Chame ConfigureServices
o construtor para adicionar seu personalizado ITelemetryInitializer
ao pipeline.
static async Task Main()
{
var builder = new HostBuilder();
builder.ConfigureWebJobs(b =>
{
b.AddAzureStorageCoreServices();
});
builder.ConfigureLogging((context, b) =>
{
// Add logging providers.
b.AddConsole();
// If this key exists in any config, use it to enable Application Insights.
string appInsightsKey = context.Configuration["APPINSIGHTS_INSTRUMENTATIONKEY"];
if (!string.IsNullOrEmpty(appInsightsKey))
{
// This uses the options callback to explicitly set the instrumentation key.
b.AddApplicationInsights(o => o.InstrumentationKey = appInsightsKey);
}
});
builder.ConfigureServices(services =>
{
services.AddSingleton<ITelemetryInitializer, CustomTelemetryInitializer>();
});
var host = builder.Build();
using (host)
{
await host.RunAsync();
}
}
Quando o TelemetryConfiguration
é construído, todos os tipos registrados de ITelemetryInitializer
são incluídos. Para saber mais, consulte API do Application Insights para eventos e métricas personalizados.
Na versão 3.x, você não precisa mais liberar o TelemetryClient
quando o host para. O sistema de injeção de dependência do .NET Core descarta automaticamente o registro ApplicationInsightsLoggerProvider
, que libera o TelemetryClient
.
Versão 2.x
Na versão 2.x, o TelemetryClient
criado internamente pelo provedor do Application Insights para o SDK WebJobs usa ServerTelemetryChannel
. Quando o ponto de extremidade do Application Insights não está disponível ou limitando as solicitações de entrada, esse canal salva as solicitações no sistema de arquivos do aplicativo Web e as reenvia posteriormente.
O TelemetryClient
é criado por uma classe que implementa ITelemetryClientFactory
. Por padrão, este é o DefaultTelemetryClientFactory
arquivo .
Se quiser modificar qualquer parte do pipeline do Application Insights, você pode fornecer o seu próprio ITelemetryClientFactory
, e o host usará sua classe para construir um TelemetryClient
arquivo . Por exemplo, esse código substitui DefaultTelemetryClientFactory
para modificar uma propriedade de ServerTelemetryChannel
:
private class CustomTelemetryClientFactory : DefaultTelemetryClientFactory
{
public CustomTelemetryClientFactory(string instrumentationKey, Func<string, LogLevel, bool> filter)
: base(instrumentationKey, new SamplingPercentageEstimatorSettings(), filter)
{
}
protected override ITelemetryChannel CreateTelemetryChannel()
{
ServerTelemetryChannel channel = new ServerTelemetryChannel();
// Change the default from 30 seconds to 15 seconds.
channel.MaxTelemetryBufferDelay = TimeSpan.FromSeconds(15);
return channel;
}
}
O SamplingPercentageEstimatorSettings
objeto configura a amostragem adaptável. Isso significa que, em determinados cenários de alto volume, o Applications Insights envia um subconjunto selecionado de dados de telemetria para o servidor.
Depois de criar a fábrica de telemetria, você a passa para o provedor de log do Application Insights:
var clientFactory = new CustomTelemetryClientFactory(instrumentationKey, filter.Filter);
config.LoggerFactory = new LoggerFactory()
.AddApplicationInsights(clientFactory);
Próximos passos
Este artigo forneceu trechos de código que mostram como lidar com cenários comuns para trabalhar com o SDK WebJobs. Para obter exemplos completos, consulte azure-webjobs-sdk-samples.