Fevereiro de 2018

Volume 33 – Número 2

Arquitetura do Azure controlada por eventos na nuvem com a Grade de Eventos do Azure

Por David Barkol

Estamos vivendo um momento muito propício para ser um arquiteto da nuvem. O ritmo acelerado das inovações trouxe à tona uma série de novos desafios e tecnologias que estão reformulando o modo como as soluções são projetadas. Quem se beneficia desse crescimento são os desenvolvedores e arquitetos, que podem escolher entre uma vasta gama de serviços e opções.

À medida que os desenvolvedores decompõem suas arquiteturas para aproveitar os novos serviços, como o Azure Functions, Aplicativos Lógicos e outros, surgem obstáculos familiares. Em muitos casos, mais uma vez, temos que juntar os diversos pedaços para viabilizar o funcionamento em conjunto desses serviços. O recente lançamento da Grade de Eventos do Azure pretende vencer esse desafio, fornecendo um excelente serviço de roteamento de evento na nuvem, que é gerenciável, escalável e totalmente flexível.

Neste artigo, vou explorar a flexibilidade da Grade de Eventos do Azure e mostrar como ela pode ser usada para vencer desafios já conhecidos em aplicativos empresariais. Também recomendo que você confira o anúncio de disponibilidade geral da Grade de Eventos em aka.ms/egblog.

A reversão das dependências

A noção do uso de eventos em uma solução ou aplicativo não é novidade. Na verdade, a programação controlada por eventos usou o conceito com sucesso por bastante tempo. As filas Pub/Sub e as GUIs são apenas alguns dos exemplos que aproveitam esta ideia de reagir a eventos que acontecem em uma organização, aplicativo ou sistema.

Um dos principais locatários de uma arquitetura controlada por eventos é reverter as dependências que os serviços existentes possam ter uns dos outros. A Figura 1 mostra o exemplo de um conjunto de processos que contam uns com os outros para a comunicação e o suporte a um departamento de Recursos humanos (RH).

Serviços que contêm a lógica de outros serviços
Figura 1 Serviços que contêm a lógica de outros serviços

Para que esse projeto funcione, cada serviço deve conter uma lógica básica dos demais para que a comunicação aconteça. Essas dependências criam desafios, não só em termos de escala, mas também devido ao fato de que essa lógica está dispersa em toda a arquitetura. Com o tempo, à medida que esses tipos de solução se expandem, eles se tornam difíceis de manter e incrivelmente frágeis devido ao surgimento de mais mudanças e dependências.

Como uma alternativa, o conceito por trás de um projeto controlado por eventos remove essas dependências, promovendo a ideia de que um evento é algo como o personagem principal da arquitetura. Essa importante consideração permite que muitos outros sistemas aproveitem um serviço centralizado sem a carga das dependências e a lógica dispersa em todo o aplicativo. A Figura 2 destaca a reversão das dependências da solução do departamento de RH introduzindo este conceito principal.

Um serviço centralizado que reverte as dependências entre outros serviços
Figura 2 Um serviço centralizado que reverte as dependências entre outros serviços

A partir de agora, este artigo abordará exclusivamente este serviço principal. Vou explorar a Grade de Eventos do Azure e como ela pode ser usada para oferece suporte à próxima geração de soluções.

Introdução à Grade de Eventos do Azure

A Grade de Eventos do Azure é um serviço novo e totalmente gerenciado que dá suporte ao roteamento de eventos utilizando um modelo publicador-assinante. Basicamente, a Grade de Eventos é um serviço de roteamento de eventos que gerencia o roteamento e a entrega de eventos de diversas fontes e assinantes. A Figura 3, tirada de uma documentação de visão geral da Grade de Eventos (bit.ly/2qhaj9q), ilustra vários publicadores e manipuladores que podem ser usados na Grade de Eventos hoje.

Visão geral da Grade de Eventos do Azure
Figura 3 Visão geral da Grade de Eventos do Azure

Um evento é criado por um publicador, como uma conta de Armazenamento de Blobs, Hubs de Eventos ou até mesmo uma assinatura do Azure. À medida que os eventos ocorrem, eles são publicados em um ponto de extremidade chamado tópico, gerenciado pelo serviço Grade de Eventos para absorver todas as mensagens de entrada. A lista de serviços no Azure integrada à Grade de Eventos está crescendo, e a previsão é que ela só aumente.

