Tudo que precisa saber para integrar seu Azure Service Bus a sua Azure Function com Factory Pattern e Typescript

Cláudio Rapôso
5 min readJul 24, 2024

Bem-vindo ao sexto capítulo da nossa série emocionante sobre como integrar Azure Functions com serviços do Azure utilizando os poderosos princípios SOLID! Já exploramos como conectar o Azure Storage, Azure Key Vault e o Azure Web PubSub. Agora, prepare-se para mergulhar no fascinante mundo do Azure Service Bus! 📬

O Que é o Azure Service Bus?

O Azure Service Bus é uma plataforma de mensagens totalmente gerenciada que permite a comunicação entre diferentes partes de um sistema distribuído, como aplicações em nuvem, serviços e dispositivos. Ele oferece uma solução robusta para integrar sistemas e garantir a entrega confiável de mensagens.

Principais Componentes do Azure Service Bus

1. Filas (Queues)

As filas no Azure Service Bus permitem uma comunicação assíncrona entre diferentes partes de uma aplicação. As mensagens são armazenadas em uma fila até que o destinatário esteja pronto para processá-las, garantindo uma entrega ordenada e confiável.

2. Tópicos e Assinaturas (Topics and Subscriptions)

Os tópicos permitem um modelo de publicação e assinatura (pub/sub), onde as mensagens publicadas em um tópico são entregues a várias assinaturas. Cada assinatura pode aplicar filtros para receber apenas as mensagens relevantes, permitindo um roteamento flexível.

3. Regras e Filtros (Rules and Filters)

As assinaturas podem utilizar regras e filtros para definir critérios específicos de roteamento de mensagens. Isso permite uma personalização avançada sobre quais mensagens são entregues a quais assinaturas.

Vantagens do Azure Service Bus

1. Entrega Confiável

O Azure Service Bus garante a entrega de mensagens com durabilidade e tolerância a falhas. Ele armazena mensagens de forma persistente até que sejam processadas com sucesso pelo receptor.

2. Escalabilidade

Com capacidade de escalabilidade horizontal, o Azure Service Bus pode lidar com grandes volumes de mensagens e transações, suportando sistemas de qualquer tamanho.

3. Segurança

O Azure Service Bus integra-se com o Microsoft Entra ID e oferece autenticação robusta e controle de acesso, garantindo que apenas usuários e aplicações autorizadas possam enviar e receber mensagens.

4. Flexibilidade

Com suporte para diferentes padrões de comunicação, como filas, tópicos e assinaturas, o Azure Service Bus pode ser adaptado a uma ampla variedade de cenários e arquiteturas de sistema.

Casos de Uso

1. Integração de Sistemas Heterogêneos

O Azure Service Bus facilita a comunicação entre sistemas desenvolvidos em diferentes linguagens e plataformas, proporcionando uma integração fluida e eficiente.

2. Processamento Assíncrono

Permite o desacoplamento de componentes de uma aplicação, onde as tarefas podem ser enfileiradas e processadas de forma assíncrona, melhorando a eficiência e a resiliência do sistema.

3. Roteamento de Mensagens Complexas

Com tópicos e assinaturas, o Azure Service Bus pode gerenciar cenários complexos de roteamento de mensagens, garantindo que as informações corretas sejam entregues aos destinatários corretos.

O Azure Service Bus é uma ferramenta poderosa para a comunicação e integração de sistemas distribuídos, oferecendo entrega confiável, escalabilidade, segurança e flexibilidade. Seja para integrar sistemas heterogêneos, gerenciar processamento assíncrono ou lidar com roteamento complexo de mensagens, o Azure Service Bus é uma escolha robusta e eficiente para soluções de mensageria na nuvem.

Passo 1: Configuração do Ambiente

Antes de começar, certifique-se de ter as seguintes dependências instaladas:

npm install @azure/identity @azure/service-bus

OBS: Caso precise ver os Passos 1 ao 3 veja o artigo anterior sobre o tema:

Passo 4: Arquitetura com Provedores de Credenciais

Agora, vamos criar uma fábrica para instanciar o ServiceBusClient usando nosso CredentialProvider.

import { ServiceBusClient } from "@azure/service-bus";

/**
* Factory for creating instances of ServiceBusClient.
*/
class ServiceBusClientFactory {
private fullyQualifiedNamespace: string;
private credentialProvider: CredentialProvider;

/**
* Creates a new instance of ServiceBusClientFactory.
* @param {string} fullyQualifiedNamespace - The fully qualified namespace of the Azure Service Bus.
* @param {CredentialProvider} credentialProvider - The credential provider to be used.
*/
constructor(fullyQualifiedNamespace: string, credentialProvider: CredentialProvider) {
this.fullyQualifiedNamespace = fullyQualifiedNamespace;
this.credentialProvider = credentialProvider;
}

/**
* Creates an instance of ServiceBusClient.
* @returns {ServiceBusClient} A configured instance of ServiceBusClient.
*/
createServiceBusClient(): ServiceBusClient {
const credential = this.credentialProvider.getCredential();
return new ServiceBusClient(this.fullyQualifiedNamespace, credential);
}
}

