Ir para conteúdo

POWERED BY:

Arquivado

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

RSS iMasters

[Resolvido] Processamento distribuído em PHP utilizando Gearman -

Recommended Posts

Este artigo é a continuação do primeiro sobre Gearman, um framework genérico para distribuir o processamento de diferentes tarefas namesma máquina ou em outras máquinas de um cluster.

 

 

Iniciandoum servidor de trabalho Gearman com uma fila de job persistente

Iniciar um servidor de trabalho Gearman é fácil. Mas sevocê precisar que ele use uma fila de job persistente, serão necessários algunspassos adicionais.

 

Primeiro, você precisa configurar o armazenamento de fila. Por exemplo, se você desejausar MySQL como armazenamento de fila, você precisará criar uma tabela de fila como segue: 

 

CREATE TABLE gearman_queue(

`unique_key` VARCHAR(64) PRIMARY KEY,

`function_name` VARCHAR(255),

`priority` INT,

`data` LONGBLOB

);Você precisa então rodar o programa gerenciador doGearman, passando diversos parâmetrospara configurar a conexão ao servidor MySQL com o banco de dados que tem a tabela de fila:

 

./gearmand -q libdrizzle --libdrizzle-host=10.1.1.1 --libdrizzle-user=gearman --libdrizzle-password=secret --libdrizzle-db=some_db --libdrizzle-table=gearman_queue --libdrizzle-mysqlO Gearman também suporta armazenar filas persistentes emservidores Memcached e em bancos de dado SQLite.

 

 

Distribuindo aplicativos PHP ao configurar processos do PHP worker e do client

A primeira coisa que você devefazer é criar funções PHP que serão chamadas para executar os trabalhos doworker. Será necessário então registrar as funções para lidar com o trabalho em um servidor de trabalho Gearman. Finalmente será necessário começar a aceitar solicitações para quaisquer requisições de trabalho.

 

Aqui segue um simplesexemplo de um script de processo PHP worker:

 

<?php

 

$worker = new GearmanWorker();

$worker->addServer('localhost');

$worker->addServer('10.1.1.1');

 

$worker->addFunction("reverse", "reverse_fn");

 

while($worker->work())

{

 

if ($worker->returnCode() != GEARMAN_SUCCESS)

{

 

syslog(LOG_ERR, "return_code: " . $worker->returnCode());

break;

 

}

 

}

 

function reverse_fn($job)

{

 

$param = $job->workload();

return strrev($param);

 

}

?>Um script de trabalho do lado do cliente pode ser assim:

 

<?php

 

$client = new GearmanClient();

$client->addServer('localhost');

$client->addServer('10.1.1.1');

 

$return = $client->do('reverse', 'Hello World!');

var_dump($return);

 

?>Como se pode ver, é fácil implementar workers e clientscom o Gearman.  Naturalmente o exemploacima é bastante simplório. Vamos então ver um exemplo mais interessante: um código de varredura que é executado em segundo plano e oferece um relatório de status.

 

<?php

 

$worker = new GearmanWorker();

$worker->addServer('localhost');

$worker->addServer('10.1.1.1');

 

$worker->addFunction("crawler", "crawler_fn");

 

while($worker->work())

{

 

if ($worker->returnCode() != GEARMAN_SUCCESS)

{

 

syslog(LOG_ERR, "return_code: " . $worker->returnCode());

break;

 

}

 

}

 

function crawler_fn($job)

{

 

$param = $job->workload();

$urls = unserialize($param);

$count = count($urls);

for($i=0; $i < $count; $i++)

{

 

$url = $urls[$i];

$content = file_get_contents($url);

 

/* this function might save the retrieved content into a database */

 

save_content($url, $content);

$job->sendStatus($i, $count);

sleep(1); /* pause a little while */

 

}

 

}

?>Como se pode notar, a função worker não retorna nenhumvalor. Isso porque ela roda em segundo plano, e não há client esperando por umvalor de retorno.

 

O scriptclient poderia ser assim:

 

<?php

 

session_start();

$client = new GearmanClient();

$client->addServer('localhost');

$client->addServer('10.1.1.1');

 

$urls = array(

 

"http://www.google.com/",

"http://www.phpclasses.org/",

"http://crodas.org/"

 

);

 

$jobid = $client->doBackground('crawl', serialize($urls));

 

$_SESSION['jobid'] = $jobid;

$_SESSION['urls'] = $urls;

 

print "Your pages were queued for downloadingn";

 