Os publicadores de eventos não estão limitados a serviços do Azure. Na verdade, um caso de uso muito comum inclui eventos provenientes de aplicativos ou sistemas personalizados que podem ser executados em qualquer lugar. Eles incluem aplicativos hospedados localmente, em um datacenter ou mesmo em outras nuvens. Esses tipos de publicadores são chamados de Tópicos Personalizados. Se eles puderem publicar uma solicitação HTTP no serviço da Grade de Eventos, serão candidatos a enviar eventos.

Os manipuladores de eventos também incluem diversos serviços no Azure. Eles apresentam algumas das tecnologias sem servidor emergentes no Azure, como Funções e Aplicativos Lógicos. Além da Automação do Azure, outro tipo de manipulador de eventos pode ser qualquer retorno de chamada HTTP, também conhecido como WebHook. Os manipuladores são registrados com a Grade de Eventos por meio da criação de uma assinatura de eventos. Se o ponto de extremidade do manipulador de eventos for acessível publicamente e criptografado pelo protocolo TLS, as mensagens podem ser enviadas por push para ele da Grade de Eventos.

Diferentemente de vários serviços do Azure, não existe um namespace da Grade de Eventos que precise ser provisionado ou gerenciado. Os tópicos dos recursos nativos do Azure são internos e completamente transparentes para os usuários. Já os tópicos personalizados são provisionados ad-hoc e existem em um grupo de recursos. As assinaturas de eventos são simplesmente associadas a um tópico. Esse modelo simplifica o gerenciamento dos tópicos e das assinaturas e torna a Grade de Eventos altamente multilocatária, permitindo uma expansão horizontal em massa.

A Grade de Eventos do Azure independe de qualquer linguagem ou plataforma. Embora ela se integre nativamente aos serviços do Azure, pode ser facilmente aproveitada por qualquer coisa que dê suporte ao protocolo HTTP, o que a torna um serviço inovador e muito inteligente.

Eventos ou comandos

Antes de começar a analisar códigos e desenvolver uma solução que destaque alguns desses recursos, vamos diferenciar um evento de um comando. Às vezes, a diferença pode ser sutil, mas é importante entendê-la ao projetar sistemas que contam com mensagens.

Quando uma mensagem envia uma ação ou resposta específica, o mais provável é que ela seja um comando. Por exemplo, se um funcionário é promovido em uma organização e uma mensagem é enviada para instruir o novo gerente a preencher um formulário, ela transmite um objetivo ou uma intenção específica. Como o remetente da mensagem tem uma expectativa e, em alguns casos, pode até esperar uma resposta, podemos categorizar essa mensagem como um comando.

Se uma mensagem é publicada sem que se saiba como será recebida e não houver nenhuma expectativa em relação a ela, é considerada um evento. Digamos que, dentro de uma organização, o mesmo funcionário tenha solicitado a mudança do seu endereço de correspondência. Como esta ação pode ser interessante para vários sistemas na organização, mas não exige que o publicador esteja especificamente ciente deles, trata-se de uma mensagem que não define nenhum objetivo. Nesse caso, o publicador está simplesmente notificando quaisquer partes interessadas sobre a ocorrência de um evento. É um evento, e claramente a ocorrência de algo que é uma opção viável para um serviço como a Grade de Eventos.

Poderia passar muito mais tempo discutindo essas diferenças e falar sobre como selecionar o serviço de mensagem apropriado no Azure. No entanto, isso está fora do escopo deste artigo. Recomendo a leitura desta postagem repleta de informações úteis de Clemens Vasters sobre o tópico: bit.ly/2CH3sbQ.

Um cenário de recursos humanos

A melhor forma de entender a fundo a Grade de Eventos é escrever o código que aproveita seus recursos. Neste artigo, vou analisar alguns eventos provenientes de um aplicativo de RH fictício. Publicarei eventos em um tópico personalizado e, em seguida, assinarei os eventos usando diversos manipuladores.

