Por que a pesquisa de opinião é aceita na programação da web?


108

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

Um item essencial para esse projeto é que ele mostra novas postagens em tempo real sem a necessidade de atualizar a página da web. Depois de pesquisar um pouco, deparei-me com algumas soluções e serviços 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.
  • Em segundo plano, o código JavaScript está pesquisando um ponto de extremidade 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 tem uma pilha de fotos em sua mesa.
  • Ele / ela 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 entra, pode tirar a foto e colocá-la na pilha.

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

  • O usuário 1 tem uma pilha de fotos em sua mesa.
  • O fotógrafo tira uma nova foto.
  • O fotógrafo caminha até a pilha e a põe com o resto.

A solução PubNub é basicamente a mesma, porém desta vez há um estagiário caminhando 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) por que esse modo de implementação é usado em quase todos os aplicativos em tempo real.


195
Ignorando por um momento que os navegadores da web não são servidores que podem receber conexões de entrada ... espere, não, não vamos ignorar isso.
GrandmasterB

17
@ dennis: uma conexão estável e persistente entre o servidor e o cliente provavelmente eliminaria a necessidade de pesquisas, mas não foi assim que a Web foi projetada.
FrustratedWithFormsDesigner

58
E quanto aos Websockets?
22714

25
Ou dê uma olhada nas pesquisas longas. Basicamente, você pesquisa, mas o servidor não responde antes de ter novos dados para mostrar.
Matsemann

53
Existem muitas soluções e algoritmos perfeitamente sensatos no espaço do computador que seriam completamente absurdos no espaço de carnes.
Whatsisname

Respostas:


179

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

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

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

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

Dito isto, um modelo push ainda é melhor em muitas situações. Se você precisar de baixa latência (precisa da nova foto 5s depois de tirada), ou as atualizações forem raras e solicite freqüentes e previsíveis (pergunte ao fotógrafo a cada 10 segundos quando ele gerar uma nova foto por dia), puxar é inapropriado. Depende do que você está tentando fazer. NASDAQ: push. Serviço meteorológico: tração. Fotógrafo de casamento: provavelmente pull. Agência de notícias: provavelmente pressione.


32
Eu realmente gosto da sua analogia com 1000 usuários, alguns de férias, outros não interessados. +1.
Rjalk

4
@EsbenSkovPedersen: o limite do soquete não é devido ao endereço IP. É devido ao descritor máximo de arquivo aberto. Portanto, o número máximo de soquetes abertos é independente de quantos endereços IP você usa.
slebetman

10
Essa é uma analogia horrível para dizer o mínimo. Para que o push funcione, o cliente de qualquer usuário deve manter uma conexão aberta de algum tipo. De fato, a pesquisa é uma emulação de uma conexão. Não é como porque alguns clientes estão pesquisando, que todos os clientes são notificados. Da mesma forma, quando alguns clientes abrem uma conexão para notificações push, nem todos os clientes são notificados. Este é um conselho muito ruim que convida a lançar recursos pela janela. Ser bombardeado com 10000 solicitações por segundo praticamente nunca é mais barato ou melhor do que manter 10000 soquetes abertos.
Jul23

8
@ ptyx: O intervalo 1s é o discutido aqui. 10k solicitações por segundo significam 10k handshakes TCP e 10k solicitações HTTP (cada uma alcançando facilmente 2KB), o que oferece várias ordens de magnitude com mais ruído de fundo que sobrecarrega o servidor. Há uma variedade de bibliotecas testadas em batalha que tornam as assinaturas push tão fáceis quanto colocar a pesquisa no local. Existem até estruturas como o meteor.js que abstraem completamente toda a questão. Apelar à escalabilidade sem maiores explicações também não é um argumento. De qualquer forma, eu expressei minhas dúvidas e não deseja iniciar uma discussão;)
back2dos

5
Eu concordo com o comentário de back2dos acima. Se o pull for dimensionado melhor do que o push, o google, a troca de pilhas, o facebook, os serviços de estoque on-line etc. usarão a tecnologia pull. Mas eles não. Fundamentalmente, martelar o servidor em vez de configurar uma estação de escuta aumenta enormemente. Os principais serviços evitam pesquisas.
Travis J

106

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

De fato, o PubNub os usa. Para seu aplicativo, o navegador provavelmente assinaria um soquete que seria transmitido sempre que uma nova foto estivesse disponível. O soquete não envia a foto, lembre-se, mas apenas um link para que o navegador possa baixá-la de forma assíncrona.

