Otimizando sites baseados em Kohana para velocidade e escalabilidade

Um site que construí com Kohana foi batido com uma enorme quantidade de trânsito ontem, fazendo com que eu dê um passo atrás e avalie parte do design. Estou curioso o que são algumas técnicas padrão para otimizar aplicativos baseados em Kohana?

Eu também estou interessado em comparações. Preciso configurar o Benchmark::start() e o Benchmark::stop() para cada método do controlador para ver os tempos de execução de todas as páginas ou posso aplicar benchmarking globalmente e rapidamente?

Estarei usando o Cache-library mais no tempo por vir, mas estou aberto a mais sugestões porque tenho certeza de que há muito o que posso fazer, simplesmente não estou ciente do momento.

O que direi nesta resposta não é específico para o Kohana, e provavelmente pode ser aplicado a muitos projetos PHP.

Aqui estão alguns pontos que me faltam quando falo sobre desempenho, escalabilidade, PHP, …
Eu usei muitas dessas idéias ao trabalhar em vários projetos – e eles ajudaram; então eles provavelmente poderiam ajudar aqui também.

Em primeiro lugar, quando se trata de performances, há muitos aspectos / questões a serem consideradas :

  • configuração do servidor (Apache, PHP, MySQL, outros daemons possíveis e sistema) ; você pode obter mais ajuda sobre isso no ServerFault , suponho,
  • Código PHP
  • Consultas de database,
  • Usando ou não seu servidor web?
  • Você pode usar qualquer tipo de mecanismo de cache? Ou você precisa sempre mais de dados atualizados no site?

Usando um proxy reverso

A primeira coisa que pode ser realmente útil é usar um proxy reverso , como o verniz , na frente do seu servidor web: deixe que armazene o máximo de coisas possível , de modo que apenas as solicitações que realmente precisam de cálculos PHP / MySQL (e, claro, algumas outras pedidos, quando eles não estão no cache do proxy), ele é para o Apache / PHP / MySQL.

  • Antes de tudo, seu CSS / Javascript / Imagens – bem, tudo o que é estático – provavelmente não precisa ser sempre servido pelo Apache
    • Então, você pode ter o cache de proxy reverso todos esses.
    • Servir esses arquivos estáticos não é grande coisa para o Apache, mas quanto menos ele tem para trabalhar, mais isso será capaz de fazer com o PHP.
    • Lembre-se: o Apache só pode servidor um número finito, limitado, de pedidos por vez.
  • Em seguida, faça com que o proxy inverso sirva o máximo possível de páginas PHP do cache: provavelmente há algumas páginas que não mudam com freqüência e podem ser atendidas a partir do cache. Em vez de usar algum cache baseado em PHP, por que não permitir que outro servidor mais leve sirva esses (e buscá-los do servidor PHP de tempos em tempos, então eles estão sempre quase atualizados) ?
    • Por exemplo, se você tiver alguns feeds RSS (Geralmente, tendemos a esquecer aqueles, ao tentar otimizar para performances) que são solicitados com muita frequência , ter-lhes no cache por alguns minutos pode salvar centenas / milhares de solicitação para o Apache + PHP + MySQL!
    • O mesmo para as páginas mais visitadas do seu site, se eles não mudam por pelo menos alguns minutos (exemplo: página inicial?) , Então, não é necessário desperdiçar a CPU gerando novamente cada vez que um usuário os solicita.
  • Talvez haja uma diferença entre as páginas atendidas para usuários anônimos (a mesma página para todos os usuários anônimos) e páginas atendidas para usuários identificados (“Olá, Sr. X, você tem novas mensagens”, por exemplo) ?
    • Se assim for, você provavelmente pode configurar o proxy reverso para armazenar em cache a página que é servida para usuários anônimos (com base em um cookie, como o cookie da session, geralmente)
    • Isso significa que o Apache + PHP tem menos para lidar com: apenas usuários identificados – o que pode ser apenas uma pequena parte de seus usuários.

Sobre o uso de um proxy inverso como cache , para um aplicativo PHP, você pode, por exemplo, ver os resultados do benchmark Mostrar aumento de 400% a 700% nas capacidades do servidor com cache APC e Squid .
(Sim, eles estão usando Squid, e eu estava falando sobre verniz – isso é apenas uma outra possibilidade ^ ^ O verniz é mais recente, mas mais dedicado ao armazenamento em cache)

Se você fizer isso bem o suficiente e conseguir parar de reabastecer muitas páginas repetidas vezes, talvez você nem precise otimizar qualquer código 😉
Pelo menos, talvez não em qualquer tipo de pressa … E é sempre melhor fazer otimizações quando você não está sob muita pressão …

Como um sidenote: você está dizendo no OP:

Um site que eu construí com Kohana foi batido com uma enorme quantidade de trânsito ontem,

Este é o tipo de situação súbita em que um proxy reverso pode, literalmente, salvar o dia , se o seu site pode lidar com não estar atualizado pelo segundo:

  • instalá-lo, configurá-lo, deixá-lo sempre – todo dia normal – executar:
    • Configure para não manter as páginas do PHP no cache; ou apenas por uma curta duração; desta forma, você sempre possui dados atualizados exibidos
  • E, no dia em que você toma um efeito slashdot ou digg:
    • Configure o proxy reverso para manter as páginas PHP no cache; ou por um longo período de tempo; talvez suas páginas não estejam atualizadas pelo segundo, mas permitirá que seu site sobreviva ao efeito digg!

Sobre isso, como eu posso detectar e sobreviver sendo “Slashdotted”? pode ser uma leitura interessante.

No lado do PHP das coisas:

Em primeiro lugar: você está usando uma versão recente do PHP ? Existem melhorias regulares em velocidade, com novas versões 😉
Por exemplo, dê uma olhada no Benchmark de PHP Branches 3.0 a 5.3-CVS .

Observe que as performances são uma boa razão para usar o PHP 5.3 ( eu fiz alguns benchmarks (em francês) e os resultados são excelentes
Outra razão muito boa, é claro, que o PHP 5.2 atingiu o fim da vida e já não é mantido!

Você está usando algum cache de código aberto?

  • Estou pensando em APC – Cache do PHP Alternativo , por exemplo ( pecl , manual ) , que é a solução que eu já usei – e isso é usado em todos os servidores nos quais trabalhei.
    • Veja também: Slides APC Facebook ,
    • Ou os resultados do benchmark mostram aumento de 400% a 700% nas capacidades do servidor com cache APC e Squid .
  • Pode realmente reduzir muito a carga da CPU de um servidor, em alguns casos (eu vi CPU-load em alguns servidores passar de 80% a 40%, apenas instalando o APC e ativando sua funcionalidade de cache-opcode!)
  • Basicamente, a execução de um script PHP é feita em duas etapas:
    • Compilação do código-fonte do PHP para opcodes (tipo de equivalente ao bytecode da JAVA)
    • Execução desses opcodes
    • A APC mantém esses na memory, portanto, há menos trabalho a ser feito sempre que um script / arquivo PHP é executado: apenas busque os códigos opcionais da RAM e execute-os.
  • Você pode precisar dar uma olhada nas opções de configuração da APC , btw
    • há alguns desses, e alguns podem ter um grande impacto em velocidade / CPU-carga / facilidade de uso para você
    • Por exemplo, desativar [apc.stat](http://php.net/manual/en/apc.configuration.php#ini.apc.stat) pode ser bom para o sistema de carga; mas significa que as modificações feitas em arquivos PHP não serão levadas em consideração a menos que você elimine todo o código-cache; sobre isso, para mais detalhes, veja, por exemplo, para stat () Or Not To stat ()?

Usando o cache para dados

Tanto quanto possível, é melhor evitar fazer o mesmo uma e outra vez .

A principal coisa em que eu penso é, é claro, as Consultas SQL: muitas das suas páginas provavelmente fazem as mesmas consultas, e os resultados de algumas delas provavelmente são quase sempre os mesmos … O que significa muitas consultas “inúteis” feito para o database, que tem que gastar tempo servindo os mesmos dados uma e outra vez.
Claro, isso é verdade para outras coisas, como chamadas de serviços da Web, buscando informações de outros sites, cálculos intensos, …

Pode ser muito interessante para você identificar:

  • Quais consultas são executadas muitas vezes, sempre retornando os mesmos dados
  • Quais outros cálculos (pesados) são feitos muito tempo, sempre retornando o mesmo resultado

E armazene esses dados / resultados em algum tipo de cache, então eles são mais fáceis de obter – mais rápido – e você não precisa ir ao seu servidor SQL para “nada”.

Grandes mecanismos de cache são, por exemplo:

  • APC : além do opcode-cache, falou anteriormente, ele permite que você armazene dados na memory,
  • E / ou memcached ( veja também ) , o que é muito útil se você literalmente tem muitos dados e / ou está usando vários servidores , pois está distribuído.
  • claro, você pode pensar em arquivos; e provavelmente muitas outras idéias.

Tenho certeza de que seu framework vem com algumas coisas relacionadas ao cache; Você provavelmente já sabe disso, como você disse: “Eu vou usar a biblioteca Cache mais na hora certa” no OP 😉

Perfilamento

Agora, uma coisa agradável a fazer seria usar a extensão Xdebug para perfilar sua aplicação : geralmente permite encontrar um par de pontos fracos com bastante facilidade – pelo menos, se houver alguma function que demore muito tempo.

Configurado corretamente , ele irá gerar arquivos de perfil que podem ser analisados ​​com algumas ferramentas gráficas, como:

  • KCachegrind : meu favorito, mas funciona apenas no Linux / KDE
  • Wincachegrind para janelas; faz um pouco menos do que o KCacheGrind, infelizmente – não exibe callgraphs, normalmente.
  • Webgrind que é executado em um servidor web PHP, portanto funciona em qualquer lugar – mas provavelmente tem menos resources.

Por exemplo, aqui estão algumas screenshots do KCacheGrind:

KCacheGrind: canvas principal http://extern.pascal-martin.fr/so/kcachegrind/kcachegrind-1-small.png KCacheGrind: Callgraph exportado como uma imagem http://extern.pascal-martin.fr/so/kcachegrind/ kcachegrind-2-small.png

(BTW, o callgraph apresentado na segunda captura de canvas normalmente não é algo que WinCacheGrind nem Webgrind podem fazer, se eu me lembro corretamente ^^)

(Obrigado @Mikushi pelo comentário) Outra possibilidade de que eu não usei muito é a extensão xhprof : também ajuda com o perfil, pode gerar callgraphs – mas é mais leve do que o Xdebug, o que significa que você deve poder instalá-lo em um servidor de produção.

Você deve ser capaz de usá-lo ao XShong , que ajudará a visualizar os dados.

No lado SQL das coisas:

Agora que falamos um pouco sobre o PHP, note que é mais do que possível que seu gargalo não seja o lado do PHP das coisas , mas o database …

Pelo menos duas ou três coisas, aqui:

  • Você deve determinar:
    • Quais são as consultas mais freqüentes que o seu aplicativo está fazendo?
    • Se eles são otimizados (usando os índices certos , principalmente?) , Usando a instrução EXPLAIN , se você estiver usando o MySQL
      • Veja também: Otimizando SELECT e outras declarações
      • Você pode, por exemplo, ativar log_slow_queries para obter uma lista dos pedidos que demoram “muito” tempo e começar sua otimização por esses.
    • se você poderia armazenar algumas dessas consultas (veja o que eu disse anteriormente)
  • O seu MySQL está bem configurado? Eu não sei muito sobre isso, mas existem algumas opções de configuração que podem ter algum impacto.
    • Otimizar o MySQL Server pode fornecer algumas informações interessantes sobre isso.

Ainda assim, as duas coisas mais importantes são:

  • Não vá para o database se você não precisa: esconder o máximo que puder !
  • Quando você precisa ir para o database, use consultas eficientes: use índices; e perfil!

E agora?

Se você ainda está lendo, o que mais poderia ser otimizado?

Bem, ainda há espaço para melhorias … Algumas idéias orientadas para a arquitetura podem ser:

  • Mude para uma arquitetura de camada n:
    • Coloque o MySQL em outro servidor (2 níveis: um para o PHP e o outro para o MySQL)
    • Use vários servidores PHP (e balanceie os usuários entre eles)
    • Use outras máquinas para arquivos estáticos, com um servidor web mais leve, como:
      • Lighttpd
      • ou nginx – este está se tornando cada vez mais popular, principalmente.
    • Use vários servidores para o MySQL, vários servidores para PHP e vários proxies reversos na frente desses
    • Claro: instale os daemons memcached em qualquer servidor com qualquer quantidade de RAM livre, e use-os para armazenar em cache tanto como você pode / faz sentido.
  • Use algo “mais eficiente” que o Apache?
    • Eu ouço cada vez mais sobre o nginx , o que é suposto ser ótimo quando se trata de PHP e sites de alto volume; Eu nunca usei isso mesmo, mas você pode encontrar alguns artigos interessantes sobre isso na net;
      • por exemplo, desempenho PHP III – executando nginx .
      • Veja também: PHP-FPM – FastCGI Process Manager , que é empacotado com PHP> = 5.3.3, e faz maravilhas com o nginx.

Bem, talvez algumas dessas idéias sejam um pouco exageradas em sua situação ^^
Mas, ainda … Por que não estudá-los um pouco, apenas no caso? 😉

E o Kohana?

Sua pergunta inicial foi sobre otimizar um aplicativo que usa o Kohana … Bem, postei algumas idéias que são verdadeiras para qualquer aplicativo PHP … O que significa que elas são verdadeiras para o Kohana também 😉
(Mesmo que não seja específico para isso ^^)

Eu disse: use cache; Kohana parece suportar algumas coisas em cache (você falou sobre isso sozinho, então não há nada de novo aqui …)
Se houver algo que possa ser feito rapidamente, tente-o 😉

Eu também disse que você não deveria fazer nada que não fosse necessário; Existe alguma coisa habilitada por padrão em Kohana que você não precisa?
Navegando pela rede, parece que há pelo menos algo sobre filtragem XSS; você precisa disso?

Ainda assim, aqui estão alguns links que podem ser úteis:

  • Kohana Discussion Geral: Caching?
  • Suporte comunitário: otimização do site: desempenho máximo do site usando Kohana

Conclusão?

E, para concluir, um pensamento simples:

  • Quanto custa a sua empresa pagar 5 dias? – considerando que é uma quantidade razoável de tempo para fazer algumas ótimas otimizações
  • Quanto custará à sua empresa comprar (pagar por?) Um segundo servidor e sua manutenção?
  • E se você tiver que dimensionar maior?
    • Quanto custará gastar 10 dias? Mais? otimizando cada bit possível da sua aplicação?
    • E quanto para mais alguns servidores?

Não estou dizendo que você não deve otimizar: você definitivamente deve!
Mas vá para otimizações “rápidas” que você obterá grandes recompensas primeiro: usar algum cache de código operacional pode ajudá-lo a obter entre 10 e 50 por cento de carga de CPU do seu servidor … E demora apenas alguns minutos para configurar; ) Do outro lado, gastando 3 dias por 2% …

Ah, e, btw: antes de fazer qualquer coisa: coloque algumas coisas de monitoramento no lugar , então você sabe quais melhorias foram feitas e como!
Sem monitoramento, você não terá idéia do efeito do que você fez … Mesmo que seja uma otimização real ou não!

Por exemplo, você poderia usar algo como RRDtool + cacti .
E mostrar ao seu chefe alguns charts agradáveis ​​com uma queda de carga de CPU de 40% sempre é ótimo 😉

De qualquer forma, e para realmente concluir: divirta-se!
(Sim, otimizar é divertido!)
(Ergh, não pensei que escrevesse muito … Espero que pelo menos algumas partes disso sejam úteis … E eu devo me lembrar dessa resposta: pode ser útil algumas outras vezes …)

Use XDebug e WinCacheGrind ou WebCacheGrind para perfilar e analisar a execução lenta do código.

WebCacheGrind http://jokke.dk/media/2008-webgrind/webgrind_small.png WinCacheGrind

Código de perfil com XDebug .

Use um monte de cache. Se suas páginas são relativamente estáticas, o proxy reverso pode ser a melhor forma de fazê-lo.

Kohana está fora da checkbox muito rápido, exceto pelo uso de objects de database. Para citar o Zombor “Você pode reduzir o uso da memory, garantindo que você esteja usando o object de resultado do database em vez dos arrays de resultados”. Isso faz uma diferença de desempenho HUGEE em um site que está sendo derrubado. Não só usa mais memory, mas retarda a execução de scripts.

Além disso, você deve usar o armazenamento em cache. Prefiro memcache e use-o em meus modelos como este:

 public function get($e_id) { $event_data = $this->cache->get('event_get_'.$e_id.Kohana::config('config.site_domain')); if ($event_data === NULL) { $this->db_slave ->select('e_id,e_name') ->from('Events') ->where('e_id', $e_id); $result = $this->db_slave->get(); $event_data = ($result->count() ==1)? $result->current() : FALSE; $this->cache->set('event_get_'.$e_id.Kohana::config('config.site_domain'), $event_data, NULL, 300); // 5 minutes } return $event_data; } 

Isso também aumentará dramaticamente o desempenho. As duas técnicas anteriores melhoraram o desempenho de um site em 80%.

Se você forneceu mais informações sobre onde você acha que o gargalo é, eu tenho certeza que podemos dar algumas idéias melhores.

Verifique também o yslow (google it) para algumas outras dicas de desempenho.

Estritamente relacionado ao Kohana (você provavelmente já fez isso, ou não):

No modo de produção:

  1. Habilite o armazenamento em cache interno (isso só armazena os resultados do Kohana :: find_file, mas isso realmente pode ajudar muito.
  2. Desativar perfil

Apenas meus 2 centavos 🙂

Concordo totalmente com as respostas XDebug e cache. Não olhe para a camada de Kohana para otimizar até que você tenha identificado a maior velocidade e os estrangulamentos da escala.

XDebug irá dizer-lhe se você gastou a maior parte do tempo e identificar “hotspots” em seu código. Mantenha esta informação de perfil para que você possa basear e medir melhorias no desempenho.

Exemplo de problema e solução: se você achar que você está construindo objects caros do database cada vez, isso realmente não muda frequentemente, então você pode olhar para armazená-los com o memcached ou outro mecanismo. Todas essas correções de desempenho levam tempo e adicionam complexidade ao seu sistema, então, certifique-se de seus pontos de estrangulamento antes de começar a corrigi-los.