?>O client não espera que o trabalho termine porquerodará em segundo plano. O identificador do trabalho é armazenado em uma sessãovariável, de forma que pode ser recuperado mais tarde, quando for necessáriochecar o status do trabalho, por exemplo enviando uma solicitação AJAX  a um script PHP, que pode ser assim:

 

<?php

 

session_start();

 

if (!isset($_SESSION['jobid']))

exit;

 

$client = new GearmanClient();

$client->addServer('localhost');

$client->addServer('10.1.1.1');

 

$status = $client->jobStatus($_SESSION['jobid']);

ob_start();

 

if ($status[0] == true

&& $status[1] == false)

{

 

echo json_encode( array('status' => 'The job is still on the queue.'));

 

}

elseif($status[0] == $status[1] && $status[1] == true)

{

 

$percent = $status[2] / $status[3] * 100;

echo json_encode( array('status' => 'Done $percent %'));

 

}

else

{

 

echo json_encode( array("status" => "Done"));

foreach ($_SESSION['urls']) as $url)

{

 

/* Do something with the crawled pages */

 

}

 

}

 

echo json_encode( array('results' => ob_get_clean()) );

 

?>É isso aí, muito simples! Há uma página que podeiniciar jobs assíncronos. Outra página pode mostrar o status de qualquerjob a qualquer tempo.

 

Até recentemente, faríamos uma coisa assim usando o crontab para agendartrabalhos e outros truques não muito legais.

 

 

Ideias de aplicativos

O Gearman poderia ser realmenteútil em aplicativos do mundo real. Seguem abaixo algumas ideias de possíveisaplicações:

 

 

Entregade newsletters

 

O envio de newsletters paramuitos assinantes é uma tarefa complicada. Consome uma quantidade de tempoconsiderável, proporcional ao número a ser enviado. Dessa forma, a entrega precisa ser feita em segundo plano, sempre que houvermuitos assinantes.

 

Como acima demonstrado, o Gearman serve bem a esse propósito, uma vez quepermite processamento em segundo plano, e é possível acompanhar como andam osencaminhamentos.

 

Primeiro é necessário criar e registrar um script worker job que enviará essanewsletter para uma lista de assinantes.

 

Poderíamos criar um processo principal, que poderia ser uma tarefa em segundo plano tambémcriada pelo Gearman, que geraria um conjunto de tarefas, atribuindo a elas umconjunto de e-mails para enviar.

 

Ele poderia detectar tentativas de entregas falhas, reenviando mensagens somentepara os endereços que registraram falhas, já que mensagens não devem ser enviadas mais de umavez para cada assinante.

 

Isso pode ser obtido enviando uma lista de identificadores de assinantes para oprocesso worker. O worker precisa buscar a informação em um banco de dados eatualizar o status do assinante que recebeu a mensagem.

 

 

Servidor de aplicação

 

O Gearman é muito rápido, uma vez que é escrito em C, e émulti-segmentado. É também tão seguro quanto o Apache, já que os workers rodamem processos separados, como no Apache no modo pre-fork. Acho que o Gearmanpode eventualmente ser usado como substituto do Apache, já que pode atuar comoum servidor HTTP.

 

Comecei a trabalhar em algo similar, até agora somente por prazer. É basicamenteum módulo Nginx que conversa diretamente com o Gearman. Tenciono implantá-locomo um servidor de serviço web e, se funcionar bem, por que não substituir oApache um dia desses?

 

Estou também escrevendo um módulo para servidor Kannel Open Source SMS para umacompanhia privada na qual trabalho. Esse módulo submete qualquer SMS que chegaa um worker Gearman.

 

http://www.kannel.org/

 

Map/Reduce

 

Um outro uso interessante para oGearman é escrever sua própria implementação do algoritmo Map/Reduce. Ele podeser usado para distribuir o processamento de grandes conjuntos de dados em umcluster de servidores.

 

Poderia ser interessante e até mesmo rápido, uma vez que ele poderia usar oGearman com um banco de dados local em vez de um sistema de arquivos distribuídos.

 

Para fazer isso, poderíamos configurar um processo master job worker quedistribuiria uma lista de valores de dados e o código-fonte para as funções Mape Reduce a serem aplicadas a todos os dados.

 

Isso é bastante simples de fazer,uma vez que o  PHP é uma linguagemdinâmica, e há a função eval() para executar o o código passado dinamicamente. ;-)

 

?

 

Texto original disponível em http://www.phpclasses.org/blog/post/108-Distributing-PHP-processing-with-Gearman.html

 

 

 

 

 

http://imasters.com.br/artigo/21387/php/processamento-distribuido-em-php-utilizando-gearman-parte-2

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.