Ir para conteúdo

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

Fernando Rafael

Conexão automática com ajax excede o limite de conexões do banco

Recommended Posts

Bom dia pessoal, estou com um problema que não sei ao certo como resolver, estou fazendo uma aplicação WEB que busca informações automáticas no banco de dados, mas com o passar do tempo o banco on-line para de funcionar e as seguintes mensagens são exibidas:

 

Warning: mysql_connect() [function.mysql-connect]: User '1396734_teste' has exceeded the 'max_connections_per_hour' resource (current value: 1500) in /srv/disk1/1396756/www/testes.eu.pn/conect.php on line 8

Warning: mysql_select_db() expects parameter 2 to be resource, boolean given in /srv/disk1/1396734/www/testes.eu.pn/conect.php on line 9
Erro ao conectar ao bando de dados

 

Bem, vi no manual do PHP e lá diz que quando uma conexão é aberta e depois é novamente usada o servidor mantêm a mesma porta de conexão, caso seja fechada ele libera outra. Mas ai e que ta, meu Java script através de funções Ajax chama um arquivo PHP que tem uma linha de conexão, depois executa o comando de busca e em seguida fecha a conexão (fiz os testes sem a linha em que ele fecha a conexão, mas o erro persiste), tenho suspeitas da quantidades de vezes que o arquivo é chamado (1 vez por segundo) sendo assim o comando de conexão e executado repetidasvezes, mas preciso que essas buscas aconteçam em no máximo 3 segundos.

 

outra suspeita seria o limite Maximo de conexões simultâneas, que seria teoricamente resolvido com o fechamento da conexão, mas não resolveu...

 

FUNCIONAMENTO DO MEU SITE:

 

1º PÁGINA WEB COM ARQUIVO JAVASCRIPT (USANDO FUNÇÕES AJAX PARA CHAMAR O BUSCA.PHP).

2º ARQUIVO BUSCA.PHP (CONECTA COM O BANCO, RETORNA O QUE ACHOU, FECHA A CONEXAO (TAMBÉM FIZ TESTE SEM A LINHA EM QUE É FECHADA A CONEXÃO)).

3º AQUIVO JAVASCRIPT (PEGA O CONTEUDO E POSTA NA PÁGINA E NOVAMENTE FAZ OUTRA BUSCA NO BUSCA.PHP).

 

É possível não ficar conectando e desconectando do banco durante essas buscas? ou seria uma outra forma de executar esses comandos?

 

 

OBS: na minha máquina local funciona perfeitamente mas na WEB esse erro persiste, o problema é comigo ou no servidor? caso seja no servidor o que devo fazer para resolver sem custos (hospedagem grátis)?

 

 

 

Compartilhar este post


Link para o post
Compartilhar em outros sites

dá uma olhada em websockets para vc usar no lugar do setInterval|Timeout.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Cara vou dar uma estudada sobre o assunto, notei que essa tecnologia é nova, então como faziam as antigas salas de bate-papo?

 

No meu site eu limitei para rodar no IE8 em diante, e essa tecnologia aparentemente não roda nele, existiria outra solução?

Compartilhar este post


Link para o post
Compartilhar em outros sites

Amigo consulte sua hospedagem, se é possivel aumentar o numero de conexões!

caso contrario controle essa conexão via codigo! verifique se você não abre ela em nenhuma outra parte do codigo!(sistema)

 

o mais correto neste caso seria vc usar o conceito singleton, criar uma classe e instaciala 1 única vez em seu sistema!

 

 

Abraços

Compartilhar este post


Link para o post
Compartilhar em outros sites

Creio que provavelmente, eram feitas com commet/long polling

Compartilhar este post


Link para o post
Compartilhar em outros sites

Fabio...

 

Em todo meu código a única parte em que é conectada no banco é quando o arquivo PHP é chamado pelo AJAX; aumentar o limite não seria uma boa solução pois so vai adiar o problema...

Preciso me conectar com o servidor uma única vez durante todo o tempo em que a página estiver aberta...

 

A solução do Willian é bem convincente mas não acho um exemplo prático ou entendivel pela minha pessoa...

 

Alguem tem um exemplo simples com ajax e PHP sobre WebSocKets ou similares?