Para simplificar, vou implementar dois tipos de eventos do sistema de RH: quando um funcionário é admitido em uma organização e quando é afastado. Esses eventos são muito parecidos em sua essência e fornecerão opções que demonstram como filtrar e manipular eventos de diferentes formas. Uma representação visual da solução é mostrada na Figura 4.

Uma solução de exemplo
Figura 4 Uma solução de exemplo

Em um nível alto, a solução consiste em vários componentes principais que vou criar neste artigo. Vamos explorá-los aqui.

Os Eventos de Funcionários serão um Tópico da Grade de Eventos ao qual o aplicativo de RH pode enviar mensagens. Serão incluídos eventos para os funcionários novos e para os afastados da organização. Cada mensagem conterá informações sobre o funcionário, seu departamento e o tipo de evento.

Boas Vindas ao Novo Funcionário será um Aplicativo Lógico que assina mensagens para os novos funcionários da organização. Ele envia um email de boas vindas para o novo funcionário.

Pedido de Equipamento para Novo Funcionário é uma Função do Azure que assinará eventos para os novos funcionários no departamento de engenharia. Ele criará uma mensagem em uma fila para processamento adicional.

Registros de Funcionários é um site da Web personalizado incorporado ao ASP.NET Core que vai expor a API da Web para receber mensagens quando os funcionários saírem da organização.

Criação de um tópico personalizado

Para começar, preciso criar alguns recursos básicos no Azure. Você pode iniciar o Azure Cloud Shell pelo portal ou usar a interface de linha de comando localmente. Você poderá encontrar informações detalhadas sobre como usar o Cloud Shell em bit.ly/2CsFtQB. Se você nunca usou o Cloud Shell, eu recomendo.

A primeira coisa que vou fazer é criar um grupo de recursos para gerenciar e encapsular os recursos do Azure:

az group create --name <resource-group-name> --location <location>

Após a criação do grupo, um Tópico da Grade de Eventos será provisionado. Isso fornecerá um ponto de extremidade para publicar eventos personalizados de um aplicativo de RH. O nome do tópico deve ser exclusivo na região, pois será um serviço publicamente acessível no Azure. O local também deve ser em uma região em que o serviço Grade de Eventos esteja disponível. Em geral, escolho o local westus2 ou consulto a lista de serviços fornecidos em cada região do Azure (consulte bit.ly/2DU15ln).

az eventgrid topic create --name <topic-name> \
  --location <location> \
  --resource-group <resource group name>

Após a execução do comando para criar o tópico, são retornados os detalhes sobre o recurso. A saída será semelhante a este código aqui:

{
  "endpoint": "https://<topic name>.westus2-1.eventgrid.azure.net/api/events",
  "id": "/subscriptions/xxxx-xxx-xx-xxx-xx/resourceGroups/eventgridsolution-rg/providers/Microsoft.EventGrid/topics/<topic name>",
  "location": "westus2",
  "name": "<topic name>",
  "provisioningState": "Succeeded",
  "resourceGroup": "eventgridsolution-rg",
  "tags": null,
  "type": "Microsoft.EventGrid/topics"
}

Anote o valor do ponto de extremidade, pois ele será usado posteriormente na publicação dos eventos. Você também precisará de uma das duas chaves de acesso geradas para autorização. Para recuperar as chaves, você pode listar as associadas ao tópico. Você pode e deve mudar e gerar novamente essas chaves como medida de segurança, exatamente como faria com outros serviços no Azure.

az eventgrid topic key list --name <topic-name> --resource-group <resource-group-name>

Se preferir trabalhar no Portal do Azure, poderá criar e exibir todas essas opções e configurações lá também.

Publicação de um evento

Antes de enviar o primeiro evento, você precisa entender o esquema de eventos esperado pelo tópico. Cada evento, independentemente de o publicador ser um recurso ou aplicativo personalizado do Azure, vai seguir a estrutura descrita no seguinte código (uma referência útil para o esquema de eventos, bem como alguns exemplos, podem ser encontrados em bit.ly/2CG8oxI):

[
  {
    "topic": string,
    "subject": string,   
    "id": string,
    "eventType": string,
    "eventTime": string,
    "data":{
      object-unique-to-each-publisher
    }
  }
]

