El Blog de Trespams

Blog personal sobre tecnologia, gestió de projectes i coses que se me passen pel cap

Escalabilitat, multiprocessador i GIL

Una de les dèries que tenim com a informàtics (o que hauríem de tenir) és la d'aprofitar el millor possible els recursos que tenim a la nostra disposició.

Això es tradueix algunes vegades en discussions de que si un llenguatge és millor que un altre en l'aprofitament de la màquina, i quan toca a Python, el tema estrella és el GIL, el mecanisme intern que fa servir Python per poder ser multi-fil. GIL fa que les aplicacions que fan un us intensiu dels fils no siguin tan òptimes com podrien ser (potser sí són més segures i més bones de programar, però això és una altra història) i que puguem pensar no facin tan bon us dels múltiples processadors com es podria suposar. En aquests casos el millor potser és llegir un article molt aclaridor, en lloc de començar a pegar destralades.

Tot i això, pareix que hi ha una confusió entre el que representa l'escalabilitat d'una aplicació i el nombre de processadors d'una màquina. En principi pareix el mateix, però realment no ho és.

La vertadera escalabilitat no la dóna el fet de que l'aplicació aprofiti al 100% els 4 o 8 processadors que pugui tenir el nostre servidor, l'escalabilitat la tenim quan aquesta mateixa aplicació pot executar-se damunt 8 màquines amb els processadors que tenguin. És a dir, que davant un problema que necessiti més potència de màquina, la solució no sigui posar una màquina amb més processadors, sinó posar més màquines.

Aqui ja no parlar d'aplicacions que executin fils, parlam d'aplicacions que executen processos, de comunicacions entre processos, de particionat de la nostra aplicació de manera que pugui distribuir-se.

Una de les maneres més senzilles que he trobat d'obtenir això és mitjançant els sistemes de missatgeria i de les coes de feina. En aquest cas tenim un o varis servidors que actuen de gestors de les coes de feina i una sèrie de processos que envien tasques a la cua per a ser realitzades, processos que realitzen les tasques i processos que consumeixen els resultats. El GIL no és un problema, el problema és pensar en com s'ha de fer l'aplicació, en com distribuir les càrregues entre els servidors, en definitiva, el problema és d'enginyeria de programari pur i dur. Passam de pensar en dues dimensions a pensar en n-dimensions.

Si hi ha una cosa que té bona Python és la poca distància que hi ha entre voler fer una cosa i tenir la capacitat de fer-la. Així doncs fer programes que facin servir les cues és realment trivial: posam un servidor, el beanstalkc per exemple, les llibreries Python que facin de client i ja ho tenim llest. Separar l'aplicació real per a que vagi en capes i establir un sistema integrat de control, això ja és una altra cosa :)

Quan parlam d'aplicacions web un sistema de coes a més pot fer-se servir per a augmentar l'escalabilitat de la nostra aplicació i donar un millor temps de resposta als nostres usuaris.

Imaginem per exemple una situació típica: la nostra web (feta amb Django, per suposat) quan acaba el procés de compra envia un e-mail a l'usuari amb la factura del que acaba de comprar.

Si no ens hem complicat la vida, tendrem que dins la mateixa vista que guarda les dades de la compra hem posat una cridada a la funció que genera el pdf amb la factura i la cridada a la funció que l'envia.

Encara que la factura es generi força ràpid, generar i enviar el pdf pot ser un problema si tenim molta càrrega, consumeix cicles de CPU que estam llevant als visitants de la nostra web.

En aquest cas podem tenir una maquina o vàries destinades a la generació i enviament de les factures. La nostra aplicació web sols envia a la cua (a una altra màquina o màquines) la petició de que s'ha de fer la factura, i els processos que tenim escoltant a la cua de treballs generaran i enviaran la factura.

Com que l'enviament del treball a la cua de treballs és pràcticament instantani, l'usuari té la sensació de que la web ha respost molt ràpidament. Com que tenim màquines dedicades per a la generació de les factures aquestes també es generen força aviat i s'envien. Mentre hem deixat el servidor (o servidors web) descarregats per atendre més peticions. Hem escalat!

És un exemple típic, com veis l'escalabilitat no s'ha aconseguit posant més màquines que fessin de servidors d'aplicacions Django o posant més processadors, sinó separant les tasques en màquines especialitzades. Si parlam de parsejar XML la cosa és encara més divertida, a l'article [High-performance XML parsing in Python with lxml] (http://www.ibm.com/developerworks/xml/library/x-hiperfparse/) de la web d'IBM i gairebé a les acaballes també ens dóna la pista: l'estratègia de dividir i conquerir; una altra vegada més pensar en com feim les coses.

Aquest és un apunt damunt escalabilita, Python i Django, però perfectament podríeu substituir Python pel vostre llenguatge de capçalera i Django pel vostre bastiment web preferit, Python fa fàcil provar totes aquestes coses, però el realment important és adonar-se de que es poden fer.

blog comments powered by Disqus