Estive dando uma olhada em commet/long polling, comentado por Willian, é interessante o servidor reseber uma solicitação e nocaso de não houver dados ele aguardar para retornar, mas vi que o desempenho não é bom pois ainda sim ele fecha e abre a conexão, apenas faz isso com menos frequencia...



Uma boa fonte sobre WebSocKets:

 

http://www.alexandreporfirio.com/2013/08/01/artigos/voce-sabe-o-que-sao-websockets/

 

Quem tiver mais exemplos ou opniões podem acompanhar este tópico, pois assim que eu encontrar a solução postarei aqui e marcarei como resolvido (Respeitando os créditos de todos os que me ajudaram...)

Compartilhar este post


Link para o post
Compartilhar em outros sites

@Fernando Rafael,

 

Uma outra solução ainda melhor, é usar NodeJS. Ele sim foi "pensado" para esse tipo de requisição. No caso, essa parte do seu backend seria trocada de php para node.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Estive lendo todos os conceitos sobre WebSocKets e NodeJS, eles tem o que preciso para estabelecer uma conexão com o banco, mas não consigo entender sua prática (onde colocar ou implementar em meu código).

 

Alguém sabe onde encontrar arquivos prontos como exemplo?

 

 

Gostaria que fosse em PHP, java Script (com um pouco de ajax) e a conexão com um banco Mysql (pois domino bem essas linguagens).

Compartilhar este post


Link para o post
Compartilhar em outros sites

Bem, vi no manual do PHP e lá diz que quando uma conexão é aberta e depois é novamente usada o servidor mantêm a mesma porta de conexão, caso seja fechada ele libera outra. Mas ai e que ta, meu Java script através de funções Ajax chama um arquivo PHP que tem uma linha de conexão, depois executa o comando de busca e em seguida fecha a conexão (fiz os testes sem a linha em que ele fecha a conexão, mas o erro persiste), tenho suspeitas da quantidades de vezes que o arquivo é chamado (1 vez por segundo) sendo assim o comando de conexão e executado repetidasvezes, mas preciso que essas buscas aconteçam em no máximo 3 segundos.

 

Se não for uma conexão persistente, queira ou não, ela sempre será fechada ao final da execução do script.

 

Estive dando uma olhada em commet/long polling, comentado por Willian, é interessante o servidor reseber uma solicitação e nocaso de não houver dados ele aguardar para retornar, mas vi que o desempenho não é bom pois ainda sim ele fecha e abre a conexão, apenas faz isso com menos frequencia...

 

Falar que o desempenho não é bom, é relativo. O Facebook ainda usa long polling (dentre outras tecnologias) e ainda assim está feliz da vida.

 

Se a sua aplicação não for monstruosa grande, pode usar long polling com tranquilidade, até ter confiança, ou entender o código, para utilizar NodeJS ou WebSockets.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Gabriel...

 

Obrigado pela atenção, me ajudou muito com sua afirmação sobre as conexões, e sobre a dica do long polling.

 

Meu maior problema e que todos os desafios que encontro são novos pois sou iniciante, agradeço a todos os que estão me ajudando com este tópico, achei uma boa referência do long polling que também esta na minha lista de estudos:

 

http://carlosmaniero.blogspot.com.br/2012/07/php-long-polling.html

 

Darei continuidade com este post amanhã (04/01/14) ou domingo, responderei a todos...

abraços...

Compartilhar este post


Link para o post
Compartilhar em outros sites

eu sempre tive um problema no long polling quando o servidor dava timeout, então fiz algumas verificações de um código que encontrei anos atrás.

Passarei o código aqui que pode lhe ser útil. Eu utilizei o ajax da jQuery pra facilitar minha vida e diminuir a quantidade de código.

Arquivo getData.php

 

/** arquivo a ser verificado **/
$fileName = 'teste.txt';//deve estar na mesma pasta que este arquivo.

/** 
 *  tempo de sleep do sistema
 *  quanto maior o tempo, menos processamento é utilizado, 
 *  entretanto tem um maior o tempo de espera para a resposta
 **/
$sleepTime = 3;//segundos

/** tempo de execução definido para o script **/
$executionTime = 100;//segundos