A primeira coisa a ressaltar é que os eventos são enviados em uma matriz. Isso é feito intencionalmente dessa forma para possibilitar o envio de vários eventos em uma solicitação. Os eventos podem ser enviados em lotes, o que reduz o movimento da rede e dá suporte a cenários em que a conectividade nem sempre está disponível.

O primeiro evento que desejo publicar é para quando um novo funcionário é admitido em uma organização. O payload desse evento pode ser semelhante ao conteúdo da Figura 5.

Figura 5 Evento para funcionário admitido

[{
  "id": "30934",
  "eventType": "employeeAdded",
  "subject": "department/engineering",
  "eventTime": "2017-12-14T10:10:20+00:00",
  "data":{
    "employeeId": "14",
    "employeeName": "Nigel Tufnel",
    "employeeEmail": "nigel@contoso.com",
    "manager": "itmanager@contoso.com",
    "managerId": "4"
  }
}]

Posteriormente neste artigo, vou usar a mesma estrutura, com algumas diferenças nos valores, como quando um funcionário sai da organização. As principais propriedades neste evento são as seguintes:

eventType é um valor usado para identificar com exclusividade o tipo de evento publicado. Essa propriedade pode ser usada por manipuladores que querem assinar somente tipos de evento específicos, em vez de todos os tipos.

subject é um valor, como eventType, disponível para fornecer contexto adicional sobre o evento, com a opção de também fornecer um filtro adicional aos assinantes. Vou aproveitar eventType e subject em breve quando criar as assinaturas. Subject e eventType dão contexto ao evento.

data é um bucket definido pelo manipulador, um objeto que pode conter uma ou mais propriedades. Os publicadores atribuem informações relevantes sobre o próprio evento nessa propriedade. Por exemplo, o evento de Armazenamento do Blob do Azure inclui detalhes sobre o blob criado ou excluído, como uma URL ou tipo de evento.

Para publicar o evento, uso o Postman (ou uma ferramenta semelhante) para simular a mensagem proveniente de um aplicativo de RH para o endereço de ponto de extremidade mencionado anteriormente. Para autorização, adiciono um item ao cabeçalho chamado aeg-sas-key, que é o valor de uma das chaves de acesso geradas quando o tópico é criado. O corpo da solicitação conterá o payload mencionado na Figura 5.

Como não existe nenhum assinante, ainda não há nada a ser visto. A próxima etapa será ver isso em ação criando alguns manipuladores de evento aos quais a Grade de Eventos enviará eventos por push.

Manipulação de eventos com uma Azure Function

Agora começa a parte divertida da assinatura de eventos. Nosso primeiro manipulador será uma Azure Function. Para aprender o básico sobre como criar uma Azure Function, consulte bit.ly/2A6pFgu. Para este tipo de situação, quero assinar especificamente os eventos relacionados a funcionários admitidos recentemente. Além disso, e não menos importante, esse manipulador só deve ser chamado para os funcionários que pertencem ao departamento de engenharia.

A maioria dos exemplos descreve a criação de uma Azure Funtion usando o Portal do Azure, que é superfácil e rápido. Gostaria de mostrar como fazer isso localmente usando o Visual Studio. Isso será um preparatório antes de abordarmos mais códigos prontos para produção. Também usarei um utilitário chamado ngrok (consulte ngrok.com) para dar suporte à depuração local com a Grade de Eventos.

Se você quiser acompanhar, precisará do ngrok, além de uma versão atualizada do Visual Studio (usei a versão 15.5.2 para este artigo). Vamos começar criando um novo projeto e selecionando a Azure Functions nos modelos da nuvem. Na caixa de diálogo Novo Projeto, selecione a opção de gatilho HTTP e mantenha os valores padrão.

Atualize o código da função para refletir o que está representado na Figura 6. Se desejar, renomeie o arquivo para refletir o nome da função.

