Criando um aplicativo em tempo real com o SignalR – Parte 2
Este post é uma continuação do meu post anterior, onde discutimos as necessidades, noções básicas, configurações e mecanismo de transporte do SignalR. Nesta postagem, daremos um passo adiante, criando um aplicativo de amostra e analisando-o ainda mais.
Este post é uma continuação do meu post anterior, onde discutimos as necessidades, noções básicas, configurações e mecanismo de transporte do SignalR. Nesta postagem, daremos um passo adiante, criando um aplicativo de amostra e analisando-o ainda mais.
Em linhas gerais, este post pode ser dividido em duas partes principais: Na primeira parte, criaremos um exemplo e na outra, veremos como o SignalR funciona em vários ambientes e examinaremos a solicitação de comunicação entre cliente e servidor.
Trabalhando no exemplo
O monitoramento do servidor é uma das tarefas importantes que realizamos várias vezes em vários cenários. Uma maneira simples de fazer isso é por meio de login remoto no servidor para monitorar – ou você também pode usar um cliente que conecta o servidor, extrai os contadores de desempenho necessários e exibe essas informações de acordo.
Neste exemplo, vamos criar um aplicativo de monitoramento de servidor que mostrará a utilização dos recursos do servidor em tempo real. Nosso exemplo será básico, pois nosso objetivo é explicar o SignalR, e leremos alguns contadores básicos do servidor e exibiremos essas informações na interface do usuário. A interface do usuário será atualizada a cada segundo, o que é implementado por meio de um temporizador no servidor que envia os dados para o cliente a cada segundo.
Já vimos a configuração necessária em nosso post anterior, então criei um aplicativo ASP.NET vazio e concluí as seguintes etapas:
- Pacote Nuget do SignalR instalado
- Adicionada classe Startup e adicionado método Configuration
- Adicionado um arquivo HTML como Index.HTML e adicionado jQuery, jQuery SignalR e proxy Hub.
A parte principal de qualquer aplicativo SignalR é o HUB. Há duas coisas principais que faremos aqui. Primeiro, lendo o contador de recursos do servidor e, segundo, enviando essas informações para os clientes conectados após um determinado intervalo (neste exemplo, 1 segundo). Então, vamos ver a implementação do hub:
[HubMethodName("sendSeverDetails")] public void SendSeverDetails() { string processorTime; string memoryUsage; string diskReadperSec; string diskWriteperSec; string diskTransferperSec; // Getting the server counters GetServerUsageDetails(out processorTime, out memoryUsage, out diskReadperSec, out diskWriteperSec, out diskTransferperSec); // Broadcasting the counters to the connected clients Clients.All.SendSeverDetails(processorTime, memoryUsage, diskReadperSec, diskWriteperSec, diskTransferperSec, DateTime.Now.ToString()); }
Este é o método do hub principal. Aqui estamos obtendo os contadores do servidor e, em seguida, chamando a função de retorno de chamada do cliente e passando todos os parâmetros. Neste exemplo, estamos passando parâmetros diferentes para cada valor de contador, mas também podemos criar uma instância e passar uma string JSON. Como precisamos continuar atualizando o cliente com o contador mais recente, precisamos chamar esse método em determinados intervalos (aqui, digamos 1 segundo). Isso pode ser feito por meio de um cronômetro como tal:
static Timer myTimer; private readonly TimeSpan _updateInterval = TimeSpan.FromMilliseconds(1000); public ServerDetailsHub() { myTimer = new System.Threading.Timer(UpdateUI, null, _updateInterval, _updateInterval); // Rest of the code removed for brevity. Download the solution for complete code } // This is called via Timer after certain interval which inturn calls the core hub method private void UpdateUI(object state) { SendSeverDetails(); }
Agora vamos ver nosso lado do cliente, onde definimos o método de retorno de chamada.
$(function () { var num = 1; // Declare a proxy to reference the hub. var hubProxy = $.connection.serverDetailsHub; // Create a function that the hub can call to broadcast messages. hubProxy.client.sendSeverDetails = function (processorTime, memoryUsage, diskReadperSec, diskWriteperSec, diskTransferperSec, when) { $('#tblServerUsage tr').last().after("<tr><td>" + num++ + "</td><td>" + processorTime + "</td><td>" + memoryUsage + "</td><td>" + diskReadperSec + "</td><td>" + diskWriteperSec + "</td><td>" + diskTransferperSec + "</td><td>" + when + "</td></tr>"); }; // Start the connection. $.connection.hub.start(); });
Nota – você pode baixar o código completo para este exemploaqui.
No código acima, há três coisas que estamos fazendo. Primeiro, criando o proxy do hub; segundo, definimos o método de retorno de chamada que é chamado do servidor e recebe o mesmo número de parâmetros; e terceiro – que é outro passo muito importante – iniciar o hub. Essas etapas fazem a negociação com o servidor e criam uma conexão persistente com o servidor. Nesta demonstração, estou apenas adicionando uma nova linha sempre que os novos dados são recebidos do servidor.
Analisando o aplicativo
O SignalR cria um JavaScript de proxy em tempo de execução, que é usado para criar a instância de proxy e estabelecer a conexão do servidor. Pode ser visto se navegarmos no URL do proxy da seguinte maneira:

Em minha postagem anterior, discutimos que o SignalR é capaz de usar vários mecanismos de transporte e, com base no cenário, escolhe uma das melhores opções. Então, vamos ver como a negociação acontece antes de selecionar uma.

O tráfego acima é capturado durante a execução do exemplo no IE 11. Depois de baixar os scripts necessários, ele baixa os hubs (que é o proxy que discutimos acima). Em seguida, você verá a área circundada em vermelho para onde ele envia a solicitação de negociação ao servidor. Com base nisso, na próxima solicitação, o transporte webSockets é selecionado. Existem alguns outros dados com a solicitação também, como token de conexão, que é exclusivo por cliente.
Vamos observar no mesmo aplicativo em um ambiente diferente:

Esses detalhes foram capturados no Chrome, e aqui vemos que, além das solicitações comuns, ele envia a solicitação de negociação e escolhe serverSentEevents como o transporte e inicia a solicitação usando o transporte selecionado. Vejamos mais um cenário:

Por meio do IE9, recebemos três solicitações semelhantes às acima, exceto que o transporte selecionado foi foreverFrame, que inicia a conexão.
Vemos que, com base na solicitação de negociação, o SignalR escolhe uma das melhores opções – e, exceto para o Web Socket, ele requer mais uma solicitação para iniciar a conexão.
Limitando os protocolos de transporte
O SignalR é muito flexível e permite muitas opções de configuração com base na necessidade. Podemos configurar para um transporte específico ou podemos até mesmo fornecer o fallback em uma ordem específica. Isso também ajuda a reduzir o período de tempo inicial para iniciar a conexão, pois o SignalR já sabe qual protocolo de transporte deve ser usado. Podemos fornecer qualquer transporte específico ao iniciar o hub porque é a função que decide a seleção do Protocolo.
$.connection.hub.start({ transport: 'foreverFrame' });
Fornecemos também as opções de fallback como
$.connection.hub.start({ transport: ['foreverFrame', 'longPolling'] });
Nota – Semelhante a $.connection.hub.start(), o proxy também fornece outra função para interromper a conexão persistente como $.connection.hub.stop() e uma vez chamado, precisamos iniciar o hub novamente para continuar a comunicação entre cliente e servidor.
Conclusão
Nesta postagem, criamos um exemplo de monitor de servidor, onde o servidor envia os detalhes do contador de uso do servidor em um determinado intervalo para todos os clientes conectados. Usamos um temporizador que, após um certo intervalo, gera um evento, que primeiro coleta os contadores e transmite para o cliente conectado.
Também analisamos as ferramentas de desenvolvedor para examinar vários protocolos de transporte usados em vários cenários e vimos que o mesmo aplicativo usa protocolos diferentes com base nas negociações. Também vimos como restringir o transporte ou até mesmo fornecer um protocolo específico, o que reduz a sobrecarga inicial.
Espero que tenham gostado deste post, e obrigado por ler!