/** caso não estiver em safe mode, pode realizar alterações no tempo de execução do script **/
if(!ini_get('safe_mode')) {
    
    /** verifica se o limite de tempo para execução de script definido no servidor é menor que o definido em $executionTime **/ 
    if(ini_get('max_execution_time') < $executionTime) {
        
        /** altera o limite de processamento para o tempo definido em $executionTime **/
        set_time_limit($executionTime);
    } else {
        
        /** caso o tempo já definido for maior, utiliza-se dele para os testes **/ 
        $executionTime = ini_get('max_execution_time');
    }
} else {
    
    /** caso servidor estiver em safe mode, recupera o tempo de execução definido pelo servidor **/
    $executionTime = ini_get('max_execution_time');
}

/** verificação do arquivo definido em $fileName **/
$lastModif = isset($_GET['timestamp']) ? $_GET['timestamp'] : filemtime($fileName);

$response = array();
$response['get_timestamp'] = isset($_GET['timestamp']) ? $_GET['timestamp'] : '';
$response['filemtime'] = filemtime($fileName);
$response['lastmodif'] = $lastModif;

$currentModif = filemtime($fileName);

$time = time();
while($lastModif == $currentModif) {
    sleep($sleepTime);
    
    /** remove o cache da função filetime, é irrelevante ao long polling **/
    clearstatcache();
    
    $currentModif = filemtime($fileName); 
    
    /** 
     * o long polling irá parar sempre que o arquivo for modificado
     * ou que o tempo de execução do script estiver próximo do fim do limite de tempo de exceução do servidor
     * Essa verificação evita que o PHP responda com timeout
     **/
    if((time() - $time) >= ($executionTime - ($sleepTime - 1))) {
        break;
    }   
} 

if($lastModif != $currentModif) {
    $response['msg'] = utf8_encode(file_get_contents($fileName));
}
$response['timestamp'] = $currentModif;
echo json_encode($response);




Script para execução do long polling:

 

var timestamp = null;

function waitForMsg() {
    $.ajax({
        type: 'GET',
        url: 'getData.php?timestamp=' + timestamp,
        async: true,
        cache: false,
        
        success: function(data) {
            var json = eval('(' + data + ')');
            
            if (json['msg'] != undefined) {
                $('body p').append(data);
            }
            
            timestamp = json['timestamp'];
            
            setTimeout('waitForMsg()' , 1000);
        },
        error: function(XMLHttpRequest , textStatus , errorThrow) {
            setTimeOut('waitForMsg()' , 15000);
        }
    } );
}

 




Chamada do script:

 

waitForMessage();

 

 

 

Depois é sór ir modificando o arquivo text.txt e verificar se está respondendo corretamente.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Mais um detalhe. Se o seu script PHP utilizar sessão, você precisará fechar a sessão, pois o apache não trabalha com mais de uma sessão aberta ao mesmo tempo.

 

Se você estiver usando o long polling, e tentar avançar para outra página, o navegador ficará tentando acessar o conteúdo até o script long polling tiver terminado.

 

Para evitar esse problema, pode usar a função session_write_close. Essa função escreve os dados da sessão e encerra a sessão. Assim, você ainda pode consultar os valores das variáveis na sessão.

Compartilhar este post


Link para o post
Compartilhar em outros sites

RE: Gabriel Heming

Estive dando uma olhada em seu código, mas não entendi como as informações serão inseridas no arquivo ".txt", na chamada da função não pede parâmetros. Um tempo atrás estudei sobre como criar arquivos com PHP e também como alterar-los, se esse for o caso poderei desenrolar pois notei que os comandos buscam alterações no arquivo, mas também não entendi o retorno, pois não vejo em seu código algum comando que seta os valores em algum elemento (pelo ID ou Return). SE não for pedir D+, vc poderia dar um exemplo funcional simples de seu código? caso seja melhor, pode me manda por e-mail: fernandocontatos2014@gmail.com.

 

Seu código me vai ser muito útil em um pequeno sistema de chat que estou fazendo, se vc autorizar o uso é claro..., mas ainda sim preciso resolver as consultas constante no banco de dados, pois preciso das informações no banco... Notei que na net não está muito claro sobre esse assunto, pretendo também deixar neste tópico a melhor solução sobre este tema, para os outros futuros pesquisadores...

 

 

Ops.... Valeu também pela dica do session_write_close...

Compartilhar este post


Link para o post
Compartilhar em outros sites