Figura 6 Implementação do Manipulador de Eventos para Novo Funcionário>

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Azure.WebJobs.Host;
using Newtonsoft.Json;
namespace NewEmployeeApp
{
  public static class NewEmployeeHandler
  {
    public class GridEvent<T> where T : class
    {
      public string Id { get; set; }
      public string EventType { get; set; }
      public string Subject { get; set; }
      public DateTime EventTime { get; set; }
      public T Data { get; set; }
      public string Topic { get; set; }
    }
      [FunctionName("newemployeehandler")]
      public static async Task<HttpResponseMessage> Run(
        [HttpTrigger(AuthorizationLevel.Function, "post", Route = null)]
        HttpRequestMessage req,
        TraceWriter log)
         {
          log.Info("New Employee Handler Triggered");
          // Retrieve the contents of the request and
          // deserialize it into a grid event object.
          var jsonContent = await req.Content.ReadAsStringAsync();
          var gridEvent =
            JsonConvert.DeserializeObject<List<GridEvent<Dictionary<string,
              string>>>>(jsonContent)
              ?.SingleOrDefault();
            // Check to see if the event is available and
            // return an error response if its missing.
            if (gridEvent == null)
            {
              return req.CreateErrorResponse(HttpStatusCode.BadRequest,
                $@"Missing event details");
            }
          // Check the header to identify the type of request
          // from Event Grid. A subscription validation request
          // must echo back the validation code.
          var gridEventType = req.Headers.GetValues("Aeg-Event-Type"). 
            FirstOrDefault();
          if (gridEventType == "SubscriptionValidation")
          {
            var code = gridEvent.Data["validationCode"];
            return req.CreateResponse(HttpStatusCode.OK,
              new { validationResponse = code });
          }
          else if (gridEventType == "Notification")
          {
            // Pseudo code: place message into a queue
            // for further processing.
            return req.CreateResponse(HttpStatusCode.OK);
          }
          else
          {
            return req.CreateErrorResponse(HttpStatusCode.BadRequest,
              $@"Unknown request type");
          }
        }
  }
}

Temos alguns códigos importantes para analisar aqui. Bem no início há uma classe chamada GridEvent que pretende refletir o payload e o esquema de eventos da Grade de Eventos. O ideal seria posicionar essa classe em uma biblioteca comum para que possa ser reutilizada. Neste exemplo, ela é usada para desserializar o conteúdo da solicitação em um objeto com tipo bem definido.

A Grade de Eventos enviará para seus assinantes dois tipos de solicitação, SubscriptionValidation e Notification, que você pode identificar inspecionando um valor no cabeçalho. A solicitação de validação é importante para garantir que todos os assinantes sejam explicitamente adicionados. Tudo o que preciso fazer aqui é repetir o código de validação para confirmar que posso receber mensagens:

var code = gridEvent.Data["validationCode"];
return req.CreateResponse(HttpStatusCode.OK,
  new { validationResponse = code });

As solicitações de validação também podem ser identificadas pelo seu tipo de evento: Microsoft.EventGrid.SubscriptionValidationEvent. Se o tipo de evento for Notification, continuo com a implementação da lógica comercial. Essa abordagem de programação defensiva é altamente recomendada quando expõem-se pontos de extremidade a outros serviços.

As funções hospedadas no Azure e referenciadas com o domínio azurewebsites.net não precisam da lógica de validação de assinaturas. Em vez disso, elas são autorizadas pela Grade de Eventos com vários outros serviços, como os Aplicativos Lógicos e os retornos de chamada dos livros de execução da Automação do Azure. Como pretendo testar localmente, preciso repetir o código de validação da Grade de Eventos para confirmar a função como um ponto de extremidade válido.

Eventualmente, o SDK de tempo de execução da Grade de Eventos fará grande parte dessa configuração, desde a desserialização de eventos e criação de objetos com tipo bem definido da Grade de Eventos até a validação automática dos pontos de extremidade. Até o momento em que escrevi este artigo, os SDKs de tempo de execução atualizados ainda não estavam disponíveis.

Teste da função local

Vamos começar a função no Visual Studio para que a execução seja feita localmente na porta 7071. Quando estiver em execução, abra um prompt de comando e use ngrok para criar um túnel seguro:

ngrok http -host-header=localhost 7071

Vou recuperar um endereço HTTPS de ngrok e usá-lo como o ponto de extremidade do assinante. O endereço deve ter uma aparência semelhante a esta: https://d69f6bed.ngrok.io, mas com um subdomínio diferente cada vez que o comando ngrok for executado. Acrescente a rota de nossa função à URL para que tenha uma aparência semelhante a esta: https://<generated-value>.ngrok.io/api/newemployeehandler. Esse será o endereço de ponto de extremidade para a assinatura do evento.

