1 Apache ha muerto Viva LIGHTTPD! [email protected] * No creo realmente que el Apache haya muerto, pero si que ahora hay mas opciones, algunas mucho mas interesantes, como Lighty. El titulo de la presentacion es para provocar, nomas.
2 Características Casi 3 años de desarrollo. Lo empezo un tal Jan Kneschke La ultima versión estable es 1.4.18, devel es 1.5-prerelease. Licencia BSD. Proof of Concept de "The C10K problem": "It's time for web servers to handle 10.000 clients simultaneously" Corre PHP, Python, PERL, Ruby, cualquier cosa que sea FastCGI o SCGI o AJP13 o... Market Share de 0.6% (feb 2007) Mueve 6 de los Top 250 sitios en la internet (Alexa - puaj) Increíblemente rápido, liviano y flexible (condicionales, etc)
3 La filosofía Lighty Un solo proceso, 1 solo thread KISS: “keep it simple, stupid” Los archivos estáticos los manda directo el kernel: del disco al socket FastCGI: Los script PHP los procesa -el- PHP (no el mod_php, ni el mod_snake) Un web server es, básicamente, un programa que mueve texto de un lado al otro de la memoria. Mover "mucho" texto no debería ser algo "pesado" (limitado por el CPU) Lighttpd como proxy HTTP "The web is a pipe"
4 Cuando si, cuando no Lighty es perfecto cuando: Uno puede y quiere tener control total sobre las aplicaciones que corre Cuando el hardware no esta súper exigido Lighty no es ideal cuando: Hay cientos de usuarios distintos usando virtualhosts (virtual hosting barato) y van a quejarse de cosas como "los rewrites de Apache no me andan!" Los recursos son escasos para el trafico (discos exprimidos!)
5 Quien usa Lighttpd Algunos nombres "importantes" YouTube Wikipedia ImageShack SourceForge SendSpace.com MiniNova.org IsoHunt.com
6 Módulos disponibles Los normales: rewrite (como Apache) auth (HTTP auth, con distintos backends) deflate (comprime con GZIP o BZIP2, todo lo que es text/*) expire (agrega headers de Expires)... Los emocionantes: flv_streaming (youtube en casa!) magnet (dar vuelta requests como una media) trigger_b4_dl (anti hotlinking) upload_progress (progress bars en javascript fáciles)
7 Problemas y soluciones Clusters (FastCGI) Downloads "protegidos" (X-SENDFILE) Distribuyendo la carga (mod_proxy_core) Scripteando las tripas de lighty (mod magnet) imágenes al azar cache
8 Configuración condicional Se pueden comparar: cookie, host,useragent, referer, url, querystring, remoteip, socket, path, existing-path server.document-root = "/var/www/example/" $HTTP["host"] == "www2.example.org" { server.document-root = "/var/www/alt/" } $HTTP["url"] =~ "^/images/" { expire.url = ( "" => "access 365 days" ) }
9 FastCGI 1.El interprete de FastCGI (php, rails) corre permanentemente como un daemon, atendiendo en un socket (unix o TCP) 2.El webserver se le conecta para pedirle que interprete un script 3.El daemon devuelve una respuesta (ej, HTML) Notas: La performance obtenida es similar a la de Apache mod_php Se necesita una instancia del interprete de FastCGI para cada pedido simultaneo (PHP va forkeando, como necesita)
10 Apache mod_php vs FastCGI Apache: 1.atiende el request 2.se lo pasa internamente al mod_php 3.devuelve la respuesta Lighttpd: 1.atiende el request 2.se conecta con el servidor de FastCGI (local o remoto) 3.devuelve la respuesta
11 1 servidor HTTP, 3 servidores PHP HTT P FastCG I
12 Balanceo de Carga PHP Notas: También puede balancear usando SQF (shortest queue first )y Cache Array Routing Protocol (CARP) Soporta FailOver: si un procesador esta caído, prueba con el próximo $HTTP["url"] =~ "\.php$" { proxy-core.protocol = "fastcgi" proxy-core.balancer = "round-robin" proxy-core.backends = ( "10.0.0.1:1000", "10.0.0.2:1000", "10.0.0.3:1000") }
13 Un servidor por "zona" $HTTP["url"] =~ "^/forum" { proxy-core.protocol = "fastcgi" proxy-core.backends = ( "10.0.0.1:1000") } $HTTP["url"] =~ "^/torrents" { proxy-core.protocol = "fastcgi" proxy-core.backends = ( "10.0.0.99:1000") }
14 Distribuyendo la carga mod_proxy_core Proxy de HTTP, FastCGI, SCGI, AJP13 Un servidor de Lighttpd "adelante" Funcionando como un proxy (sin cache!) Redirgiendo los requests al backend correspondiente Los PHP a 10.0.0.1:1000 (FastCGI) Las imágenes, al servidor que les corresponda /images/[0-4]/* -> http://10.0.0.2/images/ (HTTP)http://10.0.0.2/images/ /images/[5-9]/* -> http://10.0.0.3/images/ (HTTP)http://10.0.0.3/images/
15 Distribuyendo la carga $HTTP["url"] =~ "\.php$" { proxy-core.protocol = "fastcgi" proxy-core.backends = ( "10.0.0.1:1000" ) } else $HTTP["url"] =~ "^/images/[0-4]/" { proxy-core.protocol = "http" proxy-core.backends = ( "10.0.0.2:80" ) } else $HTTP["url"] =~ "^/images/[5-9]/" { proxy-core.protocol = "http" proxy-core.backends = ( "10.0.0.3:80" ) } The web is a pipe!
16 Sirviendo downloads "protegidos" Problema clásico: El archivo / screensaver "pescaditos.exe" esta solo disponible para usuarios registrados Solución clásica (php):
17 Sirviendo archivos "protegidos" Problemas de la solucion clásica: No hay resume de downloads No hay cache de ningún tipo Ocupa un "servidor de php" (Apache child o FastCGI) Es leeento (abrir el archivo, copiar el contenido del archivo a la memoria, mandar el contenido al socket) Desperdicia memoria con archivos "grandes" Solución Lighty recanchera: El PHP (o lo que sea) valida si el usuario tiene permisos Devuelve un header de HTTP especial, "X-Sendfile" con el path del archivo estático a devolver Lighty encuentra este header especial y manda al kernel a darle el archivo al usuario
18 Solución Lighty recanchera Ventajas: ● Es muy rápido; el archivo lo manda el kernel directo (usa sendfile(2) ● Manda headers HTTP como la gente: Last-Modification, Etag, Size ● Soporta resume, puede responder If-Modified-Since, If-None-Match, etc ● No ocupa un procesador de FastCGI
19 Scripteando las tripas de Lighty ModMagnet "atrae" los requests al servidor HTTP y permite modificarlos a gusto Usa scripts LUA para alterar los pedidos / las respuestas Los scripts solo son compilados cuando el servidor es reiniciado o cuando cambian Corre en el mismo proceso que lighty, así que cualquier operación "lenta" bloquea todo el server Permite hacer cosas bastante macabras
20 Un archivo al azar En PHP, PHP+X-Sendfile y LUA
21 magnet, minibenchmark Resultados: PHP: 212.47 trans/sec (100%) PHP + X-Sendfile: 264.10 trans/sec (124%) LUA: 432.97 trans/sec (203%)
22 magnet: cache html Idea de un cache HTML bastante rudimentario La primera vez que un script PHP se ejecuta, su salida (probablemente HTML) se guarda en un archivo temporal Las siguientes veces que es ejecutado, antes de hacer todas las cosas "interesantes" (conectarse a la db, hacer cosas), nos fijamos si este archivo temporal existe. Si es así, se devuelve el contenido del archivo temporal, evitando (y nos ahorramos toda la parte larga)
23 magnet: cache html Guardar el output HTML en el archivo temporal:
24 magnet: cache html Devolver el contenido del archivo temporal si existe y terminar la ejecucion (PHP):
25 magnet: cache html Devolver el contenido del archivo temporal si existe y terminar la ejecucion (LUA): info = lighty.stat(lighty.env["physical.path"]) cache_path = "/tmp/"..info["st_ino"]..".html" cache_info = lighty.stat(cache_path) if (cache_info) then lighty.env["physical.path"] = cache_path end
26 magnet: cache html Benchmark de juguete: ● Cache PHP: 189.53 trans/sec (100%) ● Cache LUA: 360.72 trans/sec (190%)
27 Ayuda, por dios! http://www.lighttpd.net http://blog.lighttpd.net Trac (wiki+tickets) http://trac.lighttpd.nethttp://trac.lighttpd.net/trac/wiki/ #[email protected] http://forum.lighttpd.net/forum/1/ [email protected] Creative Commons Attribution-Noncommercial Share Alike 2.5 Argentina License