No seu exemplo, imagine algo como:

  1. O (s) usuário (s) permite que o fotógrafo saiba que ele quer saber sobre todas as fotos futuras
  2. Fotógrafo diz pelo alto-falante que uma nova foto está disponível
  3. Usuário pede foto do fotógrafo

É um pouco como a sua solução de exemplo original. É mais eficiente do que a pesquisa porque o cliente não precisa enviar nenhum dado ao servidor (exceto, talvez, batimentos cardíacos ).

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


43
@RobertHarvey, como é que os WebSockets não estão relacionados à pergunta? A questão pergunta se a pesquisa é uma estratégia aceitável e hoje em dia claramente não é aceitável (ou pelo menos não é ideal). WebSockets, eventos enviados pelo servidor e pesquisas longas têm um desempenho muito melhor em praticamente todos os casos de uso.
Fabrício Matté 22/07/2014

7
@RobertHarvey, essa foi apenas a minha interpretação, sem reformular tanto quanto eu posso ver. Claro, a pergunta foi feita por que ela ainda é aceita e não qual é a estratégia ideal , mas essas ainda estão intimamente relacionadas.
Fabrício Matté 22/07

25
Os WebSockets (e similares) são os mais próximos que você pode implementar da "solução" do OP, então acho que é muito relevante, apesar de ele não ter mencionado isso especificamente.
22614 korylprince

6
Sem mencionar, StackExchangesites como o que você está usando agora (a menos que esteja vendo esta página em cache / salva) usam WebSockets. Era por isso que eu também estava me perguntando por que ninguém até @korylprince mencionou WebSockets.
trysis 23/07

6
@ FabrícioMatté: na verdade, nem todos os casos de uso. Pesquisas longas exigem manter um soquete aberto para todos os usuários que consomem recursos do sistema. Serviços fr que não são muito críticos em termos de tempo, mas têm muitos usuários, manter um soquete aberto geralmente é mais caro do que atender um 304 curto de vez em quando. Para a maioria dos serviços, um pequeno atraso não é um problema. Uma única máquina geralmente pode atender mais clientes com polling do que com push.
Lie Ryan

42

Às vezes, bom o suficiente é bom o suficiente.

De todas as formas possíveis de implementar um processo de comunicação em "tempo real", a pesquisa talvez seja a maneira mais simples. A pesquisa pode ser usada efetivamente quando o intervalo de pesquisa é relativamente longo (ou seja, segundos, minutos ou horas, e não instantâneo), e o ciclo do relógio consumido verificando a conexão ou o recurso realmente não importa.


3
Isso, mil vezes isso. É aceito porque geralmente é bom o suficiente.
corsiKa

1
Essa é uma resposta boa o suficiente
Zain R

31

O protocolo HTTP é limitado, pois o cliente DEVE ser o único a iniciar a solicitação. O servidor não pode se comunicar com o cliente, a menos que responda a uma solicitação do cliente.

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

  • O Usuário 2 SOMENTE pode responder às perguntas do Usuário 1 com uma resposta de frase única, após a 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 isso além da votação?


6
O HTTP 2.0 dará suporte a pushes do servidor. "O envio permite que os servidores enviem representações aos clientes sem que uma solicitação explícita seja feita." pt.wikipedia.org/wiki/HTTP_2.0
kaptan

5
@ Kaptan, isso é ótimo, mas não está disponível. Se contentar com o que você tem.
Rjalk

7
Há também pesquisas longas que estão disponíveis no momento e simulam um modelo push usando um pull.
Tim B

24
@ dennis: Tendo escrito um software de automação industrial, gostaria de comentar seu exemplo de pesquisa de sensores. Os sensores de polling servem para dois propósitos - o mais óbvio é buscar novos dados. O menos óbvio é detectar que o sensor ainda está vivo, não travou devido a um erro ou queima devido a incêndio na fábrica ou derretido devido a acidente industrial. O silêncio, o fato de você não receber resposta, também é um dado valioso.
slebetman

3
Os sensores @dennis costumam sentir muito mais rápido do que você está interessado nos dados. A pesquisa permite que você obtenha o valor do sensor exatamente quando quiser, sem ser inundado por atualizações que não lhe interessam. (Imagine se o OS notificado a sua aplicação cada vez que um arquivo foi alterado em qualquer lugar no disco, em vez de sua aplicação precisar abrir e ler o arquivo)
immibis

13

Por que a pesquisa é aceita? Porque, na realidade, todas as soluções são realmente pesquisas de baixo nível!

