Por que o polling é aceito na programação da web?

107

Atualmente, estou trabalhando em um projeto Ruby on Rails , que mostra uma lista de imagens.

Um must-have para este projeto é que ele mostra novas postagens em tempo real, sem a necessidade de atualizar a página da web. Depois de procurar por um tempo, me deparei com algumas soluções e serviços de JavaScript, como o PubNub; no entanto, nenhuma das soluções fornecidas fazia sentido.

Na solução JavaScript ( sondagem ) acontece o seguinte:

  • O usuário 1 visualiza a lista de fotos.
  • No segundo plano, o código JavaScript está pesquisando um endpoint a cada segundo para ver se há uma nova postagem.
  • O usuário 2 adiciona uma nova foto.
  • Há um atraso de 50 ms antes que o novo ciclo seja acionado e busque os novos dados.
  • O novo conteúdo é carregado no DOM .

Isso parece estranho quando traduzido para um exemplo do mundo real:

  • O usuário 1 guarda uma pilha de fotos na sua mesa.
  • Ele caminha para o fotógrafo a cada segundo e pergunta se ele tem um novo.
  • O fotógrafo faz uma nova foto.
  • Neste segundo, quando ele entrar, ela pode tirar a foto e colocá-lo na pilha.

Na minha opinião, a solução deve ser a seguinte:

  • O usuário 1 guarda uma pilha de fotos na sua mesa.
  • O fotógrafo tira uma nova foto.
  • O fotógrafo anda até a pilha e coloca com o resto.

A solução PubNub é basicamente a mesma, mas desta vez há um interno andando entre as partes para compartilhar os dados.

É desnecessário dizer que ambas as soluções consomem muita energia, pois são acionadas mesmo quando não há dados para carregar.

No que diz respeito ao meu conhecimento, não há explicação (lógica) de por que essa forma de implementação é usada em quase todos os aplicativos em tempo real.

    
por dennis 22.07.2014 / 20:39
fonte

8 respostas

177

O envio funciona bem para 1 ou um número limitado de usuários.

Agora, altere o cenário com um fotógrafo e 1.000 usuários que desejam uma cópia da foto. O fotógrafo terá que andar para 1000 pilhas. Alguns deles podem estar no escritório trancado ou espalhados por todo o chão. Ou seu usuário em férias, e não está interessado em novas fotos no momento.

O fotógrafo estaria ocupado andando o tempo todo e não tiraria novas fotos.

Fundamentalmente: um modelo pull / poll escala melhor para muitos leitores não confiáveis com requisitos de tempo real fracos (se uma imagem leva 10 segundos depois para chegar em uma pilha, qual é o problema).

Dito isto, um modelo push ainda é melhor em muitas situações. Se você precisa de baixa latência (você precisa daquela nova foto 5s depois dela), ou atualizações são raras e pedem freqüentes e previsíveis (continue perguntando ao fotógrafo a cada 10 segundos quando ele gera uma nova foto por dia), então puxar é inadequado. Depende do que você está tentando fazer. NASDAQ: empurre. Tempo de serviço: puxar. Fotógrafo de casamento: provavelmente puxar. Agência de fotos de notícias: provavelmente pressione.

    
por 22.07.2014 / 20:57
fonte
106

Estou realmente surpreso que apenas uma pessoa tenha mencionado WebSockets . O suporte é implementado basicamente em todos os principais navegadores .

Na verdade, o PubNub os usa. Para o seu aplicativo, o navegador provavelmente se inscreveria em um soquete que seria transmitido sempre que uma nova foto estivesse disponível. O soquete não enviaria a foto, lembre-se, mas apenas um link para que o navegador possa baixá-lo de forma assíncrona.

No seu exemplo, imagine algo como:

  1. Usuário (s) informa ao fotógrafo que deseja saber sobre todas as fotos futuras
  2. O fotógrafo diz por alto-falante que uma nova foto está disponível
  3. O usuário pergunta ao fotógrafo por foto

Isto é um pouco como a sua solução de exemplo original. É mais eficiente que o polling porque o cliente não precisa enviar nenhum dado ao servidor (exceto talvez heartbeats .)