Com a função em execução e o túnel seguro, agora posso criar a assinatura de evento na CLI ou no Azure Cloud Shell:

az eventgrid event-subscription create --name <event-subscription-name> \
  --resource-group <resource group name> \
  --topic-name <topic name> \
  --subject-ends-with engineering \
  --included-event-type employeeAdded \
  --endpoint <function endpoint>

Também posso adicionar uma assinatura de evento no portal preenchendo a caixa de diálogo, conforme mostrado na Figura 7.

Criação de uma assinatura de evento no portal
Figura 7 Criação de uma assinatura de evento no portal

Gostaria de destacar diversos argumentos importantes na criação da assinatura do evento.

subject-begins-with (Filtro de prefixos) é um argumento opcional que filtra com base no prefixo do campo de assunto nos eventos. É preciso haver uma correspondência exata da cadeia de caracteres. Os caracteres curinga e as expressões regulares não são suportados.

subject-ends-with (Filtro de sufixos) é um argumento opcional com base em um sufixo para filtrar eventos. Os caracteres curinga e as expressões regulares não são suportados.

included-event-type (Tipos de Eventos) é uma lista opcional de tipos de evento a ser assinada. Os tipos são separados por um espaço.

Agora posso voltar ao exemplo de publicação de evento anterior deste artigo para garantir que os eventos estão fluindo do Postman para a Grade de Eventos e, por fim, para a função local. Fique à vontade para alterar os valores na solicitação para confirmar que os filtros estão funcionando conforme esperado.

Manipulação de eventos: Aplicativo Lógico e WebHook

A próxima assinatura de evento é um Aplicativo Lógico. Como no exemplo da Azure Function, apenas o tipo de evento de admissão de funcionário interessa. Os filtros de prefixo e sufixo não serão aproveitados porque quero enviar uma mensagem aos funcionários de todos os departamentos. A versão completa do Aplicativo Lógico é mostrada na Figura 8.

Um Aplicativo Lógico que dá boas vindas aos novos funcionários
Figura 8 Um Aplicativo Lógico que dá boas vindas aos novos funcionários

O Aplicativo Lógico começa com um gatilho da Grade de Eventos. A seleção de Microsoft.EventGrid.topics como o tipo de recurso permitirá que eu escolha entre os tópicos personalizados na assinatura.

A ação Analisar JSON será útil para acessar as propriedades no objeto Dados. Usarei esse payload de amostra para gerar o esquema:

{
  "id": "40000",
  "eventType": "employeeAdded",
  "subject": "department/finance",
  "eventTime": "2017-12-20T10:10:20+00:00",
  "data":{
    "employeeId": "24",
    "employeeName": "David St. Hubbins",
    "employeeEmail": "david@contoso.com",
    "manager": "finance@contoso.com",
    "managerId": "10"
  }
}

Em seguida, o filtro do tipo de evento deve ser feito com uma ação de condição. Essa é uma pequena diferença do modo como a assinatura de eventos foi criada com a Azure Function, pois não é possível selecionar essa opção no gatilho da Grade de Eventos.

A última etapa envia um email ao funcionário. Ela usa as propriedades que foram recuperadas na segunda etapa para preencher os campos do endereço do destinatário e do assunto do email. Para testar o Aplicativo Lógico, clique em Executar no designer e envie uma mensagem para o ponto de extremidade, como foi feito anteriormente.

A última assinatura de eventos é uma chamada de retorno básica ou um WebHook. Vou atualizar o aplicativo ASP.NET Core existente com uma API da Web para eventos de entrada. O código para o WebHook será muito semelhante ao da Azure Function que escrevi anteriormente. Algumas diferenças sutis incluem a forma como os valores de cabeçalho são recuperados para inspecionar o tipo de solicitação, conforme visto na Figura 9.