Se o servidor precisar atualizá-lo assim que novas fotos estiverem disponíveis, ele geralmente precisará ter uma conexão com você - porque os endereços IP mudam frequentemente e você nunca sabe se alguém não está mais interessado, portanto, o cliente precisa enviar algum tipo de sinal keep-alive, por exemplo, "ainda estou aqui, não estou offline"

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

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

Portanto, a melhor abordagem provavelmente seria longa:

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

Se o servidor agora tiver novas fotos, ele poderá responder imediatamente a todos os clientes que estão na fila para novas fotos. Portanto, seu tempo de reação após uma nova imagem é ainda menor do que com o envio por push, pois o cliente ainda aguarda uma resposta em uma conexão aberta 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!


Não concordo que todas as soluções acabem sendo pesquisas de baixo nível. Você está confundindo a pesquisa necessária para enviar dados com a pesquisa necessária para saber quando um cliente é perdido. Sim, o último sempre acaba pesquisando em algum lugar da pilha de protocolos, mas isso pode ocorrer em uma frequência muito baixa (como uma vez a cada cinco minutos), enquanto a pesquisa de dados reais a cada segundo é um desperdício que PODE ser evitado com verdadeiras notificações push que NÃO está pesquisando em nenhum nível da pilha.
Allon Guralnek

Primeiro, a maioria dos pacotes keepalive é executada em uma frequência bastante alta, porque você deseja evitar intervalos de tempo limite comuns, pois poucos segundos não são incomuns para TCP / IP e quase tudo que não estiver usando tcp pode ser bloqueado por firewalls. Então, quando eu preciso enviar um pacote de dados a cada X segundos, por que não preenchê-lo com alguns dados praticamente sem nenhum custo?
Falco

1
@Guralnek, mesmo que você tivesse uma conexão com um intervalo de keep alive de 5 minutos, o tempo limite seria maior, pois você precisa adicionar um atraso real e pacotes perdidos. Eo servidor iria manter muitas conexões para 5min depois que os clientes ter desligado, de modo geral este poderia custar mais recursos do servidor, enquanto salvando apenas largura de banda mínima
Falco

1
+1 para pesquisas longas. Procure o Cometa en.wikipedia.org/wiki/Comet_%28programming%29
Zan Lynx

9

Uma vantagem da pesquisa é que ela limita o dano que pode ser causado se uma mensagem desaparecer ou se o estado de algo for danificado. Se X solicitar seu estado a Y uma vez a cada cinco segundos, a perda de uma solicitação ou resposta resultará apenas na informação de X sendo dez segundos desatualizada em vez de 5. Se Y for reiniciado, X poderá descobrir sobre isso na próxima o tempo Y é capaz de responder a uma das mensagens de X. Se o X for reiniciado, talvez nunca mais lhe peça nada, mas quem estiver observando o status do X deve reconhecer que foi reiniciado.

Se, em vez de X pesquisar Y, X confiasse em Y para informá-lo sempre que seu estado fosse alterado, se o estado de Y mudasse e ele enviasse uma mensagem para X, mas por qualquer motivo, essa mensagem não foi recebida, X poderá nunca tomar conhecimento da alteração . Da mesma forma, se Y for reiniciado e nunca tiver qualquer motivo para enviar uma mensagem a X sobre algo.

Em alguns casos, pode ser útil para o X solicitar que Y envie autonomamente mensagens com seu status, periodicamente ou quando elas forem alteradas, e só faça a pesquisa X se demorar demais sem ouvir nada de Y. Esse design pode eliminar o é necessário que X envie a maioria de suas mensagens (normalmente, X deve ao menos ocasionalmente informar Y de que ainda está interessado em receber mensagens e Y deve parar de enviar mensagens se demorar demais sem qualquer indicação de interesse). Tal projeto exigiria, no entanto, que Y persistissemantenha as informações sobre o X, em vez de poder simplesmente enviar uma resposta para quem as pesquisou e depois esquecer imediatamente quem era. Se Y for um sistema incorporado, essa simplificação pode ajudar a reduzir os requisitos de memória o suficiente para permitir o uso de um controlador menor e mais barato.

