Partilhar via


Este artigo foi traduzido por máquina.

Cutting Edge

Sondagem longa e SignalR

Dino Esposito

 

Dino EspositoEstamos a construir aplicações Web mais sofisticadas em cima de um protocolo que, paradoxalmente, foi concebida e projectada para muito mais simples formas de interação. HTTP tem suporte incorporado para o Estado ou mesmo segurança. Seu pressuposto básico é que o cliente faz uma solicitação e o servidor Web emitirá uma resposta. Em suma, isso significa que nenhuma solicitação, nenhuma resposta.

Dada a penetração atual da Web e a ubiquidade de soluções Web, mudar os pilares da Web (HTTP, HTML, JavaScript) é fora de questão. Mas devemos considerar melhorar alguns desses pilares? É claro! Aplicações modernas têm requisitos específicos que empurrar Web protocolos e linguagens para seu limite — ou mais além.

Nas recentes edições desta coluna, abordei uma implementação artesanal de um mecanismo que controla o servidor e relata as alterações para o cliente. No mês passado, implementei a mesma idéia usando os serviços de uma biblioteca de emergente — SignalR. Agora eu vou dar uma visão geral das técnicas e um resumo das opções que você tem hoje. Vou colocar SignalR no centro do atenções e olhar para sua implementação — e alguns de sua magia.

Considerações de sondagem

Tendo em conta a restrição de solicitação/resposta HTTP, a sondagem é a única maneira de configurar a comunicação ao vivo entre um cliente e um servidor Web. O cliente envia solicitações em sua conveniência e o servidor responde diligentemente. A chave para avaliar a eficácia de sondagem é o real significado que você atribui à expressão "a sua conveniência." Há sempre uma solicitação de cliente no núcleo de qualquer solução baseada na sondagem. O pedido fica até que o servidor respondeu. Qualquer solicitação pendente consome uma ligação do browser e, mais importante ainda, contrata um thread de servidor, tornando esse valioso recurso indisponível para outras solicitações. Em poucas palavras, demasiado frequentes solicitações construir pressão no servidor Web.

Mas não é a capacidade do servidor para manipular um número crescente de pedidos de todo o conceito de escalabilidade? Na verdade, sondagem não cria novas preocupações de escalabilidade, mas ele adicionar um número substancial de novas solicitações para o servidor que deve ser tomado em conta para garantir um servidor escalável e de alto desempenho. Vamos ver como nós pode implementar sondagem.

Pesquisa AJAX

Na minha de Dezembro de 2011 (msdn.microsoft.com/magazine/hh580729) e de Janeiro de 2012 (msdn.microsoft.com/magazine/hh708746) colunas, apresentei um quadro para controlar o Progressoo de uma operação remota. A estrutura inteira foi baseada em chamadas AJAX. Em primeiro lugar, o cliente chama um ponto de extremidade do servidor para iniciar uma tarefa potencialmente moroso; em seguida, ele define um temporizador para colocar chamadas simultâneas para outro ponto de extremidade a cada 500 milissegundos. Como a tarefa de servidor faz o seu trabalho, ele atualiza um local conhecido. O ponto de extremidade do servidor que tenha invocado periodicamente simplesmente verifica se há dados nesse local e retorna qualquer conteúdo que ele encontra para o cliente.

Este padrão AJAX-sondagem funciona lindamente e é amplamente empregado em muitos cenários de indústria. A maioria dos sites que fornecem atualizações de notícias ou placares seguem esse padrão. Em meus artigos, eu simplesmente adaptou o padrão para o cenário específico de acompanhar o progresso de uma operação remota.

No final, o problema com a sondagem de AJAX é descobrir o intervalo de atualização de direito — uma que representa um bom equilíbrio entre a pressão no servidor e precisão da informação comunicada aos usuários. Uma solução eficaz de AJAX-sondagem dá um significado concreto para "do cliente conveniência" no envio de solicitações.

Long Polling

Antes de AJAX, desenvolvedores usaram a atualizar de meta tag HTML para instruir o navegador para atualizar uma página cada determinado número de segundos. Com sondagem do AJAX, você conseguir a mesma coisa, mas de uma maneira muito mais suave.

Para um número crescente de aplicações, no entanto, esta forma de sondagem não basta. Pesquisa AJAX quase inevitavelmente apresenta um atraso entre a ocorrência de um evento no servidor e a notificação do evento para o cliente. Ajustando a freqüência das atualizações, você pode encontrar soluções boas, ainda sondagem AJAX não pode entregar essa conexão constante e contínua que muitos aplicativos (principalmente sociais) parecem necessitar de hoje.

