Pergunta

No projeto que estou trabalhando atualmente, temos a necessidade de desenvolver uma aplicação de web chat, não é um chat muito complexo, apenas uma forma de conectar duas pessoas para conversar sobre um tema bem específico, não precisamos de nenhum tipo de autenticação para um dos dois usuários, não precisamos oferecer suporte a emoticons, avatares ou coisas assim.

Alguns membros do projeto sugeriram que poderíamos usar XMPP através do BOSH, eu disse que é como tentar pegar um peixe com a rede de um barco, e propus um método mais simples, como um simples chat na web Ajax/MySQL, mas estamos preocupados com o desempenho atingido no servidor por causa da pesquisa constante de muitos chats abertos ao mesmo tempo.

Alguém já fez algo assim antes?O que você recomendaria?

Foi útil?

Solução

Você também pode querer investigar Cometa.

É usado por GTalk, Meebo e muitos outros aplicativos de bate-papo.Há alguns anos, quando eu estava experimentando isso, não havia muitas bibliotecas ou detalhes sobre a arquitetura do servidor para implementá-lo, mas parece que há muito mais coisas disponíveis agora.

Dê uma olhada no cometa projeto para mais informações técnicas.

Outras dicas

O que você recomendaria?

XMPP através de BOSH

Não há necessidade de inventar seu próprio formato de mensagem e protocolo de transporte quando outra pessoa o fez.Se você tentar, aos poucos ele se tornará tão complexo quanto o BOSH, mas sem o benefício de suporte ou padronização de bibliotecas de terceiros.

Se você não gosta da ideia de pesquisa HTTP, você pode ter um filme em Flash na página de bate-papo que tenha uma conexão constante com algum deamon no servidor, o filme em Flash invocaria funções JavaScript no cliente para atualizar o bate-papo à medida que novas mensagens aparecem.(A menos que você queira uma interface Flash para seu bate-papo.)

Você também pode querer dar uma olhada no Comet.

Achei que todo mundo usava o cometd para esse tipo de coisa.

BOSH é um padrão para transporte de XMPP por HTTP.Envolve o Comet para enviar dados ao cliente.

Existe um servidor muito bom para lidar com o envio de mensagens do servidor para o navegador (apelidado Cometa) - Orbitado.É facilmente integrado com outras tecnologias (Django, Rails, PHP etc.), assim como o memcached.

Você realmente deveria verificar isso se quiser lidar com cargas pesadas.Caso contrário, a pesquisa simples do Ajax é a melhor maneira.

O truque é perceber que o único momento em que seu aplicativo precisa invocar CGI no servidor é quando alguém diz alguma coisa.Para as enquetes regulares, enquete uma página estática que seu script CGI atualiza sempre que há um novo bate-papo.Use solicitações HEAD, compare os carimbos de data e hora com os vistos pela última vez e só faça um GET completo quando eles mudarem.Eu tenho um aplicativo de bate-papo simples e ingênuo implementado dessa maneira, e a carga e o uso da largura de banda são insignificantes para as poucas dezenas de usuários simultâneos que temos.

Eu fiz exatamente a mesma coisa há alguns meses e me diverti brincando com os conceitos.Na verdade eu usei o quadro para sempre técnica em vez de votação.

O código abaixo é meu arquivo js "comet" que contém os conceitos gerais necessários para obter uma configuração de "bate-papo em grupo".

function Comet(key) {

  var random = key;
  var title = 'Comet';
  var connection = false;
  var iframediv = false;
  var browserIsIE = /*@cc_on!@*/false;
  var blurStatus = false;
  var tmpframe = document.createElement('iframe');
  var nl = '\r\n';

  this.initialize = function() {
    if (browserIsIE) {
      connection = new ActiveXObject("htmlfile");
      connection.open();
      connection.write("<html>");
      connection.write("<script>document.domain = '"+document.domain+"'");
      connection.write("</html>");
      connection.close();
      iframediv = connection.createElement("div");
      connection.appendChild(iframediv);
      connection.parentWindow.comet = comet;
      iframediv.innerHTML = "<iframe id='comet_iframe' src='./comet.aspx?key="+random+"'></iframe>";
    } else {
      connection = document.createElement('iframe');
      connection.setAttribute('id', 'comet_iframe');
      iframediv = document.createElement('iframe');
      iframediv.setAttribute('src', './comet.aspx?key='+random);
      connection.appendChild(iframediv);
      document.body.appendChild(connection);
    }
  }

  // this function is called from the server to keep the connection alive
  this.keepAlive = function () {
    if (!browserIsIE) {
        mozillaHack();
    }
  }

  // this function is called from the server to update the client
  this.updateClient = function (value) {
    var outputDiv = document.getElementById('output');
    outputDiv.value = value + nl + outputDiv.value;
    if (blurStatus == true) {
        document.title = value;
    }
    if (!browserIsIE) {
        mozillaHack();
    }
  }

  this.onUnload = function() {
    if (connection) {
      // this will release the iframe to prevent problems with IE when reloading the page
      connection = false;
    }
  }

  this.toggleBlurStatus = function(bool) {
    blurStatus = bool;
  }

  this.resetTitle = function() {
    document.title = title;
  }

  function mozillaHack() {
    // this hack will fix the hour glass and loading status for Mozilla browsers
    document.body.appendChild(tmpframe);
    document.body.removeChild(tmpframe);
  }
}

