PHP e seus demônios
Upcoming SlideShare
Loading in...5
×
 

PHP e seus demônios

on

  • 1,694 views

Criando Daemons em PHP

Criando Daemons em PHP

Macro tópicos
• Forks
• Sinais
• Daemons
• Spawn
• Zombies
• IPC

Statistics

Views

Total Views
1,694
Views on SlideShare
1,664
Embed Views
30

Actions

Likes
16
Downloads
19
Comments
0

4 Embeds 30

https://twitter.com 23
https://www.linkedin.com 4
http://www.linkedin.com 2
https://drive.jolicloud.com 1

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

PHP e seus demônios PHP e seus demônios Presentation Transcript

  • PHP e seus demônios CRIANDO  DAEMONS  EM  PHP
  • PALESTRANTE 2
  • Henrique  Moody • Desenvolvedor  web  com  foco  em  PHP  desde   2007   • Usuário  assíduo  de  Linux  desde  2008   • Zend  Certified  Engineer  5.3  desde  2011   • Contribui  com  vários  projetos  Open  Source     • Líder  Técnico   • Desenvolvedor  PHP  Senior 3
  • PALESTRA 4
  • PHP  e  seus  demônios • • • • • • Forks   Sinais   Daemons   Spawn   Zombies   IPC 5
  • FORKS 6
  • • Em  sistemas  operacionais  Unix-­‐like  fork  é  uma   operação  em  que  um  processo  cria  uma  cópia  de   si  mesmo   • Fork  é  uma  forma  de  um  processo  executar   outro  ou  outros  processos  a  partir  de  si  mesmo   • Quando  a  cópia  do  processo  é  criada  essa  cópia   é  chamada  de  processo  filho  tornando  o   processo  original  o  processo  pai   • No  PHP  é  necessária  a  extensão  PCNTL   habilitada  e  extremamente  recomendável  a   extensão  POSIX  também  habilitada 7
  • PCNTL  (Process  Control) • Deve  ser  habilitada  no  momento  da  compilação   do  PHP  (——enable-pcntl)   • Suportada  apenas  para  sistemas  Unix-­‐like   • Não  funciona  em  web  servers   • Cria  e  gerencia  processos  e  sinais 8
  • POSIX  (Portable  Operating  System   Interface) • Habilitada  por  padrão  na  compilação  do  PHP   • Suportada  apenas  para  sistemas  Unix-­‐like   • Fornece  uma  API  padrão  para  desenvolvimento   em  sistemas  Unix-­‐like   • Gerencia  processos,  sessões,  grupos,  usuários  e   arquivos  de  sistemas  Unix-­‐like 9
  • Funcionamento • A  função  pcntl_fork()  criará  o  fork  e  retornará  um  valor   diferente  para  cada  processo  (pai  e  filho)   • Caso  pcntl_fork()  retorne  -1  ocorreu  um  erro  no  fork   • Caso  pcntl_fork()  retorne  0  houve  sucesso  no  fork.  O   processo  atual  é  o  filho   • Caso  pcntl_fork()  retorne  um  número  maior  do  que  0   houve  sucesso  no  fork.  O  processo  atual  é  o  pai  e  o  retorno   de  pcntl_fork()  é  o  PID  do  filho   • Nada  impede  um  processo  filho  criar  forks  de  si  mesmo   • Todas  as  variáveis  inicializadas  no  processo  pai  estarão   disponíveis  para  os  filhos 10
  • Forks/pcntl.php <?php $pid = pcntl_fork(); if ($pid == -1) { // Falha na criação do fork echo 'Falha na criação do fork' . PHP_EOL; ! } elseif ($pid > 0) { // Sou o processo pai echo 'Fork criado com sucesso sob o PID ' . $pid . PHP_EOL; ! } else { // Sou o processo filho, em background mail('vagrant@localhost', 'Lorem ipsum', 'Dolor sit amet'); } 11
  • Forks/pcntl+posix.php <?php $pid = pcntl_fork(); if ($pid == -1) { // Falha na criação do fork echo 'Falha na criação do fork' . PHP_EOL; ! } elseif ($pid > 0) { // Sou o processo pai echo 'Fork criado com sucesso sob o PID ' . $pid . PHP_EOL; ! } else { // Sou o processo filho, em background if (0 !== posix_getuid()) { error_log('É necessário ser root para alterar informações do processo'); exit(2); } ! ! ! if (! posix_setuid(1000)) { error_log('Não foi possível definir o usuário do processo como 1000'); exit(3); } if (! posix_setgid(1000)) { error_log('Não foi possível definir o grupo do processo como 1000'); exit(4); } mail('vagrant@localhost', 'Lorem ipsum', 'Dolor sit amet'); } 12
  • SINAIS 13
  • • Em  sistemas  Unix-­‐like,  um  sinal  é  uma   notificação  de  software  a  um  processo  da   ocorrência  de  um  evento   • Um  sinal  é  gerado  pelo  SO  quando  o  evento  que   causa  o  sinal  acontece   • Existem  vários  sinais  que  podem  ser  enviados   para  um  processo,  alguns  deles  podem  ser   manipulados  pela  aplicação  já  outros  apenas   pelo  próprio  SO   • Podemos  enviar  através  da  função  posix_kill()   • Podemos  definir  um  callback  para  manipular   sinais  através  da  função  pcntl_signal() 14
  • Lista  de  constantes  de  sinais  do  PHP • SIGABRT • SIGIOT • SIGTTIN • SIGALRM • SIGKILL • SIGTTOU • SIGBABY • SIGPIPE • SIGURG • SIGBUS • SIGPROF • SIGUSR1 • SIGCHLD • SIGQUIT • SIGUSR2 • SIGCONT • SIGSEGV • SIGVTALRM • SIGFPE • SIGSTOP • SIGWINCH • SIGHUP • SIGSYS • SIGXCPU • SIGILL • SIGTERM • SIGXFSZ • SIGINT • SIGTRAP • SIGIO • SIGTSTP 15
  • Mais  comuns • SIGHUP:  enviado  quando  o  sessão  (terminal)  do  processo  é  fechada   • • • • • • • Pode  ser  interceptado   SIGINT:  enviado  quando  um  se  pretende  interromper  o  processo   • Pode  ser  interceptado   • Pode  ser  enviado  via  teclado,  com  Control-C,  e  em  alguns  sistemas  com  delete  ou  break   SIGTSTP:  enviado  quando  se  pretende  pausar  o  processo   • Pode  ser  interceptado   • Pode  ser  enviado  via  teclado,  com  Control-Z SIGCONT:  enviado  quando  se  pretende  despausar  o  processo  após  SIGTSTP   • Pode  ser  interceptado   SIGTERM:  enviado  quando  se  pretende  terminar  o  processo  (amigavelmente).   • Pode  ser  interceptado   SIGQUIT:  enviado  quando  se  pretende  encerrar  o  processo  e  obter  um  dump  de  memória.   • Pode  ser  interceptado   • Pode  ser  enviado  via  teclado,  com  Control-   SIGKILL:  enviado  quando  se  pretende  encerrar  imediatamente  o  processo   • Não  ser  interceptado 16
  • Sinais/envio.php <?php ! // Envia um 0 (verifica se o PID é válido ou não) posix_kill($pid, 0); ! // Envia um SIGUSR1 (User-defined signal 1) posix_kill($pid, SIGUSR1); ! // Envia um SIGSTOP (pausa a execução do processo) posix_kill($pid, SIGSTOP); ! // Envia um SIGCONT (continua a execução do processo) posix_kill($pid, SIGCONT); ! // Envia um SIGKILL (mata instantâneamente o processo) posix_kill($pid, SIGKILL); 17
  • Sinais/manipulacao.php <?php ! declare(ticks = 1); function signalHandler($signal) { switch ($signal) { case SIGQUIT; error_log('Me fecharam com o teclado (Control-)'); exit(1); case SIGINT: error_log('Me interromperam com o teclado (Control-C)'); exit(1); case SIGHUP: error_log('Fecharam meu terminal'); exit(1); case SIGTERM: error_log('Me pediram para me matar'); exit(0); } } ! pcntl_signal(SIGQUIT, 'signalHandler'); pcntl_signal(SIGINT, 'signalHandler'); pcntl_signal(SIGHUP, 'signalHandler'); pcntl_signal(SIGTERM, 'signalHandler'); pcntl_signal(SIGTSTP, 'signalHandler'); pcntl_signal(SIGTSTP, SIG_IGN); // SIG_IGN faz com que SIGTSTP seja ignorado pcntl_signal(SIGCONT, SIG_IGN); // SIG_IGN faz com que SIGCONT seja ignorado ! echo 'PID: ' . getmypid() . PHP_EOL; while (true) { echo date('Y-m-d H:i:s') . PHP_EOL; sleep(1); } 18
  • DAEMONS 19
  • • Acrônimo  de  Disk  And  Execution  MONitor  (Monitor   de  Execução  e  de  Disco)   • Em  Unix  e  outros  sistemas  operacionais  multi-­‐ tarefas  é  um  programa  de  computador  que  roda  de   forma  independente  em  background,  ao  invés  de   ser  controlado  diretamente  por  um  usuário   • Em  um  ambiente  Unix,  o  processo  pai  de  um   daemon  é  normalmente  (mas  nem  sempre)  o   processo  init  (PID=1)   • Alguns  exemplos  de  daemons  são:  MySQL  Server,   Apache  Server,  Nginx  Server,  Cron   • Muitas  vezes,  um  programa  se  torna  um  daemon   através  de  forking 20
  • CRIANDO  UM  DAEMON 21
  • Passo  a  passo 1. Fork  off  and  die   2. Máscara  de  criação  dos  arquivos   3. Entradas  e  saídas   4. Logging   5. Desligar  sessão  (SID)   6. Working  directory   7. Locking 22
  • Fork  off  and  die • Você  apenas  criará  o  fork  e  encerrará   imediatamente  o  processo  pai   • O  processo  filho  será  o  daemon,  executando  em   background 23
  • Daemons/fork.php <?php $pid = pcntl_fork(); if ($pid == -1) { echo 'Falha na criação do fork' . PHP_EOL; exit(2); ! } elseif ($pid > 0) { echo 'Daemon inicializado (PID: ' . $pid . ').' . PHP_EOL; exit(); } ! while (true) { mail('vagrant@localhost', 'Lorem ipsum', 'Dolor sit amet'); sleep(2); } 24
  • Máscara  de  criação  dos  arquivos • Para  garantir  que  você  possa  ler  e  escrever   arquivos  restaure  o  umask  para  o  padrão  do   sistema,  com  umask(0) 25
  • Daemons/fork+umask.php <?php $pid = pcntl_fork(); if ($pid == -1) { echo 'Falha na criação do fork' . PHP_EOL; exit(2); ! } elseif ($pid > 0) { echo 'Daemon inicializado (PID: ' . $pid . ').' . PHP_EOL; exit(); } ! umask(0); ! while (true) { mail('vagrant@localhost', 'Lorem ipsum', 'Dolor sit amet'); sleep(2); } 26
  • Entradas  e  saídas • O  daemon  não  possui  interação  com  o  usuário,   portanto  você  não  deve  permitir  que  os  métodos   de  entrada  e  saída  (STDIN,  STDOUT  e  STDERR)   sejam  utilizados   • Você  pode  fechar  STDIN,  STDOUT  e  STDERR,  mas   caso  você  esteja  utilizando  essas  constantes  com   certeza  você  terá  problemas   • Você  também  pode  utilizar  as  funções  ob_*  para   evitar  outputs 27
  • Daemons/fork+umask+file_descriptors.php <?php $pid = pcntl_fork(); if ($pid == -1) { echo 'Falha na criação do fork' . PHP_EOL; exit(2); ! } elseif ($pid > 0) { echo 'Daemon inicializado (PID: ' . $pid . ').' . PHP_EOL; exit(); } ! umask(0); ! fclose(STDIN); fclose(STDOUT); fclose(STDERR); ! $fd0 = fopen('/dev/null', 'r'); $fd1 = fopen('/tmp/psd.log', 'a'); $fd2 = fopen('php://stdout', 'a'); ! while (true) { mail('vagrant@localhost', 'Lorem ipsum', 'Dolor sit amet'); sleep(2); } 28
  • Logging • Visto  que  não  interação  entre  o  daemon  e  o  usuário,   logs  são  uma  ótima  forma  de  obter  feedback  de  um   daemon   • Você  pode  fazer  logs  em:   ‣ Arquivos   ‣ Bancos  de  dados  relacionais   ‣ Bancos  de  dados  não-­‐relacionais   ‣ Message  Queue   ‣ Syslog   ‣… 29
  • Daemons/fork+umask+file_descriptors+logging.php <?php $pid = pcntl_fork(); if ($pid == -1) { echo 'Falha na criação do fork' . PHP_EOL; exit(2); ! } elseif ($pid > 0) { echo 'Daemon inicializado (PID: ' . $pid . ').' . PHP_EOL; exit(); } ! umask(0); ! fclose(STDIN); fclose(STDOUT); fclose(STDERR); ! $fd0 = fopen('/dev/null', 'r'); $fd1 = fopen('/tmp/psd.log', 'a'); $fd2 = fopen('php://stdout', 'a'); ! ! openlog('PSD', LOG_PID | LOG_CONS, LOG_LOCAL0); while (true) { syslog(LOG_DEBUG, 'Envio de email iniciando'); $sent = mail('vagrant@localhost', 'Lorem ipsum', 'Lorem ipsum dolor sit amet'); if (true === $sent) { syslog(LOG_DEBUG, 'Envio de email terminado sucesso'); continue; } syslog(LOG_ERR, 'Falha ao enviar email'); sleep(2); } closelog(); 30
  • Desligar  sessão  (SID) • Mesmo  que  o  processo  filho  seja  executado  em   background,  não  dependendo  do  processo  pai,  eles  estão   na  mesma  sessão   • Quando  a  sessão  terminar  (o  terminal  fechado,  por   exemplo),  o  sistema  matará  o  processo  filho   • A  função  posix_setsid()  cria  uma  nova  sessão  para  o   processo  filho,  desvinculando-­‐o  do  processo  pai  e  sua   sessão   • O  processo  filho  passa  a  ter  o  init  (processo  inicial  que   carrega  todos  os  outros  processos  do  sistema)  como   processo  pai 31
  • Daemons/fork+umask+file_descriptors+logging+detach_sid.php <?php $pid = pcntl_fork(); if ($pid == -1) { echo 'Falha na criação do fork' . PHP_EOL; exit(2); ! } elseif ($pid > 0) { echo 'Daemon inicializado (PID: ' . $pid . ').' . PHP_EOL; exit(); } ! umask(0); ! fclose(STDIN); fclose(STDOUT); fclose(STDERR); ! $fd0 = fopen('/dev/null', 'r'); $fd1 = fopen('/tmp/psd.log', 'a'); $fd2 = fopen('php://stdout', 'a'); ! openlog('PSD', LOG_PID | LOG_CONS, LOG_LOCAL0); ! if (posix_setsid() < 0) { syslog(LOG_ERR, 'Não foi possível desvincular processo de sua sessão'); exit(2); } ! while (true) { /** Payload **/ } closelog(); 32
  • Working  directory • O  filho  herda  o  working  directory  do  pai   • Este  working  directory  pode  ser  um  volume   montado  que  pode  ser  desmontado  em  algum   momento   • Para  desmontar  um  volume  o  sistema  irá  matar   qualquer  processo  que  ainda  está  usando  o   diretório 33
  • Daemons/fork+umask+file_descriptors+logging+detach_sid+chdir.php <?php $pid = pcntl_fork(); if ($pid == -1) { echo 'Falha na criação do fork' . PHP_EOL; exit(2); ! } elseif ($pid > 0) { echo 'Daemon inicializado (PID: ' . $pid . ').' . PHP_EOL; exit(); } ! umask(0); ! fclose(STDIN); fclose(STDOUT); fclose(STDERR); ! $fd0 = fopen('/dev/null', 'r'); $fd1 = fopen('/tmp/psd.log', 'a'); $fd2 = fopen('php://stdout', 'a'); ! openlog('PSD', LOG_PID | LOG_CONS, LOG_LOCAL0); ! if (posix_setsid() < 0) { syslog(LOG_ERR, 'Não foi possível desvincular processo de sua sessão'); exit(2); } ! chdir(__DIR__); ! while (true) { /** Payload **/ } closelog(); 34
  • pidfile • Contém  o  PID  do  daemon   • Impede  que  o  daemon  seja  executado  mais  de   uma  vez 35
  • Generated  by  https://www.lucidchart.com 36
  • Daemons/fork+umask+file_descriptors+logging+detach_sid+chdir+pidfile.php <?php ! $pidfile = '/var/run/psd/daemon.pid'; if (file_exists($pidfile)) { $daemonPid = (int) file_get_contents($pidfile); if (true === posix_kill($daemonPid, 0)) { echo 'Daemon já em execução (PID ' . $daemonPid . ').' . PHP_EOL; exit(2); } unlink($pidfile); } ! $pidfileHandler ! = fopen($pidfile, 'w+'); if (! flock($pidfileHandler, LOCK_EX | LOCK_NB)) { echo 'Falha ao bloquear acesso externo ao pidfile' . PHP_EOL; exit(3); } ! $pid = pcntl_fork(); if ($pid == -1) { echo 'Falha na criação do fork' . PHP_EOL; exit(4); ! } elseif ($pid > 0) { if (! fwrite($pidfileHandler, $pid)) { echo 'Falha ao escrever PID no pidfile' . PHP_EOL; exit(5); } ! echo 'Daemon inicializado (PID: ' . $pid . ').' . PHP_EOL; exit(); } ! register_shutdown_function('unlink', ! $pidfile); // Corpo do daemon 37
  • SPAWN 38
  • • Muito  utilizado  no  processamento  de  filas   quando  você  precisa  de  processos  concorrentes   • Um  processo  pode  criar  outros  processos  e   delegar  tarefas  para  cada  um  deles   • Esse  recurso  muitas  vezes  é  confundido  com   multi-­‐threading,  mas  não  é  isso.  O  PHP  não   possui  suporte  a  este  recurso  mas  existe  uma   extensão  PECL  para  isso   • Geralmente  os  processos  pai  são  daemons   sendo  seus  filhos  workers   • Você  não  pode  alterar  o  SID  dos  filhos  pois  você   precisa  deles  na  mesma  sessão  do  processo  pai 39
  • Spawn/exemplo.php <?php $pid = pcntl...// Fluxo normal do daemon ! $childrenLimit = 10; $childrenPids = array(); while (true) { if (count($childrenPids) >= $childrenLimit) { $firstChildPid = array_shift($childrenPids); pcntl_waitpid($firstChildPid, $status); } ! ! ! ! $childPid = pcntl_fork(); if ($childPid == -1) { syslog(LOG_ERR, 'Falha ao criar filho'); continue; } if ($childPid > 0) { $childrenPids[] = $childPid; continue; } syslog(LOG_DEBUG, 'Envio de email iniciando'); $sent = mail('vagrant@localhost', 'Lorem ipsum', 'Lorem ipsum dolor sit amet'); if (true === $sent) { syslog(LOG_DEBUG, 'Envio de email terminado sucesso'); exit(0); } syslog(LOG_ERR, 'Falha ao enviar email'); exit(3); } closelog(); 40
  • ZOMBIES 41
  • • Um  processo  zombie  é  um  processo  que  já  foi   completamente  executado  mas  ainda  se  encontra  na  tabela   de  processos  do  SO,  permitindo  que  o  processo  que  o  criou   leia  o  seu  valor  de  saída   • Quando  um  processo  termina,  a  memória  a  ele  associada  é   libertada,  no  entanto  a  informação  sobre  esse  processo   continua  disponível,  embora  ele  já  não  exista   • Normalmente  os  processos  zombie  não  duram  muito  tempo   já  que  o  sinal  SIGCHLD  é  emitido  quando  ele  entra  nesse   estado,  possibilitando  ao  processo  pai  saber  quando  isso   acontece  para  ler  as  informações  necessárias   • Se  o  processo  pai  explicitamente  ignora  o  SIGCHLD  definindo   seu  manipulador  como  SIG_IGN  todos  as  informações  de   término  dos  processos  filhos  serão  descartadas  e  os   processos  zombies  continuarão  na  tabela 42
  • Zombies/reaper.php <?php ! function reaper($signal) { if ($signal != SIGCHLD) { return; } ! while (pcntl_waitpid(-1, $status, WNOHANG | WUNTRACED) > 0) { usleep(1000); } } ! pcntl_signal(SIGCHLD, 'reaper'); 43
  • Inter-­‐Process  Communication IPC 44
  • • Cada  processo  possui  um  contexto  de  execução  próprio.  Um   processo  não  tem  conhecimento  do  contexto  de  outro   processo  sendo  assim  os  processos  não  conseguem  transferir   informação  entre  si   • Inter-­‐Process  Communication  (IPC),  é  o  grupo  de  mecanismos   que  permite  aos  processos  transferirem  informação  entre  si   • Usando  IPC  um  processo  pai  consegue  obter  informações   precisar  de  seus  filhos   • Para  IPC  podemos  utilizar:   ‣ Arquivos   ‣ Filas  de  mensagens   ‣ Memória  Compartilhada   ‣ Sinais   ‣ Par  de  Sockets   ‣… 45
  • Arquivos • Você  pode  escrever  dados  em  um  processo  e  ler   em  outro  processo,  desde  que  ambos  tenham   permissão  de  leitura   • Nome  do  arquivo  deve  ser  único 46
  • IPC/file.php <?php ! $filename = '/tmp/' . getmypid() . '.ipc'; if (! is_file($filename)) { touch($filename); } ! $dataWritten = 'PHP e seus Demônios'; if (false === file_put_contents($filename, $dataWritten)) { echo 'Falha ao gravar dados no arquivo' . PHP_EOL; exit(2); } ! $dataGiven = file_get_contents($filename); if (false === $dataGiven) { echo 'Falha ao ler dados no arquivo' . PHP_EOL; exit(3); } ! echo 'Dado lido no arquivo: ' . $dataGiven . PHP_EOL; ! if (! unlink($filename)) { echo 'Falha ao tentar remover o arquivo' . PHP_EOL; exit(3); } 47
  • Memória  compartilhada • É  um  fácil  caminho  para  usar  funções  que  permitem  o  PHP  ler,   escrever,  criar  e  deletar  segmentos  de  memória  compartilhada  UNIX   • O  PHP  possui  duas  API’s,  as  funções  shmop_*  e  shm_*:     • Para  habilitar  as  funções    shmop_*    é  preciso  compilar  o  PHP  com  a   opção  --enable-shmop  do  configure   • Para  habilitar  as  funções    shm_*    é  preciso  compilar  o  PHP  com  a   opção  --enable-sysvshm  do  configure   • Funciona  basicamente  com  uma  chave,  por  ela  você  pode  ler  e   escrever  dados  na  memória   • Utilize  o  comando  ipcs  para  monitorar  os  seguimentos  criados  e   ipcrm shm ID  para  remover  seguimentos  (você  também  pode  usar   ipcmk  para  criar  seguimentos) 48
  • IPC/shmop.php <?php ! $key = getmypid(); $flag = 'c'; $permission = 0644; $memorySize = 1024; ! $shmId = shmop_open($key, $flag, $permission, $memorySize); if (! $shmId) { echo 'Não foi possível criar o segmento de memória' . PHP_EOL; exit(1); } ! $stringWritten = 'PHP e seus demônios'; $shmBytesWritten = shmop_write($shmId, $stringWritten, 0); if ($shmBytesWritten != strlen($stringWritten)) { echo 'Não foi possível gravar o dado e com seu tamanho correto' . PHP_EOL; exit(2); } ! $stringRead = shmop_read($shmId, 0, $memorySize); if (! $stringRead) { echo 'Não foi possível ler o dado na memória compartilhada' . PHP_EOL; exit(2); } ! echo 'Dado lido na memória compartilhada foi: ' . $stringRead . PHP_EOL; ! if (! shmop_delete($shmId)) { echo 'Não foi possível marcar o bloco de memória compartilhada para remoção'; } ! shmop_close($shmId); 49
  • IPC/shm.php <?php ! $key = getmypid(); $permission = 0644; $memorySize = 1024; ! $shmId = shm_attach($key, $memorySize, $permission); if (! $shmId) { echo 'Falha ao criar o segmento de memória' . PHP_EOL; exit(1); } ! $stringWritten = 'PHP e seus demônios'; if (! shm_put_var($shmId, 1, $stringWritten)) { echo 'Falha ao gravar o dado na memória compartilhada' . PHP_EOL; exit(2); } ! if (! shm_has_var($shmId, 1)) { echo 'Nenhum dado na chave 1 foi encontrado na memória' . PHP_EOL; exit(2); } ! $stringRead = shm_get_var($shmId, 1); if (! $stringRead) { echo 'Falha ao ler o dado da chave 1 na memória compartilhada' . PHP_EOL; exit(2); } ! echo 'Dado lido na memória compartilhada foi: ' . $stringRead . PHP_EOL; ! if (! shm_remove($shmId)) { echo 'Falha ao remover do bloco de memória compartilhada'; } ! if (! shm_detach($shmId)) { echo 'Falha ao se desconectar do bloco de memória compartilhada'; } 50
  • Filas  de  mensagens • O  PHP  possui  suporte  a  filas  de  mensagens  do     • Para  habilitar  as  funções    msg_*    é  preciso   compilar  o  PHP  com  a  opção  --enable-sysvmsg   do  configure   • Utilize  o  comando  ipcs  para  monitorar  os   seguimentos  criados  e  ipcrm msg ID  para   remover  seguimentos  (você  também  pode  usar   ipcmk  para  criar  seguimentos) 51
  • IPC/msg.php <?php ! $key = getmypid(); $messageQueueId = msg_get_queue($key); ! $messageSent = 'PHP e seus demônios'; $messageWasSent = msg_send($messageQueueId, 2, $messageSent); if (! $messageWasSent) { echo 'Falha ao enviar mensagem' . PHP_EOL; exit(2); } ! if (! msg_receive($messageQueueId, 2, $msgType, 1024, $messageReceived, true, 0, $error)) { echo 'Falha ao ler mensagem' . $error . PHP_EOL; exit(3); } echo 'Mensagem recebida: ' . $messageReceived . PHP_EOL; ! if (! msg_remove_queue($messageQueueId)) { echo 'Falha ao remover fila de mensagens'. PHP_EOL; exit(3); } 52
  • Par  de  sockets • Dois  sockets  conectados  armazenados  em  um   array   • Conexão  de  duas  vias,  as  mensagens  são   entregues  no  mesmo  instante 53
  • IPC/msg.php <?php ! $sockets = array(); ! if (false === socket_create_pair(AF_UNIX, SOCK_STREAM, 0, $sockets)) { echo 'Falha ao criar par de sockets: ' . socket_strerror(socket_last_error()) . PHP_EOL; } ! $pid = pcntl_fork(); if ($pid == -1) { echo 'Falha na criação do fork' . PHP_EOL; } elseif ($pid > 0) { ! ! ! socket_close($sockets[0]); $messageWritten = 'Mensagem enviada pelo processo pai'; if (false === socket_write($sockets[1], $messageWritten, strlen($messageWritten))) { echo 'Falha ao escrever dados no socket: ' . socket_strerror(socket_last_error($sockets)); exit(3); } $messageGiven = socket_read($sockets[1], 1024, PHP_BINARY_READ); echo 'Mensagem no processo pai: ' . "t" . $messageGiven . PHP_EOL; socket_close($sockets[1]); ! } else { ! ! ! socket_close($sockets[1]); $messageWritten = 'Mensagem enviada pelo processo filho'; if (false === socket_write($sockets[0], $messageWritten, strlen($messageWritten))) { echo 'Falha ao escrever dados no socket: ' . socket_strerror(socket_last_error($sockets)); exit(3); } $messageGiven = socket_read($sockets[0], 1024, PHP_BINARY_READ); echo 'Mensagem no processo filho: ' . "t" . $messageGiven . PHP_EOL; socket_close($sockets[0]); } 54
  • Outras  formas • • • • • • • • APC   Memcached   MongoDB   MySQL   RabbitMQ   Redis   SQLite   … 55
  • PERFORMANCE 56
  • • Não  existe  garbage  collection,  o  processo   principal  não  morre   • Utilize  as  funções  gc_enable()  e   gc_collect_cycles()   • O  PHP  possui  um  cache  padrão  de  arquivos   abertos  (em  memória)  isso  pode  prejudicar  a   performance  do  daemon,  utilize   clearstatcache()  para  remover  esse  cache   • Utilizar  IPC  sem  limpar  os  dados  corretamente   pode  ocasionar  uma  série  de  problemas 57
  • BIBLIOTECAS 58
  • • AraraProcess  (https://github.com/Arara/ Proccess)   • PHP-­‐Daemon  (https://github.com/shaneharter/ PHP-­‐Daemon)   • System_Daemon  (http://pear.php.net/package/ System_Daemon)   • ZendX_Console_Process_Unix  (http:// framework.zend.com/manual/1.12/en/ zendx.console.process.unix.html) 59
  • PERGUNTAS 60
  • CONCLUSÃO 61
  • Links • @henriquemoody  na  maioria  das  redes  sociais   (about.me,  BitBucket,  Coderbits,  GitHub,  SlideShare,   Twitter…)   • Código  da  palestra:  https://github.com/henriquemoody/ php-­‐e-­‐seus-­‐demonios/tree/1.0.0   • Ícones:  http://www.visualpharm.com   • Formatação  de  código:  https://sublime.wbond.net/ packages/Highlight 62
  • Referências • • • • • • • • • • • • • • • http://en.wikipedia.org/wiki/Cron   http://en.wikipedia.org/wiki/Daemon_(computing)   http://en.wikipedia.org/wiki/Init   http://en.wikipedia.org/wiki/POSIX   http://man7.org/linux/man-­‐pages/man7/signal.7.html   http://php.net/ChangeLog-­‐4.php   http://php.net/cli   http://php.net/ncurses   http://php.net/newt   http://php.net/pcntl   http://php.net/posix   http://php.net/readline   http://pt.wikipedia.org/wiki/Daemon_(computação)   http://www.slideshare.net/jkeppens/php-­‐in-­‐the-­‐dark   http://www.win.tue.nl/~aeb/linux/lk/lk-­‐10.html 63