A solução nestes dias parece ser longo de sondagem. Curiosamente, quando AJAX surgiu anos atrás, mais inteligente pesquisa AJAX substituído long polling porque este último não foi muito eficaz na Web. Long polling é sobre fazer pela Web as mesmas coisas que você faz em um cenário de área de trabalho. Com sondagem longa, o cliente faz a solicitação e o servidor não responder até que tenha informações para retornar. O cliente da Web mantém uma conexão pendente que é fechada somente quando alguma resposta válida pode ser retornada. Isso é exatamente o que você quer hoje em dia — exceto que ele tem o potencial de retardar o servidor Web.

Tempo de sondagem coloca um menor número de solicitações para o servidor em comparação com sondagem de AJAX, mas cada solicitação poderia levar muito mais tempo. Ao longo do tempo, isso pode ser prejudicial para a saúde do servidor da Web pois mantém segmentos de servidor envolvidos até que uma resposta pode ser gerada. Com menos threads de trabalho disponíveis em um determinado momento, o servidor Web inevitavelmente fica mais lenta em responder a quaisquer outros pedidos recebe. Para ser eficaz, long polling precisa de algum trabalho de implementação séria e avançadas habilidades de programação multithread e paralelas. Assim, durante anos, muito tempo de sondagem não era realmente uma opção, mas não importa porque não havia nenhuma demanda por conectividade contínua.

Hoje, com a biblioteca paralela de tarefas no Microsoft.NET Framework 4 e outras instalações em ASP.NET para a criação de manipuladores HTTP assíncronos, longos polling tornou-se uma opção viável. Em geral, handcrafting um quadro de long-polling é ainda mais difícil do que um quadro AJAX-polling correspondente. Você precisa de um ambiente bem projetado que não fiscal o servidor Web e um ambiente de cliente que pode suportar longa de sondagem. Na verdade, Long polling, se refere a uma operação de cliente/servidor de macro que se desenvolve através da Web e, necessariamente, ao longo de vários pacotes de solicitação/resposta HTTP clássicos. O cliente deve ser inteligente o suficiente para voltar a publicar uma nova solicitação de imediata até que a operação de macro termina. Voltarei a este ponto mais tarde.

SignalR para o resgate

SignalR é um framework de Microsoft projetado especificamente para facilitar a comunicação cliente/servidor em tempo real. Fornece uma implementação eficaz do longo de sondagem que não tem um impacto profundo sobre o servidor e ao mesmo tempo garante que os clientes são atualizados apropriadamente sobre o que está acontecendo remotamente. Figura 1mostra um trecho de código que apresentei em minha última coluna. A classe BookingHub é o método que você chama de navegador da Web para iniciar a operação de macro "reservar o voo."

Figura 1 SignalR classe que executa uma operação de Multistep

public class BookingHub : Hub
{
  public void BookFlight(String from, String to)
  {
    // Book first leg
    Clients.displayMessage(
      String.Format("Booking flight: {0}-{1} ...", from, to));
    BookFlightInternal(from, to);
    // Book return
    Clients.displayMessage(
      String.Format("Booking flight: {0}-{1} ...", to, from));
    BookFlightInternal(to, from);
    // Book return
    Clients.displayMessage("Charging credit card ...");
    ChargeCreditCardInternal();
    // Some return value
    Clients.displayMessage("Flight booked successfully.");
  }
}

Esta é claramente uma operação de várias etapas, e para cada etapa da classe envia uma notificação para o cliente. Quantos pedidos de HTTP estão envolvidos? Vamos dar uma olhada com Fiddler (ver Figura 2).

The Full Stack of HTTP Requests for the Flight-Booking Operation
Figura 2 A pilha completa de solicitações HTTP para a operação de reserva de vôo

Dentro de uma operação de SignalR

A primeira solicitação é disparada quando você chamar o método iniciar da página do cliente; Isso identifica o cliente ao back-end SignalR. Note-se que o primeiro pedido é um pedido especial de negociação. Será sempre AJAX independentemente do transporte final negociado para a conexão. Qualquer página da Web de SignalR inclui o código como o seguinte que é executado quando uma página é carregada:

$(function () {
  var bookingHub = $.connection.bookingHub;
  bookingHub.start();
}

Desta forma, a página declara sua intenção de abrir uma conexão para invocar os serviços do objeto do servidor bookingHub. Note que é SignalR que faz a mágica de criar um objeto de cliente de acordo com a interface pública do objeto do servidor de hub. O nome do objeto JavaScript corresponde ao nome do objeto do servidor. No entanto, você pode usar o atributo HubName para modificar o nome está sendo usado no cliente:

[HubName("booking")]
public class BookingHub : Hub
{
  ...
}

A solicitação de inicialização retorna uma ID de cliente que o cliente vai passar junto com quaisquer solicitações sucessivas.

{"Url":"/signalr","connectionId":"2a119962-edf7-4a97-954b-e74f2f1d27a9"}

Em seguida, a biblioteca de cliente coloca outra solicitação de conexão. Este é o pedido de "conectar", que irá resultar no evento OnConnect está sendo gerado para a conexão no servidor. Figura 3 mostra um par de solicitações de conexão.

Reiterating Connection Requests
Figura 3 reiterando as solicitações de conexão

A primeira concluída em dois minutos; o segundo é ainda pendente. Esta é a essência de long polling — o cliente tem um canal continuamente aberto com o servidor. O servidor expire a solicitação após dois minutos se nenhuma ação é executada no servidor que requer o envio de dados ao cliente. No aplicativo de vôo reserva da interface do usuário, existe um botão que o usuário pode clicar para iniciar a reserva do voo. Quando o usuário clica no botão executa o código a seguir:

bookingHub.bookFlight("fco", "jfk");

Se você criou o aplicativo de exemplo da coluna do mês passado, deve ter ligado este código ao manipulador click do botão de página.

O objeto bookingHub pertence a um script que SignalR downloads através de URL signalr/hubs, como mostrado na Figura 3. bookingHub é um objeto de proxy simples que oculta a complexidade da implementação de um padrão de long-polling. Clique no botão aciona uma nova solicitação para o servidor onde o ID do cliente é incorporado. Quando o servidor recebe um telefonema de um cliente que tem uma chamada pendente, ele termina a chamada pendente e começa a processar a solicitação de nova, como mostrado na Figura 4.

A Multistep Operation Is Taking Place
Figura 4 multipasso operação está ocorrendo

Figura 4 mostra uma solicitação pendente (signalr/enviar), duas solicitações concluídas e outra solicitação pendente. O pedido de signalr/envio é o original chamar para a operação de macro para reserva do voo, cujo código-fonte é mostrado na Figura 1.

O código no Figura 1 chama o cliente em várias fases para comunicar-lhe quaisquer progressos, da seguinte forma:

Clients.displayMessage(...);

Ao mesmo tempo que um pedido de signalr/enviar é colocado, outra solicitação inicia aguardar notificações. Este pedido aguarda até que há alguns dados para enviar voltar. Qualquer chamada para clientes no código do servidor conclui o pedido de notificação e imediatamente aciona um outro do cliente, então a seqüência no Figura 4 significa que duas etapas foram concluídas e duas mensagens de progresso tem sido recebidas pelo cliente. O processo do servidor agora está ocupado tentando realizar a terceira etapa. No final do código em Figura 1, todas as solicitações no Figura 4 terá concluído e a situação retornará a um semelhante ao que é mostrado no Figura 2.

Além do Long Polling

Se você comparar o comportamento de longa conforme implementado na SignalR com as etapas de sondagem indiquei em meus artigos sobre sondagem de AJAX, você deve reconhecer um padrão comum — o padrão Progress Indicator. AJAX de sondagem e long polling é duas implementações diferentes do mesmo padrão. Qual deles é mais eficaz depende da configuração do servidor Web e os requisitos do aplicativo. É a chamada. Em qualquer caso, se você optar por sondagem longa, você precisa SignalR ou uma biblioteca análoga. Se você quer construir seu próprio quadro, sugiro que você opt para as chamadas de numerosos-mas-rápido de pesquisa AJAX contra as menos-mas-mais chamadas de longa de sondagem.

Criação de um quadro eficaz de long-polling pode ser complicada. Com sondagem AJAX você provavelmente não começ conectividade contínua, mas você também não arrisca a abrandar o servidor. Com isto em mente, eu provavelmente não vai sair por aí e atualizar qualquer servidor Web em tempo real que eu tomar cuidado para SignalR. No entanto, uma vez SignalR é liberado, não vejo qualquer razão para não usá-lo para novas aplicações.

Finalmente, vale a pena mencionar que SignalR agora oferece suporte a outros transportes alto nível além de sondagem longa. A fonte mais recente, você também encontrar suporte para WebSockets em servidores Windows 8; Servidor enviou eventos no Chrome, Firefox, Opera e Safari; e para sempre enquadrar no Internet Explorer. A biblioteca começa no início da lista e mantém caindo voltar até encontra um transporte com suporte. Assim, no final, há muito tempo de sondagem será realmente raramente usado na maioria dos casos.

Dino Esposito* é autor de "Programming ASP.NET 4 "(Microsoft Press, 2011) e"programação ASP.NET MVC 3 "(Microsoft Press, 2010) e co-autor de"Microsoft.NET: arquitetura de aplicações para a empresa "(Microsoft Press, 2008). Residente na Itália, Esposito é um palestrante sempre presente em eventos do setor no mundo inteiro. Segui-lo no Twitter em Twitter.com/despos.*

Graças ao seguinte especialista técnico para revisão deste artigo: Damian Edwards