PHP

Magento em um ambiente distribuído



Passei as últimas semanas trabalhando com o Magento, líder do mundo dos e-commerces, em um cenário distribuído em cloud, tentando obter o máximo de performance, escalabilidade e o mínimo de custos. Utilizando alguns serviços do Amazon Web Services (AWS), tais como EC2 + ELBS3 e algumas dicas sobre como colocar o Magento em um cenário distribuído, o resultado ficou bem bacana.

Resolvi compilar algumas informações úteis neste processo e passar aqui no blog para quem esteja no mesmo barco.  Indo direto ao ponto, as dicas são:

Colocando suas imagens em um CDN

Um dos primeiros desafios foi passar as imagens dos produtos em catálogo para um CDN, que no meu caso era o Simple Storage Service da Amazon, o S3. Pra quem não conhece, o funcionamento do S3 é bem simples: você cria um bucket (ganhando assim uma url pública), coloca seus arquivos lá dentro e paga alguns miseros centavos de dolar por GB utilizado por mês.

No Magento, você pode até configurar a base url dos arquivos estáticos de CSS, imagens  e JS utilizados no template, por exemplo, para apontar para um CDN. Porém, nativamente não existe nada ligar as imagens de cache dos produtos em seu catálogo ao seu CDN. Para isso, eu utilizei uma extensão bem útil chamada OnePica, que apesar do nome lhe dar total descrédito (#troll), a extensão funciona muito bem.

Além do S3, a extensão permite você colocar suas imagens no Coral CDN, Rackspace Cloud Files e qualquer CDN, servidor ou serviço que suporte FTP, FTPS, ou SFTP.

Problema com diretório Media

Um problema quando se distribuí o Magento em várias instâncias é com relação ao diretório media, na raíz da app. Basicamente, o Magento usa o diretório media para guardar alguns css e js gerados on the fly, além de guardar as imagens originais dos produtos em catálogo – e neste último item encontrei um grande problema.

Mesmo utilizando o OnePica para fazer o storage das suas imagens em lugar fora do Magento, ainda assim ele necessita ter as imagens dos produtos no diretório media, pois aparentemente é por lá que ele sabe se a imagem existe ou se ele deve usar um placeholder. Outro seja: mesmo que a imagem esteja perfeitamente no seu bucket S3 ou qualquer outro CDN, sem a imagem original no diretório media, você terá problemas.

Levando em consideração que você tem várias instâncias do web server, não da pra saber em qual delas o Magento irá guardar a imagem do seu produto. Para isso, de cara temos duas soluções:

  1. Porca e barata: No administrador, indo em Sistema > Configuração > Avançado > Sistema, você terá o formulário Armazenamento de Configuração de Media. Nesta opção você poderá trocar o local de armazenamento de mídia do arquivo físico para o banco de dados. Note que fazendo isso facilmente você terá problemas de performance dependendo da quantidade de produtos x concorrência que seu e-commerce tiver.
  2. Minimamente aceitável: criar um diretório compartilhado via NFS (ou algo parecido) entre as instâncias e transformar o diretório media em um link simbólico para lá. Tenho usado esta última opção e o Magento tem se comportado bem até então.

Passando a sessão para Banco

Este item é moleza e não tem segredo: abra o xml app/etc/local.xml e troque o <session_save><![CDATA[files]]></session_save> para <session_save><![CDATA[db]]></session_save> .  Além de ser fácil configurar, há quem afirme que o Magento trabalha mais rápido com a sessão em banco do que em disco. Duvido, mas fica a observação.

SSL usando Load Balancer

Quem já configurou urls usando o administrador do Magento viu que é fácil habilitar a url segura: só colocar o base url na sessão HTTPS dentro de Sistema > Configuração > Web.

O pórem é que se você tiver um balanceador de carga na frente (onde você configurará o certificado SSL), o Magento pode se perder e entrar em redirect loop nas áreas onde ele precisa usar a url segura. O motivo disso é bem simples: o Magento espera que as váriaveis de ambiente $_SERVER[‘HTTPS’] e $_SERVER[‘SERVER_PORT’] estejam devidamente preenchidas, o que não acontece quando você faz foward do load balancer para as instâncias.

Para resolver isso, eu fiz o seguinte: no arquivo index.php, na raíz do Magento, adicione as seguintes linhas antes do Mage::run :

[gist]https://gist.github.com/1165072[/gist]

Embora em alguns cenários isso seja um tiro no pé com relação a segurança da sua app, em um ambiente dedicado, fechado e seu (como acontece no AWS), não será um grande problema.

Disparo de E-mails

É bem provavel que para um ambiente distribuído e balanceado, você não queira ficar enviando e-mails usando um mero sendmail local da vida – isso sem contar que como os IPs da EC2 estão queimados nos filtros de spam por conta de alguns spammers sem mãe,  o que torna necessario isolar os disparos de e-mails em algo mais apropriado.

Para quem precisa disparar uma massa considerável de e-mails , serviços como o Amazon SES talvez sejam uma opção interessante. Para outros casos, é possivel que um simples SMTP autenticado resolva sua situação. No meu caso, utilizei o próprio SMTP disponibilizado pelo Google Apps/Gmail.  Para isso instalei uma outra extensão no Magento chamada ASchroder SMTP Pro Email, que permite parametrizar sua forma de disparo de e-mails, além de permitir fazer log de todos os emails disparados.

Dica: uma vez instalada, você pode acessá-la indo em Sistema > Configuração > Avançado > Sistema. Configure sua forma de disparo de e-mails (Google Apps/Gmail, SMTP, Amazon SES), salve e depois sete a extensão de email para a forma que você escolheu (Choose extension option).

Performance, performance e performance.

O Magento pode não ser o open source mais amado do mundo, mas mesmo entre aqueles que não gostam tanto algo não pode ser negado: ele é o líder do mercado de e-commerces. É o que possui mais features (muitas delas gratuitas) e a maior comunidade. Porém algo assim não fica de graça: com tanta coisa, não é de hoje que ele conquistou a fama de ser lento.

Felizmente existem várias formas que você tornar o Magento em uma plataforma extremamente rápida. Não vou entrar muito fundo nas questões de tuning por que isso merece um post per si, mas vou levantar as seguintes questões:

  1. Habilite o cache nativo do Magento: fácil e indolor, basta entrar no admin e ligar todos os caches dentro de Sistema > Gerenciamento de cache.
  2. Faça merge dos arquivos CSS e JS: diminua o numero de requisições causados por arquivos JS e CSS, indo em Sistema > Configuração > Avançado > Desenvolvedor, colocando como sim as opções de Mesclar arquivos JavaScript e Mesclar arquivos CSS
  3. Habilite o mod_deflate do seu Apache para a transmissão dos arquivos compactados do seu servidor web para os navegadores.
  4. Use um acelerador de PHP como XCache, APC, ionCube, entre muitos outros. Os mais esperançosos acreditam reduzir em até 70% o tempo de execução PHP.
  5. Habilite o KeepAlives do Apache. Com isso, basicamente o Apache vai permitir conexões persistentes usando TCP. Isso pode acelerar seu tempo de latência para arquivos HTML com várias imagens, css, js, etc. Existem alguns contras neste tipo de abordagem, para ver mais clique aqui.
  6. Melhore a performance do seu MySQL. Um dos vários métodos é aumentando seu Query Cache.
  7. Fique de olho nas métricas: cada ms ganho, um passo dado. Para isso use ferramentas como Browsermob para checar como anda seu load time. O objetivo é simples: seja mais rápido que a concorrência. Sempre.

I'm Pedro Mendes, a passionate developer and technology enthusiast. This blog covers programming and technology in the broadest sense possible. It's the place I collect my thoughts, work and findings to share with the public.

View Comments