O Azure SignaIr é um serviço disponiblizado pela Azure para gerenciar as conexões e mensagens websockets das aplicações.
Além disso, permite criar soluções Serveless - Functions para comunicação websocket, assim os eventos podem ter um listener para serem disparados somente quando necessário.
Para criar soluções Serveless, no momento de criar o serviço na Azure precisa selecionar a opção de Serveless
.
Isso é possível pois, como dito anteriormente, o gerencimento das conexões fica como responsabilidade do serviço da Azure, estando acessível em qualquer host que tenha acesso ao serviço.
Uma aplicação que utiliza o SignaIr (websocket) tem o gerenciamento das conexões e das mensagens armazenadas dentro do host que está executando aquele processo. Com isso, quando o usuário inicia o processo de comunicação websocket, a sua conexão fica restrita ao host que recebeu essa solicitação e, consequentemente, todo o processamento que necessita enviar eventos para este usuário precisa ser executado por este host específico. Esse cenário se torna um obstáculo pois as aplicações atuais (principalmente utilizando Kubernetes) tem a capacidade e necessidade de realizar a escalabilidade visando aumentar ou diminuir a capacidade de processamento de acordo com a demanda atual de trabalho. Tendo isso em mente, pode ocorrer o seguinte cenário:
- Usuário inicia a conexão websocket e o Pod 01 recebe esse requisição.
- A aplicação aumenta a sua capacidade de processamento para 02 pods.
- Ocorre um determinado fluxo de trabalho que dispara um processamento no Pod 02 para notificar o usuário através websocket.
- O usuário não receberá essa notificação pois a conexão dele está sendo gerenciada pelo Pod 01.
Isso se torna um problema pois mesmo havendo o processamento correto do fluxo, o usuário não receberá o retorno do evento esperado.
Para contornar este problema, existe algumas soluções que tem o objetivo de gerenciar e armazenar as conexões e mensagens, sendo possível compartilhar estas informações entre os hosts disponíveis para o processamento. Dentre as soluções, há disponível:
- Azure SignaIr (utilizado neste exemplo)
- Redis para utilização de uma camada de cache
Foi criada uma aplicação frontend que iniciará a conexão websocket. Para isso, é preciso indicar qual é o host que deseja utilizar para esta comunicação e, posteriormente, enviar mensagens para testes.
Há uma aplicação backend na qual receberá as solicitações websockets (utilizando o pacote SignaIr do .NET) e processará as mensagens. Na aplicação backend, há um parâmetro de configuração para definir se irá utilizar o Azure SignaIr ou se irá manter o gerencimento no próprio host.
Para indicar que o Azure SignaIr ficará responsável por gerenciar as conexões, basta adicionar a configuração durante as adições dos serviços da aplicação:
builder.Services.AddSignalR().AddAzureSignalR(opt =>
{
opt.ApplicationName = "App01";
opt.ConnectionString = builder.Configuration.GetConnectionString("AzureSignaIR");
});
Nesse código, é informado a connection string para o serviço da Azure e também o nome da aplicação. O nome da aplicação seria necessário caso haja mais de uma utilizando este mesmo serviço. Com isso, o Azure irá adicionar um prefixo no gerenciamento dos hubs para identificação de qual aplicação o mesmo pertence.
Foi utilizando o Kubernetes para a criação de 2 pods e posteriormente utilizar, através do port forward
, no frontend para que ele se conecte separadamente em cada um deles a fim de simular o processamento em hosts distintos.
- Processamento no mesmo POD: o usuário recebe todas os eventos, pois o processamento ocorreu no POD em que a sua conexão foi iniciada.
- Sem a utilização do Azure SignaIr: note que quando o usuário é conectado no POD 01 e envia a mensagem através dele, o POD 02 não processa a mensagem e o usuário não recebe esse novo evento. E o inverso também.
- Com a utilização do Azure SignaIr: independemente de qual POD processou a mensagem, o usuário recebe o novo evento, não perdendo nenhuma atualização.