Figura 9 Um controlador da API da Web que recebe eventos

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
namespace EmployeeRecords.Controllers
{
  public class GridEvent<T> where T : class
  {
    public string Id { get; set; }
    public string Subject { get; set; }
    public string EventType { get; set; }
    public T Data { get; set; }
    public DateTime EventTime { get; set; }
  }
  [Produces("application/json")]
  [Route("api/EmployeeUpdates")]
  public class EmployeeUpdatesController : Controller
  {
    private bool EventTypeSubcriptionValidation
      => HttpContext.Request.Headers["aeg-event-type"].FirstOrDefault() ==
        "SubscriptionValidation";
    private bool EventTypeNotification
      => HttpContext.Request.Headers["aeg-event-type"].FirstOrDefault() ==
        "Notification";
    [HttpPost]
    public async Task<HttpResponseMessage> Post()
    {
      using (var reader = new StreamReader(Request.Body, Encoding.UTF8))
      {
        var jsonContent = await reader.ReadToEndAsync();
        var gridEvent =
          JsonConvert.DeserializeObject<List<GridEvent<Dictionary<string,
          string>>>>(jsonContent)
            .SingleOrDefault();
        if (gridEvent == null)
        {
          return new HttpResponseMessage { StatusCode = HttpStatusCode.BadRequest};
        }
        // Check the event type from Event Grid.
        if (EventTypeSubcriptionValidation)
        {
          // Retrieve the validation code and echo back.
          var validationCode = gridEvent.Data["validationCode"];
          var validationResponse =
            JsonConvert.SerializeObject(new { validationResponse =
            validationCode });
          return new HttpResponseMessage
          {
            StatusCode = HttpStatusCode.OK,
            Content = new StringContent(validationResponse)
          };
        }
        else if (EventTypeNotification)
        {
          // Pseudo code: Update records
          return new HttpResponseMessage { StatusCode = HttpStatusCode.OK };
        }
        else
        {
          return new HttpResponseMessage { StatusCode = HttpStatusCode.BadRequest };
        }
      }
    }
  }
}

Quando se cria a assinatura de eventos, o tipo de evento registrado deve ser employeeRemoved. Essa mudança atende ao requisito, ou seja, o manipulador só quer receber mensagens de um funcionário que foi removido da organização. Observe também que os filtros de prefixo ou sufixo não são usados porque o assinante quer ser notificado sobre cada ocorrência, independentemente do departamento:

az eventgrid event-subscription create --name <event-subscription-name> \
  --resource-group <resource group name> \
  --topic-name <topic name> \
  --included-event-type employeeRemoved \
  --endpoint <function endpoint>

Por último, lembre-se de que o ponto de extremidade para a assinatura de evento tem que ser seguro. Se você referenciar um Serviço de Aplicativo no Azure, terá que especificar o HTTPS no endereço. Se não fizer isso, a assinatura apresentará falhas.

Conclusão

A Grade de Eventos do Azure é um serviço capaz de provocar mudanças radicais. Neste artigo, abordei um cenário comum de integração de aplicativos. A Grade de Eventos foi usada como uma tecnologia viabilizadora para conectar o aplicativo a outros serviços, como a Azure Function, um Aplicativo Lógico e até mesmo um WebHook personalizado que pode residir em qualquer lugar. Quando complementada com aplicativos sem servidor, a Grade de Eventos atinge seu ápice, pois juntos podem aproveitar os excelentes recursos de escalonamento e integração aos quais o Azure dá suporte. O código deste artigo pode ser encontrado em github.com/dbarkol/AzureEventGrid.


David Barkol é um especialista em Azure da Microsoft, membro da Global Black Belt Team. Entre em contato com ele pelo Twitter: @dbarkol ou pelo email dabarkol@microsoft.com.

Agradecemos aos seguintes especialistas técnicos da Microsoft pela revisão deste artigo: Bahram Banisadr e Dan Rosanovsanova
Dan Rosanova é o principal gerente de programa, responsável pela suíte de produtos Azure Messaging, que inclui Barramento de Serviço, Hubs de Eventos, Retransmissão do Azure e a Grade de Eventos.
 
Bahram Banisadr é o gerente de projetos responsável pela Grade de Eventos do Azure e trabalha na criação de elementos para conectividade com os serviços do Azure.


Discuta esse artigo no fórum do MSDN Magazine