A pesquisa pode ter uma vantagem adicional ao usar um meio de comunicação potencialmente não confiável (por exemplo, UDP ou rádio): ele elimina amplamente a necessidade de reconhecimento da camada de link. Se X enviar a Y uma solicitação de status Q, Y responder com um relatório de status R e X ouvir R, X não precisará ouvir nenhum tipo de reconhecimento da camada de link para que Q saiba que foi recebido. Por outro lado, uma vez que Y envia R, ele não precisa saber ou se importar se X o recebeu. Se X envia uma solicitação de status e não obtém resposta, ele pode enviar outra. Se Y enviar um relatório e X não o ouvir, X enviará outra solicitação. Se cada solicitação sair uma vez e fornecer 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 uma viagem de ida e volta de relatório de solicitação não custa muito mais do que custaria um relatório e uma confirmação não solicitados. Se o X enviar algumas solicitações sem obter respostas, em algumas redes roteadas dinamicamente, será necessário habilitar as confirmações no nível do link (e solicitar na solicitação que Y faça o mesmo) para que a pilha de protocolos subjacente 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 no nível do link.


O problema sobre o qual você fala com Y enviando mensagens para X (segundo parágrafo) pode ser corrigido com um número de série anexado a cada mensagem. Se uma mensagem for perdida, X saberá porque não recebeu essa série. Nesse ponto, é possível tomar outras medidas para sincronizar com o Y. DNS master -> a replicação escrava funciona dessa maneira.
Krllince

@korylprince: Qualquer um dos lados pode descobrir a mensagem que falta, se o outro lado tiver ocasião de enviar algo (e faz isso com sucesso), ou se tiver motivos para esperar algo do outro lado e nunca recebê-lo. Se um lado enviar uma atualização de status e não exigir reconhecimentos ou desistir após tentar algumas vezes, e o outro lado não estiver esperando transmissões agendadas, o outro lado não saberá que a conexão desapareceu.
Supercat

2
@korylprince - O problema é que, sem mensagens periódicas, o X pode detectar a mensagem ausente com um dia de atraso ou um ano de atraso ou 10 anos de atraso. Para detectar pacotes ausentes em tempo razoável, é necessário pesquisar de alguma forma. Você pode "puxar" a pesquisa ou pode "empurrar" a pesquisa. O primeiro é chamado de "polling", o segundo é chamado de "batimento cardíaco"
slebetman

Ambos muito verdadeiros. Tudo depende da situação.
Korylprince

@slebetman: Sem mensagens periódicas, se Y seja reiniciado, pode haver nenhum mecanismo pelo qual X iria nunca descobri-lo.
Supercat

1

A questão é equilibrar a quantidade de pesquisas desnecessárias versus a quantidade de empurrões 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 obter uma resposta "sem conteúdo", causando carga inútil na linha.
  • Você coloca carga na linha somente quando faz uma pesquisa, mas sempre quando faz uma pesquisa.

Se você pressionar:

  • Você entrega a resposta exatamente quando está disponível, o que permite um processamento imediato no lado do cliente.
  • Você pode fornecer dados para clientes que não estão interessados ​​nesses dados, causando carga inútil na linha.
  • Você coloca carga na linha toda vez que há novos dados, mas somente quando há 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 de pesquisas para retirar a carga do sistema principal ou - para os empurrões - um regulamento para registrar e especificar os dados desejados seguidos pelo cancelamento do registro no logoff. Qual deles se encaixa melhor não é nada que você possa dizer em geral, depende do sistema.

No seu exemplo, a pesquisa não é a solução mais eficiente, mas a mais prática. É muito fácil escrever um sistema de votação em JavaScript e também muito fácil implementá-lo no lado da entrega. Um servidor criado para fornecer dados de imagem deve ser capaz de lidar com solicitações extras e, se não, pode ser dimensionado linearmente, pois os dados geralmente são estáticos e, portanto, podem ser facilmente armazenados em cache.

Um método push implementando um logon, descrição dos dados desejados e, finalmente, um logoff seria mais eficiente, mas provavelmente é muito complexo para o "script-kiddy" médio e precisa lidar com a pergunta: e se o usuário apenas desliga o navegador e o logoff não pode ser realizado?

Talvez seja melhor ter mais usuários (o acesso é fácil) do que economizar algum dinheiro em outro servidor de cache?


1

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

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

Diante dessas restrições, talvez você não tenha uma comunicação bidirecional constante. E se você analisasse o modelo OSI, descobriria que a maioria das considerações visa dissociar 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. O aumento da pressão é, na maioria das vezes, apenas o cliente que realiza pesquisas constantes ou soquetes da web. Pessoalmente, se eu fosse todo mundo lá fora, eu apreciaria a regularidade da pesquisa como um meio de análise de tráfego, onde uma solicitação GET / POST fora do tempo sinalizaria um homem na situação intermediária de algum tipo.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.