1. Rendimiento en Magento
Manel R. Doménech (@manelio)
Socio fundador de @onestic
@onestic @SoporteMagento
2. Contenidos (1/2)
• Instalación básica de Magento.
• El sistema
– Apache o nginx
– PHP, APC, php-fpm
– MySQL
• Primeras mejoras: sistema interno de caché.
• Sesiones: ¿dónde almacenarlas?
• Detección de cuellos de botella.
3. Contenidos (2/2)
• Precauciones con los módulos
• Benchmarking. Pruebas de carga.
• Caché externa y servicios externos
– Ezapps_Zoom
– Phoenix_VarnishCache
– Cloudflare
• Escalado de infraestructura
4. Instalación básica de Magento
Sistema: Virtual. Intel Xeon
E5410, 4 cores. 4GB RAM.
50GB HD.
- Catálogo de 8 productos
- Cachés deshabilitadas - Cachés habilitadas
Tiempo de carga de una Tiempo de carga de una
página de catálogo página de catálogo
2.35s .8s
5. Instalación básica de Magento
• Con 40K referencias la cosa cambia. Con
cachés habilitadas:
– Para una petición:
• Tiempo medio de respuesta: 4s
• Ratio de transacciones: .25 t/s
– Para 10 peticiones concurrentes:
• Tiempo medio de respuesta: 6.86s
• Ratio de transacciones: 0.93 t/s
• Concurrencia: 6.38
6. El sistema
• Apache o nginx: con nginx + php-fpm
obtenemos un rendimiento mucho más
elevado
• PHP
– PHP 5.3
– APC, imprescindible
• MySQL: para alto tráfico o gran cantidad de
productos, se convierte en el cuello de botella.
7. Primeras mejoras: sistema interno
de caché
• Uso intensivo de ficheros de configuración XML que Magento debe
mezclar
• Bloques HTML
• Traducciones
• Colecciones
• Atributos y tipos EAV
¿Dónde almacenar esta información cacheada?
¡Cuidado con el uso de caché en disco y las invalidaciones de
caché!
8. Primeras mejoras: sistema interno
de caché
• Motores de caché
– Ficheros
– Base de datos
– Memoria (memcached, redis)
– Híbrido, usando dos niveles de caché
En nuestra experiencia,
los mejores resultados los obtenemos con redis
9. Primeras mejoras: sistema interno
de caché
• Flat tables: flat catalog, ¿siempre?
• Cuidado con la sobrecarga que añade el reindexado
de tablas, especialmente las tablas de catálogo
cuando éste es grande y las escrituras muy
frecuentes. Por ejemplo, módulos de drop shipping.
• Cuidado también con las consultas de búsqueda
fulltext. Conviene usar un motor especializado: solr,
sphinx, lucene, elasticsearch.
10. Sesiones: ¿dónde almacenarlas?
• Cuando la base de datos se convierte en un
cuello de botella, almacenar las sesiones en
ella puede complicar aún más la situación.
• Por otro lado, si se opta por mantener
diferentes servidores de frontend, es una
forma de centralizar las sesiones.
• En este último caso es preferible utilizar
memcached o redis para almacenar sesiones.
11. Detección de cuellos de botella
class OnProfiler {
var $log = "/tmp/profile.log";
static $t0 = 0;
Método de ir por casa,
function __construct($conf) {
foreach($conf as $k => $v) $this->$k = $v; pero eficaz.
self::$t0 = microtime(true);
register_shutdown_function(array($this, 'shutdown'));
}
function shutdown() {
$t1 = microtime(true); $tdelta = $t1 - self::$t0;
$peak = memory_get_peak_usage(true);
$this->log(date('Y-m-d H:i:s')."t".sprintf("%.2ft%.2f", $tdelta, $peak/1024/1024)."t".$_SERVER['REQUEST_URI']);
}
function log($str) {
$f = fopen($this->log, "a"); fwrite($f, $str."n"); fclose($f);
}
}
$prof = new OnProfiler(array('log' => '/tmp/profile.log',));
13. Detección de cuellos de botella
• Ejemplo de resultado obtenido con xhprof
-> Mage_Catalog_Block_Product_List::getCountAllVendorProducts 20 10.3% 1,872,247 37.4% 565,912 19.9% 1,963,544 7.0% 853,464 3.0%
Las llamadas a este método duran 1.9s, de una duración total de 5.0s. Esto es un 37.4% de tiempo perdido contando los productos de
los vendedores.
-> Mage_Catalog_Block_Product_List_Toolbar::getLastPageNum 4 14.8% 145,695 2.9% 1,000 0.0% 19,976 0.1% 26,928 0.1%
En este caso, para obtener el último número de página de la lista de productos, se consumen 0.15s, un 2.9% del total.
-> Mage_Catalog_Block_Product_List::_beforeToHtml 1 2.9% 495,733 9.9% 85,986 3.0% 1,929,848 6.9% 1,513,256 5.3%
Casi lo mismo ocurre antes de renderizar la lista de productos: 0.50s, que es un 9.9% del total
-> AW_Sarp_Block_Catalog_Product_Price::getProduct 20 14.8% 621,377 12.4% 486,925 17.1% 2,533,088 9.0% 2,758,320 9.7%
Esta llamada consume 0.62s, un 12.4% del total.
-> Unirgy_Dropship_Helper_Data::loadCustomData 731 1.7% 649,759 13.0% 664,902 23.4% 6,912,152 24.6% 176,320 0.6%
Esta llamada consume 0.65s, un 13.0% del total.
13.0 + 12.4 + 9.9 + 2.9 + 37.4 = 75.6
Las llamadas a las anteriores funciones están suponiendo un 75.6% de la carga de la página. 3.79s
14. Detección de cuellos de botella
• Una vez identificados los cuellos de botella, es
el momento de corregirlos. Casos habituales:
– Consultas sin índices sobre tablas de módulos
– Abuso de llamadas a funciones en vez de
precalcular y reutilizar
– Necesidad de cacheo de bloques costosos, como
el de precio
– Separar el renderizado de los ítems en las listas
productos, y cachear estos bloques.
15. Detección de cuellos de botella
• Onestic_Profiler. Uso de redis para cálculo de
acumulados de tiempo, memoria y consultas.
• Detalle de acumulados por bloque:
++++ renderView: frontend/default/agroterra/template/catalog/product/list/toolbarbottom.phtml
+++++ renderView: frontend/default/agroterra/template/page/html/pager.phtml
- - - - - 0.00183 renderView: frontend/default/agroterra/template/page/html/pager.phtml
- - - - 0.00380 renderView: frontend/default/agroterra/template/catalog/product/list/toolbarbottom.phtml
- - - 0.80834 renderView: frontend/default/agroterra/template/catalog/product/list.phtml
- - 1.27292 renderView: frontend/default/agroterra/template/catalog/category/view.phtml
16. Precauciones con los módulos
• Hay módulos que crean tablas, modifican
consultas o añaden joins y no siempre hacen
hincapié en el rendimiento. El problema
puede no verse hasta que el tráfico crece o el
catálogo aumenta.
• Cuidado con las colisiones de rewrites de
clases. Ejemplo: Ashroeder_SMTPPro /
Ebizmarts_Mailchimp
17. … ahora parece que Magento está
en forma sin el uso de esteroides
anabólicos …
¡A reventarlo!
18. Benchmarking. Pruebas de carga.
• Multitud de herramientas
– F5
– Apache benchmark
– BadBoy / Jmeter
– Siege
• Simula una serie de peticiones a la aplicación indicando
el concurrencia, tiempo entre peticiones, repeticiones
de la prueba y un fichero de URLs.
20. Caché externa y servicios externos
Ahora sí: esteroides anabolizantes
• FPC: Full Page Caché
• FPC con Phoenix_VarnishCache
• FPC con Ezapps_Zoom
• Precauciones con FPC: usuarios
autentificados. Estrategias y ejemplos.
• Cloudflare: aligerar la carga del servidor
21. Caché externa y servicios externos
Cloudflare
CDN y protección anti DDOS
Varnish (Phoenix_VarnishCache)
Web caché, proxy
nginx
php-fpm (Ezapps_Zoom)
php-fpm (Magento)
22. Escalado de infraestructura
• Detectar qué capa puede sufrir problemas de
rendimiento: frontend o servidor de base de
datos. O ambas.
• Medida 1. Separar datos de mysql y ficheros
de aplicación en dispositivos físicos diferentes.
• Medida 2. Separar aplicación y servidor de
base de datos en instancias diferentes.
Cuidado con el tráfico.
23. Escalado de infraestructura
• Medida 3: Servidores de frontend o de base
de datos redundantes. Hay que prestar
atención a:
– Puntos únicos de fallo (balanceador de carga,
servidor NFS)
– Mantenimiento de sesiones
– Lecturas y escrituras de MySQL
– Replicaciones de MySQL
24. Y hasta aquí hemos llegado
Manel R. Doménech (@manelio)
Socio fundador y haciendo un poco de todo en @onestic
Estoy terminando esta presentación en el Alaris y sin
conexión a internet. Para que no quede vacía esta última
diapositiva utilizaré un monigote del PowerPoint (que los
acabo de encontrar) en vez de mi foto, que seguro que
es más agradable de ver.
Ale. Podéis empezar a crucificarme.