Na realidade, o exemplo já é funcional.

 

Esse script monitora as modificações no arquivo .txt. Se você for no arquivo (diretamente nele) e modificá-lo, o script informará que houve uma alteração no .txt e retornará o conteúdo dele.

 

Esse é o objeto principal do long polling, informar/observar/esperar mudanças, tanto no SGBD como em um .txt.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Entendi...

 

Tenho que sair agora, mas vou testar em meu código, e em breve postarei o resultado...

 

Ainda não parei para analisar detalhadamente o passo a passo de seu código...

 

Ma passando para a teoria, vamos ver o que está acontecendo:

 

1ª O script é chamado dando inicio a função de busca...

 

2ª O arquivo .PHP e acionado e sempre que existir uma busca ele retorna, caso contrário entra em um looping ate que surja outra resposta...

 

3ª O Script retorna para a página o conteúdo informado...

 

O ciclo se repete ate que o arquivo .PHP seja finalizado (já que o mesmo está em looping)...

 

DUVIDAS:

 

1º No meu caso, que é uma conexão com o banco, o PHP ficaria fazendo "select" ate encontrar um dado novo, sendo assim não iria quebrar o limite de conexões com o banco? Ou não já que o looping está sendo feito antes do fim da conexão...

 

2º Um looping feito no servidor é um sinal de um processo continuo, isso feito em grande escala (muitos usuários) não seria perigoso? Pois iria sobrecarregar o mesmo.

 

Volto a postar em breve... Abraços a todos....

Compartilhar este post


Link para o post
Compartilhar em outros sites

 

1ª O script é chamado dando inicio a função de busca...

 

2ª O arquivo .PHP e acionado e sempre que existir uma busca ele retorna, caso contrário entra em um looping ate que surja outra resposta...

 

3ª O Script retorna para a página o conteúdo informado...

Isso. Com uma adição ao segundo passo. O script informará sempre que houver uma resposta ou quando o limite de execução do arquivo estiver próximo. Caso chegar ao limite de execução do arquivo e não houver resposta, será retornado false, dando continuidade ao loop.

 

 

1º No meu caso, que é uma conexão com o banco, o PHP ficaria fazendo "select" ate encontrar um dado novo, sendo assim não iria quebrar o limite de conexões com o banco? Ou não já que o looping está sendo feito antes do fim da conexão...

O número de conexão com o banco de dados seria reduzido drasticamente, pois só haveria uma conexão por execução de script.

 

Imagine que o long polling tem execução de 30 segundos com uma pausa de 5 segundos entre cada consulta.

Passados os 30 segundos, você criou apenas uma conexão que realizou de 6 a 7 consultas (0, 5, 10, 15, 20, 25 e, possivelmente, 30 segundos). A última consulta pode não ocorrer, dependendo da demora das anteriores.

 

Já no seu antigo script, nos mesmos 30 segundos, caso rodasse a cada 5 segundos. seriam 6 conexões e 7 consultas.

 

Agora multiplcando por usuário, a cada usuário você terá uma conexão a cada 30 segundos (no long polling) ou 7 conexões (no antigo script).

 

 

2º Um looping feito no servidor é um sinal de um processo continuo, isso feito em grande escala (muitos usuários) não seria perigoso? Pois iria sobrecarregar o mesmo.

Esse loop é um pouco diferente do tradicional loop. Isso por causa da função sleep executada.

 

Como eu mencionei nos comentários, você pode definir o "sleep time" do long polling. É o tempo que o loop será parado entre cada consulta. Quanto menor o tempo, menor será o tempo de resposta e maior o uso do servidor.

 

Com esses dados, você pode trabalhar com o sleep time. Na maioria dos casos, eu uso um tempo entre 3-5 segundos, pois o tempo de resposta não precisa ser imediato e ainda assim existe uma boa folga no servidor.

 

Utilizamos aqui um servidor virtualizado, e está em constante acompanhamento. Roda uma aplicação, de medio porte, com vários acessos, com apenas 1GB de ram. O pico máximo de processamento foi 77%, e isso foi apenas um pico, a média é 20-30% de uso do servidor. Já o SGBD, que é separado, possui 2gb de ram e nunca ultrapassou 22%. Pico alcançado na execução de um script de importação de usuários, mais ou menos 800 usuários. Nesse exato momento, está utilizando 1% de processamento com 32 usuários ativos, todos os usuários utilizando long polling.

 

