Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Background Jobs - Ao infinito e além

Background Jobs - Ao infinito e além

Hugo Henrique

April 11, 2016
Tweet

More Decks by Hugo Henrique

Other Decks in Programming

Transcript

  1. A CHAVE DO PROBLEMA Fazer as requisições ficarem mais rápidas

    no processo PROCESSO DE CHECKOUT Até porque se um e-commerce demora em responder uma requisição, comprovadamente a porcentagem de abandono de carrinho aumenta, causando prejúizo.
  2. AMAZON Poderia perder $1.6 bilhão por ano se o tempo

    de carregamento aumentasse 0.5s http://www.fastcompany.com/1825005/how-one-second-could-cost-amazon-16-billion-sales
  3. GOOGLE Estimou que 8 milhões de buscas diárias deixariam de

    ser realizadas se o tempo de carregamento aumentasse apenas 0.04s http://www.fastcompany.com/1825005/how-one-second-could-cost-amazon-16-billion-sales
  4. Vamos simular um possível fluxo do checkout 1. Verifica no

    banco o usuário 2. Checa no gateway de pagamentos se está OK 3. Salva a compra no banco de dados 4. Notifica o usuário por e-mail 5. Altera o status do produto e indexa no buscador (ElasticSearch) 6. Gera métricas
  5. IMPREVISÍVEL algumas dessas "tarefas" são imprevisíveis por não dependerem de

    você, por exemplo a análise do pagamento junto ao gateway, que pode demorar muito, até mesmo gerar um timeout e prejudicar as outras tarefas dependentes.
  6. FLUXO SÍNCRONO 1 2 3 4 5 6 Essa etapa

    é responsável por validar no gateway de pagamento. TIMEOUT
  7. USAR BEANSTALK COM PHP composer require pda/pheanstalk Pheanstalk Pheanstalk is

    a pure PHP 5.3+ client for the beanstalkd workqueue. It has been actively developed, and used in production by many, since late 2008.
  8. 23 use Pheanstalk\Pheanstalk; $pheanstalk = new Pheanstalk('127.0.0.1'); // producer (queues

    jobs) $pheanstalk->useTube('testtube') ->put("job payload goes here\n"); // consumer (performs jobs) $job = $pheanstalk->watch('testtube') ->reserve(); echo $job->getData(); // to remove a job from queue $pheanstalk->delete($job);
  9. 25 BOAS PRÁTICAS $user = new User(); $job = ['method'

    => 'buy', 'user' => $user]; $queue->useTube('mailer')->put(json_encode($job)); $job = ['method' => 'buy', 'userId' => 123]; $queue->useTube('mailer')->put(json_encode($job));
  10. VOLTANDO AO CENÁRIO INICIAL <?php namespace MyStore\App; class PurchaseController {

    private $commandBus; public function postAction() { $command = new PurchaseProductCommand(42, 29); $this->commandBus->handle($command); } } <?php namespace MyStore\App; class PurchaseProductCommand { public $productId; public $userId; } class PurchaseProductHandler { // ... public function handle(PurchaseProductCommand $command) { $params = [ 'productId' => $command->productId, 'userId' => $command->userId ]; $this->gatewayWorker->validate('purchase.gateway', $params); $this->mailerWorker->send('purchase.mailer', $params); } }
  11. POR DENTRO DE UM WORKER <?php class MailerWorker { private

    $mailer; private $users; private $products; public function send(stdClass $params) { $user = $this->users->find($params->userId); $product = $this->products->find($params->productId); $this->mailer->send($user, $product); } // ... // ... public function execute($job) { $this->queue->watch('mailer_tube'); while($job = $queue->reserve()) { $job = json_decode($job, true); $this->{$job->method}($job->data); if ($outcome) { echo "done \n"; $queue->delete($job); } else { echo "failed \n"; $queue->bury($job); } } } }
  12. ESTATÍSTICAS $ telnet 127.0.0.1 11300 list-tubes - shows which tubes

    are available/in use use-tube [tube] - use a specific tube stats-tube [tube] - get the stats for a single tube peek-ready - shows the next job to be processed in the current tube