SignalR: resolvendo o problema da comunicação em tempo real
Nos últimos tempos, a demanda para aplicações em tempo real vem crescendo consideravelmente. Sites como Facebook e Twitter, jogos interativos, cotação de bolsa de valores, notificações de e-mail, chats, aplicações e-commerce, entre outros, são exemplos que utilizam a comunicação em tempo real.
Sumário
- 1 Mas, afinal, o que é uma aplicação em tempo real?
- 2 Como isso pode ser feito?
- 3 E agora? Devo escolher entre as técnicas existentes? Ou devo implementar um código que suporte as particularidades browsers / servidores?
- 4 Mas é complicada a implementação?
- 4.1 Startup.cs
- 4.2 HomeController.cs
- 4.3 Chat.cshtml
- 4.4 chat.js
- 4.5 ChatHub.cs
- 4.6 1) Declaração de um proxy no cliente que se referencia ao hub no servidor
- 4.7 3) Declaração das funções AdicionarUsuario e EnviarMensagem no servidor para serem acessadas pelo cliente
- 4.8 4) Iniciação da conexão do hub declarado no cliente e realização de ações após abertura da conexão.
- 4.9 5) Chamada de funções declaradas no servidor pelo cliente
- 4.10 6) Chamada de funções declaradas no cliente pelo servidor.
- 5 Ok, Entendi. Mas e se eu possuo uma aplicação com múltiplos servidores?
- 6 Então devo sempre utilizar o SignalR para comunicação em tempo real?
Mas, afinal, o que é uma aplicação em tempo real?
É uma aplicação na qual a informação é compartilhada em tempo real, ao vivo. Nesta aplicação, o servidor é capaz de sensibilizar / informar todos os clientes conectados assim que uma informação chega, sem precisar esperar que o cliente faça alguma requisição por estes dados.
Como isso pode ser feito?
Uma das primeiras alternativas apontadas para tentar resolver o problema da comunicação em tempo real foi o Ajax Polling, em que requisições são enviadas do cliente para o servidor de tempos em tempos. Quando o servidor responde, a conexão é fechada. Esta alternativa traz diversas desvantagens, como a perda de atualizações (caso o tempo de atualização não seja suficientemente pequeno) e a sobrecarga de requisições no servidor, principalmente quando se diminui o tempo entre requisições em busca de uma atualização mais confiável. Além disso, mesmo quando o servidor não possui respostas relevantes, o cliente continua fazendo requisições, o que deixa a comunicação mais lenta.
O Long Polling é outra tecnologia existente para suportar este tipo de comunicação. O cliente cria uma conexão com o servidor, que permanece aberta até que o servidor tenha uma nova atualização ou que o tempo da conexão expire. Em ambos os casos, o servidor responde ao cliente e ele, em seguida, faz uma nova requisição. Esta alternativa não tem atrasos, porém ainda existe a sobrecarga de requisições ao servidor.
Outra técnica existente é o Forever Frame, em que um iFrame escondido é criado no cliente e uma conexão duradoura é estabelecida com o servidor. Com isso, o servidor pode enviar trechos de código javascript para o cliente quando desejar notificá-lo de algo. A desvantagem nesse caso é que este método depende de particularidades de cada browser.
Na abordagem do Server Sent Event, o cliente estabelece uma conexão persistente com o servidor e as informações fluem somente no sentido servidor-cliente. Um objeto do tipo EventSource é criado no cliente com a url do servidor na qual haverão as atualizações. Sempre que uma atualização for percebida pelo servidor, um evento onMessage ocorre e a mensagem enviada pelo servidor pode ser interpretada pelo cliente. Essa técnica, no entanto, não é suportada no IE.
Finalmente, temos a técnica do Web Sockets, que é a melhor alternativa para tratar uma comunicação em tempo real. Uma conexão TCP é criada entre o cliente e o servidor e mantida enquanto necessário. A troca de mensagens é bidirecional, constante e rápida. Porém, é um protocolo que não é aceito em todos os navegadores web (Para o IE, é aceito somente na versão 10 em diante) e necessita estar instalado no IIS (oficialmente a partir do IIS 8).
E agora? Devo escolher entre as técnicas existentes? Ou devo implementar um código que suporte as particularidades browsers / servidores?
Nenhuma das duas alternativas! O SignalR é a resposta para esta pergunta. Trata-se de uma biblioteca open-source que veio para facilitar o gerenciamento e escolha dos protocolos de comunicação em tempo real, provendo atualizações / notificações de forma assíncrona em uma aplicação.
A biblioteca foi desenvolvida por dois funcionários da Microsoft, tendo sido, há algum tempo, incorporada pela plataforma ASP.net. Todo seu código fonte encontra-se no GitHub.
A tecnologia disponibiliza uma API para realização de uma chamada remota de procedimento, que permite a realização de chamadas em outros espaços de endereçamento, independente de como o procedimento está implementado. Isso permite a chamada de métodos do cliente no servidor e vice-versa. Além disso, o SignalR gerencia as conexões cliente-servidor, de forma que é possível a troca de mensagens entre servidor e todos os clientes, servidor e um cliente específico, servidor e um grupo de clientes.
Por baixo dos panos, o SignalR define o melhor tipo de comunicação entre aqueles já citados, de acordo com as configurações do cliente e do servidor.
No caso do cliente e do servidor permitirem o uso de um protocolo padronizado no HTML5, o melhor protocolo será usado. Caso não seja possível, o SignalR utilizará o modelo de programação Comet para estabelecer a comunicação em tempo real.
WebSockets é o transporte ideal para o SignalR pelas vantagens do mesmo. Por que então não implementar direto esta técnica? Porque utilizar o SignalR significa que várias implementações necessárias para o funcionamento da comunicação tempo real já vão estar feita para você. Mais importante, significa que você poderá usufruir das vantagens do WebSockets sem precisar se preocupar se o cliente ou servidor suportam esta tecnologia, sem encher o código de IF´s para tratar particularidades de clientes ou servidores. Com isso, apesar das formas de transporte serem variantes, o código fonte implementado é o mesmo.
Mas é complicada a implementação?
Não! Como exemplo, faremos uma aplicação simples de um chat. A intenção deste exemplo é apenas mostrar uma utilização simples e útil do SignalR.
A imagem a seguir resume a comunicação cliente-servidor estabelecida pelo SignalR:
O primeiro passo é incluir as bibliotecas do SignalR no seu projeto. Uma forma fácil de fazer isso é pelo gerenciador de componentes Nuget do Visual Studio. Vá em Tools | Library Package Manager | Package Manager Console e insira SignalR na busca.
O próximo passo é criar um arquivo de configuração do SignalR no projeto. Clique com o botão direito no projeto e adicione um novo Owin Startup Class. Caso sua versão do Visual Studio não possua essa opção, crie uma classe Startup da seguinte forma na raiz do projeto:
Startup.cs
A interface da nossa aplicação é bem simples: Uma tela de troca de mensagens que recebe o nome do usuário que está conectando à aplicação, registra esse usuário e o disponibiliza para troca de mensagens com os outros usuários conectados.
HomeController.cs
Chat.cshtml
chat.js
Na master page da aplicação, _Layout.cshtml, foi incluído um bundle contendo a biblioteca do SignalR, jquery.signalR-2.2.0.js.
Como podemos ver, na view mostrada, incluímos também um script signalr/hubs. Este script é necessário para o SignalR funcionar corretamente e é gerado automaticamente na execução da aplicação. Ele é responsável por fornecer todas as informações necessárias para a comunicação com o servidor.
Na parte do servidor, devemos criar uma classe que herda da classe Hub. O Hub é a forma de conexão alto nível entre cliente e servidor utilizada pelo SignalR; nessa classe, portanto, estarão implementados os métodos disponíveis para serem chamados pelo cliente e também a chamada de funções que estão declaradas no cliente.
ChatHub.cs
Nessa classe, podemos ver a implementação de um dicionário cuja chave e valor são strings para controle dos usuários que estão logados nesta aplicação. Essa implementação é simplista, por usar uma variável estática. Em uma aplicação mais complexa deve-se tratar a concorrência, múltiplos servidores, etc.
No código mostrado, temos algumas implementações bastante importantes:
1) Declaração de um proxy no cliente que se referencia ao hub no servidor
Quando fazemos esta implementação, estamos declarando o hub ChatHub (implementado no ChatHub.cs) no cliente, para estabelecer a comunicação.
2) Declaração das funções usuarioConectado e enviarMensagem no cliente para serem acessadas pelo servidor
3) Declaração das funções AdicionarUsuario e EnviarMensagem no servidor para serem acessadas pelo cliente
4) Iniciação da conexão do hub declarado no cliente e realização de ações após abertura da conexão.
5) Chamada de funções declaradas no servidor pelo cliente
6) Chamada de funções declaradas no cliente pelo servidor.
O objeto Clients é dinâmico, de forma que é possível alterar propriedades ou chamar métodos que podem não existir fisicamente. O SignalR interpreta todas estas chamadas em mensagens para serem enviadas aos clientes que estão conectados no servidor.
Nos dois primeiros métodos mostrados, chamamos Clients.All, que significa que queremos realizar a chamada pretendida em todos os clientes conectados no servidor; Já na implementação de Clients.User(connectionId), estamos realizando a chamada do método enviarMensagem somente para um cliente especificado.
Simples não é? Conexão bidirecional cliente-servidor e você não precisou especificar o transporte em nenhum momento; o SignalR simplesmente escolhe o melhor para você.
Ok, Entendi. Mas e se eu possuo uma aplicação com múltiplos servidores?
Como a conexão do SignalR é entre um servidor e um cliente específico, caso existam múltiplos servidores na arquitetura do sistema, se a atualização for percebida por um servidor e o cliente a ser notificado não tenha se conectado nele, haverá a perda de mensagem. Para solucionar este problema, o SignalR possibilita a implementação de um Backplane, que é um barramento para distribuição de mensagens. O servidor comunica com o backplane e ele reenvia as mensagens para os outros servidores, sincronizando-os e evitando a perda de mensagem.
Saiba mais sobre a implementação do backplane aqui.
Então devo sempre utilizar o SignalR para comunicação em tempo real?
Sim! Com ele você tem:
- Funcionalidades encapsuladas e prontas.
- Pode-se tirar vantagens dos transportes mais complexos sem se preocupar com clientes antigos.
- Não é necessária a preocupação com a atualização dos diferentes transportes e criação de uma nova forma de transporte
- Não é preciso fazer a escolha da melhor opção de transporte
- Fácil implementação
Agora que você sabe as vantagens, já pode usar o SignaIR nas suas aplicações. Se tiver alguma dúvida, entre em contato com a gente.
Por: Fernanda Vieira
Revisão: Jéssica Saliba.
Produtos Digitais
Confira outros artigos
Inteligência Conversacional: conecte-se com seus clientes!
Em um mundo cada vez mais digital, a capacidade de se conectar com os clientes de forma personalizada e eficiente é crucial para o sucesso de qualquer negócio. Dessa forma, a Inteligência Conversacional surge como uma poderosa ferramenta para alcançar esse objetivo, revolucionando a forma como as empresas interagem com seu público e otimizam suas […]
Produtos Digitais
Produtos digitais: entregas contínuas com IA
Nas últimas semanas, lançamos uma série de artigos sobre o uso de inteligência artificial no processo de construção de produtos digitais. Neles, apresentamos alguns aceleradores que a dti tem utilizado para potencializar a eficiência dos times. Abordamos a fase de concepção do produto, as atividades de gestão e design, o desenvolvimento do software e a […]
Produtos Digitais
Inteligência Artificial: acelerando o design e gestão de produtos digitais
Como aproveitar o melhor da Inteligência Artificial Generativa para gerar mais valor? Essa tem sido uma pergunta recorrente no mercado conforme as empresas buscam entender e adotar a tecnologia. Embora existam muitas dúvidas e hipóteses não comprovadas, parece ser consenso que os avanços na Inteligência Artificial impactarão significativamente muitas profissões. No relatório The economic potencial […]
Produtos Digitais