Por isso que eu comentei que, falar que o desempenho não é bom é relativo.

Compartilhar este post


Link para o post
Compartilhar em outros sites

RE. Gabriel Heming:

 

Gabriel, tentei fazer uns teste com seu código mas não funcionou...

 

segue o que fiz:

 

index.html

 

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Teste</title>

<script type="text/javascript">
var timestamp = null;

function waitForMsg() {
$.ajax({
type: 'GET',
url: 'getData.php?timestamp=' + timestamp,
async: true,
cache: false,

success: function(data) {
var json = eval('(' + data + ')');

if (json['msg'] != undefined) {
$('body p').append(data);
}

timestamp = json['timestamp'];

setTimeout('waitForMsg()' , 1000);
},
error: function(XMLHttpRequest , textStatus , errorThrow) {
setTimeOut('waitForMsg()' , 15000);
}
} );
}
</script>

</head>

<body onload= "waitForMsg()">

<p ID="p" NAME="p">
</p>

</body>
</html>

 

-----------------------------------------------------------//--------------------------------------------------------------------

 

getData.php

 

<?php
/** arquivo a ser verificado **/
$fileName = 'teste.txt';//deve estar na mesma pasta que este arquivo.

/**
* tempo de sleep do sistema
* quanto maior o tempo, menos processamento é utilizado,
* entretanto tem um maior o tempo de espera para a resposta
**/
$sleepTime = 3;//segundos

/** tempo de execução definido para o script **/
$executionTime = 100;//segundos

/** caso não estiver em safe mode, pode realizar alterações no tempo de execução do script **/
if(!ini_get('safe_mode')) {

/** verifica se o limite de tempo para execução de script definido no servidor é menor que o definido em $executionTime **/
if(ini_get('max_execution_time') < $executionTime) {

/** altera o limite de processamento para o tempo definido em $executionTime **/
set_time_limit($executionTime);
} else {

/** caso o tempo já definido for maior, utiliza-se dele para os testes **/
$executionTime = ini_get('max_execution_time');
}
} else {

/** caso servidor estiver em safe mode, recupera o tempo de execução definido pelo servidor **/
$executionTime = ini_get('max_execution_time');
}

/** verificação do arquivo definido em $fileName **/
$lastModif = isset($_GET['timestamp']) ? $_GET['timestamp'] : filemtime($fileName);

$response = array();
$response['get_timestamp'] = isset($_GET['timestamp']) ? $_GET['timestamp'] : '';
$response['filemtime'] = filemtime($fileName);
$response['lastmodif'] = $lastModif;

$currentModif = filemtime($fileName);

$time = time();
while($lastModif == $currentModif) {
sleep($sleepTime);

/** remove o cache da função filetime, é irrelevante ao long polling **/
clearstatcache();

$currentModif = filemtime($fileName);

/**
* o long polling irá parar sempre que o arquivo for modificado
* ou que o tempo de execução do script estiver próximo do fim do limite de tempo de exceução do servidor
* Essa verificação evita que o PHP responda com timeout
**/
if((time() - $time) >= ($executionTime - ($sleepTime - 1))) {
break;
}
}

if($lastModif != $currentModif) {
$response['msg'] = utf8_encode(file_get_contents($fileName));
}
$response['timestamp'] = $currentModif;
echo json_encode($response);

?>

 

-----------------------------------------------------------//--------------------------------------------------------------------

 

OBS: no seu exemplo a chamada da função está: waitForMessage(); alterei para waitForMsg(); (como está declarada a função).

 

O que pode estar errado? Preciso entender seu código para poder fazer as modificação para acessar o banco...

 

Abraços...

Compartilhar este post


Link para o post
Compartilhar em outros sites

Precisa incluir a jQuery junto. Não importa a versão.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Esse problema me parece que demora e trava, é justamente porque vc está efetuando uma consulta muito pesada,ou forçando um procedimento pesado no seu banco de dados, e provavelmente está dando estouro de processo. Eu reveria a forma que você está trazendo seus dados. Ou ao menos compactaria o seu banco, para que ele tenha mais desempenho...

Compartilhar este post


Link para o post
Compartilhar em outros sites

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.