Pergunta

Eu tenho uma tarefa agendada que executa um script em uma base regular (a cada hora). Este script faz alguma interação pesado com o banco de dados e sistema de arquivos e regularmente leva vários minutos para ser executado. O problema é, picos de CPU-uso do servidor enquanto o script está sendo executado e retarda as operações normais. Existe uma maneira de estrangular este processo para que ele leva mais tempo, mas não consome tantos recursos?

Eu olhei para diferentes opções de configuração para PHP, mas não parece haver qualquer que se encaixam minhas necessidades.

Configuração memory_limit no php.ini a algo menor faz com que meu objetos de dados ao transbordamento com bastante facilidade.

Já vi lugares similares onde as pessoas sugeriu o uso de sleep () em determinados pontos no script, mas isso não impede que o script de spiking do servidor.

A solução ideal seria uma maneira de dizer a Lâmpada (neste caso Wamp) pilha para usar apenas 10% de utilização da CPU máximo. Não estou preocupado em tudo sobre tempo de execução e preferiria que ele demorar mais que isso signifique salvar ciclos de CPU por segundo. Minha solução alternativa seria a instalação de um servidor diferente com a replicação do banco de dados para o cron poderia ir para a cidade, sem abrandar tudo o mais para baixo.

Ambiente: Windows Server 2k3, Apache 2.2.11, PHP 5.2.9, MySQL 5.1

Agradeço qualquer discernimento para esta situação.

EDIT: eu aprecio todas as respostas, mesmo os que são específicos de * nix. Ainda é cedo o suficiente na minha situação para mudar o ambiente de hospedagem. Esperemos que esta questão vai ajudar os outros, independentemente do sistema operacional.

Foi útil?

Solução

Este é um problema complicado. Se você estiver executando o script PHP via linha de comando, você pode definir a prioridade de agendamento do processo para baixo (start /low php.exe myscript.php eu acredito). Se o seu script PHP em si é realmente fazendo a maior parte do processamento que está comendo o seu CPU, este trabalho poder. No entanto, você disse que estão fazendo algum banco de dados pesado e sistema de arquivos interação, que esta solução não vai ajudar. Parece que há um MySQL dica "LOW_PRIORITY" para INSERT e UPDATE consultas que podem ajudá-lo lá, mas eu não tentei aqueles.

Outras dicas

Você pode definir processos no Windows a ser uma prioridade menor. eu não tenho certeza de como o processo está a ser expulso, mas se você definir o processo a ser uma prioridade baixa, o que quer que quer recursos da CPU vai buscá-los, se você definir a prioridade para ser realmente baixo.

Em UNIX (LAMP) eu consegui resolver o problema, verificando a carga do servidor antes de continuar o loop

function get_server_load($windows = 0) {
    $os = strtolower(PHP_OS);
    if(strpos($os, "win") === false) {
        if(file_exists("/proc/loadavg")) {
         $load = file_get_contents("/proc/loadavg");
         $load = explode(' ', $load);
         return $load;
        }
        elseif(function_exists("shell_exec")) {
         $load = explode(' ', `uptime`);
         return $load;
        }
        else {
         return "";
        }
    }
}

for(... ... ...){
    $data = get_server_load(); 
    if($data[0] < 0.2){
     // continue
    }else{
        sleep(1);
    }
}

Esta função deve funcionar também no Windows, mas não posso garantir isso. No linux que lhe dá de volta um array com a carga do passado 1 minuto, 5 minutos e 15 minutos

Além disso, considere começar seus scripts (se por CLI) com uma prioridade mais baixa (em Linux, use "bom")

Você também pode usar outros valores antes de continuar o ciclo, como o número de processos ativos Apache (você pode analisar o 127.0.0.1/server_status?auto página se você permitiu que o mod_status em httpd.conf), ou também a situação MySQL (conexões ativas?)

Você pode alterar a sua entrada cron para lançar o seu script usando agradável ?

Não é uma boa ideia para usar um servidor para servir os clientes e analisar os dados.

Então, se você está procurando uma solução final, fazer algumas redesenho de sua aplicação e descarregar a análise de dados a partir das interfaces e o banco de dados ao vivo para outro sistema dedicado a esta tarefa.

Mesmo se você pode conseguir acelerador o analisador, ele iria usar recursos preciosos de outra forma estaria disponível para atender os usuários.

Isto pode ser uma mudança difícil, mas pode valer a pena refatoração suas estruturas de dados em iteradores. Além disso, se você tem referências circulares em seu código, fornecer um método como clearReferences () que desactiva esses objetos. Este é um problema que é resolvido em PHP 5.3 pelo caminho.

Então, se você tem:

class Row
{
    protected $_table;

    public function __construct($table)
    {
        $this->_table = $table;
    }
}

class Table
{
    protected $_row;

    public function __construct()
    {
        $this->_row = new Row($this);
    }
}

Adicionar um clearReferences () para a classe Row:

class Row
{
    public function clearReferences()
    {
        $this->_table = null;
    }
}

Isso é tudo que eu posso vir acima com para o momento.

Eu tenho um monte de scripts que eu corro de cron de forma semelhante usando agradável:

0 * * * * agradável -n19 php myscript.php

Isso não vai ajudar a utilização RAM (somente mudando a maneira como o roteiro é escrito pode fazer isso), mas ele só usa a CPU que de outra forma seria ocioso.

EDIT: não ver que a questão envolvia um ambiente Windows, desculpe ... deixando isso em para os usuários * nix que têm o mesmo problema ..

Talvez o que o script está simplesmente tentando fazer demais de uma só vez. Será que fazer menos se ele correu três vezes por hora?

Outra solução poderia ser a configuração de um servidor adicional apenas para executar este tipo de processamento 'backend'. Este seria particularmente eficaz se não está colocando carga indevida no banco de dados, apenas o servidor web.

No entanto, uma outra abordagem para olhar é se o trabalho pode ser dividido em uma direção diferente. Esses tipos de roteiros muitas vezes têm algumas instruções SQL grandes que geram resultados usados ??para gerar uma série de instruções SQL pequenos. Se este último poderia ser posta de lado em algum lugar, eles podem ser executados contra o banco de dados como uma etapa posterior. Tal abordagem pode também permitem que você use uma consulta sem buffer para buscar os dados de pré-processamento que poderia reduzir significativamente o consumo de memória pelo código PHP.

Se você tem isso (Apache) executado como um serviço, você pode alterar a prioridade ajustes no controle Win centro / serviços. O uso da CPU vai pico de qualquer maneira, mas outros programas será preferido pelo programador. Também tente colocar o banco de dados / servidor em um hd diferente do seu Aplicações.

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