Passo 5: Utilizando a Fábrica em uma Azure Function

Vamos integrar tudo isso em uma Azure Function, mostrando cada método de autenticação.

Exemplo 1: Azure Function com Managed Identity Atribuída ao Sistema

import { AzureFunction, Context, HttpRequest } from "@azure/functions";
import { ServiceBusClientFactory } from "./ServiceBusClientFactory";
import { SystemAssignedManagedIdentityCredentialProvider } from "./SystemAssignedManagedIdentityCredentialProvider";

/**
* Azure Function using System-Assigned Managed Identity.
* @param {Context} context - The function context.
* @param {HttpRequest} req - The HTTP request.
* @returns {Promise<void>} A promise that resolves when the function is complete.
*/
const httpTrigger: AzureFunction = async function (context: Context, req: HttpRequest): Promise<void> {
const fullyQualifiedNamespace = process.env.AZURE_SERVICEBUS_FULLYQUALIFIEDNAMESPACE;
const credentialProvider = new SystemAssignedManagedIdentityCredentialProvider();
const serviceClientFactory = new ServiceBusClientFactory(fullyQualifiedNamespace, credentialProvider);

const serviceClient = serviceClientFactory.createServiceBusClient();
// Use the serviceClient for operations with Service Bus
context.res = {
body: "Azure Function using System-Assigned Managed Identity for Access to Service Bus"
};
};

export default httpTrigger;

Exemplo 2: Azure Function com Managed Identity Atribuída ao Usuário

import { AzureFunction, Context, HttpRequest } from "@azure/functions";
import { ServiceBusClientFactory } from "./ServiceBusClientFactory";
import { UserAssignedManagedIdentityCredentialProvider } from "./UserAssignedManagedIdentityCredentialProvider";

/**
* Azure Function using User-Assigned Managed Identity.
* @param {Context} context - The function context.
* @param {HttpRequest} req - The HTTP request.
* @returns {Promise<void>} A promise that resolves when the function is complete.
*/
const httpTrigger: AzureFunction = async function (context: Context, req: HttpRequest): Promise<void> {
const fullyQualifiedNamespace = process.env.AZURE_SERVICEBUS_FULLYQUALIFIEDNAMESPACE;
const clientId = process.env.AZURE_SERVICEBUS_CLIENTID;
const credentialProvider = new UserAssignedManagedIdentityCredentialProvider(clientId);
const serviceClientFactory = new ServiceBusClientFactory(fullyQualifiedNamespace, credentialProvider);

const serviceClient = serviceClientFactory.createServiceBusClient();
// Use the serviceClient for operations with Service Bus
context.res = {
body: "Azure Function using User-Assigned Managed Identity for Access to Service Bus"
};
};

export default httpTrigger;

Exemplo 3: Azure Function com Service Principal

import { AzureFunction, Context, HttpRequest } from "@azure/functions";
import { ServiceBusClientFactory } from "./ServiceBusClientFactory";
import { ServicePrincipalCredentialProvider } from "./ServicePrincipalCredentialProvider";

/**
* Azure Function using Service Principal.
* @param {Context} context - The function context.
* @param {HttpRequest} req - The HTTP request.
* @returns {Promise<void>} A promise that resolves when the function is complete.
*/
const httpTrigger: AzureFunction = async function (context: Context, req: HttpRequest): Promise<void> {
const fullyQualifiedNamespace = process.env.AZURE_SERVICEBUS_FULLYQUALIFIEDNAMESPACE;
const tenantId = process.env.AZURE_SERVICEBUS_TENANTID;
const clientId = process.env.AZURE_SERVICEBUS_CLIENTID;
const clientSecret = process.env.AZURE_SERVICEBUS_CLIENTSECRET;
const credentialProvider = new ServicePrincipalCredentialProvider(tenantId, clientId, clientSecret);
const serviceClientFactory = new ServiceBusClientFactory(fullyQualifiedNamespace, credentialProvider);

const serviceClient = serviceClientFactory.createServiceBusClient();
// Use the serviceClient for operations with Service Bus
context.res = {
body: "Azure Function using Service Principal for Access to Service Bus"
};
};

export default httpTrigger;

Conclusão

🎉 Você aprendeu como configurar Azure Functions para acessar o Azure Service Bus utilizando várias técnicas de autenticação e aplicando os princípios SOLID e Clean Code! Nossa abordagem modular e escalável facilita a manutenção e o aprimoramento do código.

Referências

--

--

Cláudio Rapôso

Microsoft MVP | Software Architect | Teacher | Book Author | MCT | 12x Microsoft Certified Connect with me in https://www.linkedin.com/in/cfraposo