Além disso, como outros já mencionaram, existem outros métodos que são melhores que simples pesquisas que funcionam em navegadores mais antigos ( longpolling, et al .

    
por 22.07.2014 / 23:51
fonte
41

Às vezes bom o suficiente é bom o suficiente.

De todas as maneiras possíveis de implementar um processo de comunicação "em tempo real", a pesquisa talvez seja a maneira mais simples. O polling pode ser usado de forma eficaz quando o intervalo de polling é relativamente longo (ou seja, segundos, minutos ou horas em vez de instantâneo), e os ciclos de clock consumidos pela verificação da conexão ou do recurso não importam realmente.

    
por 22.07.2014 / 20:57
fonte
30

O protocolo HTTP é limitado em que o cliente deve ser o único a iniciar o pedido. O servidor não pode se comunicar com o cliente, a menos que esteja respondendo ao pedido do cliente.

Então, para ajustar seu exemplo do mundo real, adicione a seguinte restrição:

  • O usuário 2 pode responder SOMENTE às perguntas do Usuário 1 com uma única sentença de resposta, após o qual o Usuário 1 deve sair. O usuário 2 não tem outra maneira de se comunicar.

Com essa nova restrição, como você faria diferente da pesquisa?

    
por 22.07.2014 / 20:55
fonte
13

Por que o polling é aceito? Porque, na realidade, toda solução é, na verdade, uma pesquisa de baixo nível!

Se o servidor deve atualizá-lo assim que novas imagens estiverem disponíveis, ele geralmente terá uma conexão com você - porque os endereços IP mudam com frequência e você nunca sabe se alguém não está mais interessado, então o cliente tem que enviar alguma forma de sinal de keep-alive, por exemplo, "Ainda estou aqui, não estou off-line"

Todas as conexões com estado (por exemplo, TCP / IP) funcionam da mesma forma, já que você só pode enviar pacotes de dados singulares pela Internet; você nunca sabe se a outra parte ainda está lá.

Assim, todo protocolo tem um tempo limite. Se uma entidade não responder dentro de X segundos, presume-se que ela esteja morta. Portanto, mesmo se você tiver apenas uma conexão aberta entre servidor e cliente, sem enviar nenhum dado, o servidor e o cliente terão que enviar pacotes regulares de manutenção (isso é tratado em baixo nível se você abrir uma conexão entre eles). isso no final é diferente do polling?

Assim, a melhor abordagem provavelmente seria longa:

O cliente envia uma solicitação imediatamente após o carregamento do site (por exemplo, informando ao fotógrafo "Diga-me se há novas fotos"), mas o servidor não responde se não houver novas imagens. Assim que o pedido expira, o cliente pergunta novamente.

Se o servidor agora tiver novas imagens, ele poderá responder imediatamente a todos os clientes que estão na fila para novas fotos. Assim, seu tempo de reação após uma nova imagem é ainda menor do que com push, já que o cliente ainda está esperando em uma conexão aberta por uma resposta e você não precisa criar uma conexão com o cliente. E as solicitações de pesquisa do cliente não são muito mais tráfego do que uma conexão constante entre cliente e servidor para uma resposta!

    
por 24.07.2014 / 11:09
fonte
9

Uma vantagem do polling é que ele limita o dano que pode ser causado se uma mensagem desaparece ou o estado de algo fica com falha. Se X pedir Y para seu estado uma vez a cada cinco segundos, a perda de uma solicitação ou resposta resultará apenas em informações de Xs sendo dez segundos desatualizadas, em vez de 5. Se Y for reinicializado, X poderá descobrir a próxima o tempo Y é capaz de responder a uma das mensagens de X. Se o X for reinicializado, ele poderá nunca mais se incomodar em perguntar o Y por nada, mas quem quer que esteja observando o status do X deve reconhecer que ele foi reinicializado.

Se em vez de X polling Y, X confiasse em Y para informá-lo sempre que seu estado mudasse, então se o estado de Y mudasse e enviasse uma mensagem para X, mas por qualquer razão que a mensagem não fosse recebida, X nunca se tornaria ciente da mudança. Da mesma forma, se Y for reinicializado e nunca tiver qualquer razão para enviar uma mensagem X sobre qualquer coisa.

Em alguns casos, pode ser útil para o X solicitar que o Y envie mensagens automaticamente com seu status, seja periodicamente ou quando ele mudar, e só tenha X poll se demorar muito sem ouvir nada de Y. Tal projeto pode eliminar a necessidade de X enviar a maioria de suas mensagens (normalmente, X deve pelo menos informar ocasionalmente Y que ainda está interessado em receber mensagens, e Y deve parar de enviar mensagens se demorar muito sem qualquer indicação de interesse). Tal projeto, no entanto, exigiria que Y persistentemente mantenha informações sobre X, em vez de simplesmente enviar uma resposta a quem quer que tenha pesquisado e, em seguida, esquecer imediatamente quem era. Se Y é um sistema embarcado, tal simplificação pode ajudar a reduzir os requisitos de memória o suficiente para permitir o uso de um controlador menor e mais barato.

O polling pode ter uma vantagem adicional ao usar um meio de comunicação potencialmente não confiável (por exemplo, UDP ou rádio): ele pode, em grande parte, eliminar a necessidade de confirmações da camada de link. Se X enviar uma solicitação de status a Y, Q, Y responderá com um relatório de status R e X ouvirá R, X não precisará ouvir nenhum tipo de reconhecimento de camada de enlace para Q saber que foi recebido. Inversamente, quando Y envia R, não precisa saber ou se importar se X o recebeu. Se X enviar uma solicitação de status e não receber resposta, ela poderá enviar outra. Se Y enviar um relatório e X não o ouvir, X enviará outro pedido. Se cada solicitação sair uma vez e gerar uma resposta ou não, nenhuma das partes precisará saber ou se importar se alguma mensagem específica foi recebida. Como o envio de uma confirmação pode consumir quase a mesma largura de banda que uma solicitação ou relatório de status, o uso de um round-trip do relatório de solicitação não custa muito mais do que um relatório e confirmação não solicitados. Se o X envia algumas requisições sem receber respostas, em algumas redes roteadas dinamicamente é necessário habilitar reconhecimentos no nível do link (e pedir em seu pedido que Y faça o mesmo) para que a pilha de protocolos possa reconhecer o problema de entrega e procurar por uma nova rota, mas quando as coisas estiverem funcionando, um modelo de relatório de solicitação será mais eficiente do que usar confirmações de nível de link.

    
por 23.07.2014 / 00:28
fonte
1

A questão é equilibrar a quantidade de pesquisas desnecessárias em relação à quantidade de pushs desnecessários.

Se você pesquisar:

  • Você recebe uma resposta neste exato momento. Bom se você perguntar apenas ocasionalmente ou precisar de um conjunto de dados neste exato momento.
  • Você pode receber uma resposta "sem conteúdo", causando uma carga desnecessária na linha.
  • Você coloca a carga na linha somente quando você pesquisa, mas sempre quando você pesquisa.

Se você pressionar:

  • Você entrega a resposta certa quando está disponível, o que permite um processamento imediato no lado do cliente.
  • Você pode entregar dados a clientes que não estão interessados nesses dados, causando carga desnecessária na linha.
  • Você coloca a carga na linha sempre que houver novos dados, mas somente quando houver novos dados.

Existem várias soluções sobre como lidar com os vários cenários e suas desvantagens, como por exemplo, um tempo mínimo entre pesquisas, proxies somente para pesquisa para tirar a carga do sistema principal, ou - para os push - um regulamento para registrar e especificar os dados desejados seguidos do cancelamento do registro no logoff. Qual deles se encaixa melhor não é nada que você possa dizer em geral, isso depende do sistema.

Em seu exemplo, a pesquisa não é a solução mais eficiente, mas a mais prática. É muito fácil escrever um sistema de pesquisa em JavaScript, e é muito fácil implementá-lo no lado da entrega também. Um servidor feito para entregar dados de imagens deve ser capaz de lidar com as requisições extras, e se não, pode ser escalado linearmente, já que os dados são quase estáticos e podem ser facilmente armazenados em cache.

Um método push implementando um login, uma descrição dos dados desejados e, finalmente, um logoff seria mais eficiente, mas é provavelmente muito complexo para a média "script-kiddy", e precisa lidar com a questão: o que se o usuário apenas desliga o navegador e o log-off não pode ser executado?

Talvez seja melhor ter mais usuários (como acessar é fácil) do que economizar alguns dólares em outro servidor de cache?

    
por 23.07.2014 / 15:42
fonte
1

Por alguma razão, hoje em dia, todos os desenvolvedores web mais jovens parecem ter esquecido as lições do passado e por que algumas coisas evoluíram como fizeram.

  1. A largura de banda foi um problema
  2. A conexão pode ser intermitente.
  3. Os navegadores não têm tanto poder de computação
  4. Havia outros métodos de acessar o conteúdo. A web não é w3.

Em face dessas restrições, talvez você não tenha uma comunicação constante de duas vias. E se você observar o modelo OSI, descobrirá que a maioria das considerações serve para desacoplar a persistência com a conexão subjacente.

Com isso em mente, um método de pesquisa de informações é uma ótima maneira de reduzir a largura de banda e a computação no lado do cliente. A ascensão do push é na maioria das vezes apenas o cliente fazendo pesquisas constantes ou soquetes da web. Pessoalmente, se eu fosse todo mundo lá fora, eu apreciaria a regularidade das pesquisas como um meio de análise de tráfego, onde um pedido fora do tempo GET / POST poderia sinalizar um homem na situação intermediária de algum tipo.

    
por 24.11.2014 / 00:21
fonte