Achei que todo mundo usava o cometd para esse tipo de coisa.

Eu concordo com João.Mas havia outra pergunta que não foi respondida.
Eu fiz isso, mas em vez de usar um banco de dados, usamos um arquivo simples, isso acabou paralisando o servidor, mas não foi até termos cerca de 450 usuários ativos, e se tivéssemos feito isso com um banco de dados, provavelmente teria funcionado melhorar.
Isso foi feito em uma conta de hospedagem básica da Godaddy.

Editar:Aliás, Godaddy parecia menos divertido quando recebi o telefonema.

Acho que a votação é a abordagem mais simples e recomendo isso primeiro.Se a carga se tornar um problema, comece a pesquisar técnicas mais complicadas.Uma boa discussão sobre os prós e os contras está aqui -http://www.infoq.com/news/2007/07/pushvspull
http://ajaxian.com/archives/a-report-on-push-versus-pull

Confira Fala.É um solução de código aberto para salas de bate-papo baseadas na Web que usam BOSH e XMPP nos bastidores.

Acabei de encontrar este post, é antigo, mas o conceito de pesquisa dá problemas para muita gente.Então vou colocar um exemplo de implementação aqui.Mas antes de lhe dar, devo dar um conselho que me deixou louco há algum tempo:

Ao fazer uma enquete, você deve cuidar do comportamento das sessões (condições da corrida).Para simplificar:se você abrir uma sessão, o arquivo da sessão será bloqueado até que a sessão seja fechada para evitar que 2 theads gravem dados diferentes nele.Portanto, se você precisar de uma sessão para verificar se um usuário está logado ou algo assim, sempre feche a sessão antes da votação.

Minha demonstração dá um exemplo de implementação de pesquisa em PHP.Não usarei um banco de dados, mas sim um arquivo.Ao clicar no botão polling, você entrará no loop e até que o arquivo seja modificado, você permanecerá polling.Ao preencher o formulário e clicar em Liberar, o que você digitou será salvo no arquivo.O tempo de modificação do arquivo será alterado e a votação será interrompida.

Dica:use uma ferramenta como Bug de fogo para ver o que aconteceu.

Agora vamos falar em uma linguagem melhor que o meu inglês:

<?php

    // For this demo
    if (file_exists('poll.txt') == false) {
        file_put_contents('poll.txt', '');
    }

    if (isset($_GET['poll'])) {

        // Don't forget to change the default time limit
        set_time_limit(120);

        date_default_timezone_set('Europe/Paris');
        $time = time();

        // We loop until you click on the "release" button...
        $poll = true;
        $number_of_tries = 1;
        while ($poll)
        {
            // Here we simulate a request (last mtime of file could be a creation/update_date field on a base)
            clearstatcache();
            $mtime = filemtime('poll.txt');

            if ($mtime > $time) {
                $result = htmlentities(file_get_contents('poll.txt'));
                $poll = false;
            }

            // Of course, else your polling will kill your resources!
            $number_of_tries++;
            sleep(1);
        }

        // Outputs result
        echo "Number of tries : {$number_of_tries}<br/>{$result}";
        die();
    }

    // Here we catch the release form
    if (isset($_GET['release']))
    {
        $data = '';
        if (isset($_GET['data'])) {
            $data = $_GET['data'];
        }
        file_put_contents('poll.txt', $data);
        die();
    }

?>

<!-- click this button to begin long-polling -->
<input id="poll" type="button" value="Click me to start polling" />

<br/><br/>

Give me some text here :
<br/>
<input id="data" type="text" />
<br/>

<!-- click this button to release long-polling -->
<input id="release" type="button" value="Click me to release polling" disabled="disabled" />

<br/><br/>

Result after releasing polling :
<div id="result"></div>

<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
<script type="text/javascript">

// Script to launch polling
$('#poll').click(function() {
    $('#poll').attr('disabled', 'disabled');
    $('#release').removeAttr('disabled');
    $.ajax({
        url: 'poll.php',
        data: {
            poll: 'yes' // sets our $_GET['poll']
        },
        success: function(data) {
            $('#result').html(data);
            $('#poll').removeAttr('disabled');
            $('#release').attr('disabled', 'disabled');
        }
    });
});

// Script to release polling
$('#release').click(function() {
    $.ajax({
        url: 'poll.php',
        data: {
            release: 'yes', // sets our $_GET['release']
            data: $('#data').val() // sets our $_GET['data']
        }
    });
});

</script>

Você pode experimentá-lo aqui

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top