Geany, editor per a programació


Escrit per Aaloy a 25 de April , 2011 a les 12:23 p.m.

Aquestes festes he estat mirant-me l'editor Geany per veure com responia a les meves necessitats de tenir un editor per a programació fonamentalment Python i Django que fos a la vegada potent i que tingués baixos consums de memòria.

En un editor per a programació crec que és important seguir el principi de Pareto o regla del 80-20, és a dir, vull un editor que amb el 20% de comun de recursos tengui el 80% de les funcionalitats d'un IDE com Eclipse+Pydev o PyCharm per exemple.

Avui en dia el meu editor de capçalera és Vim/Gvim totalment personalitzat amb la configuració que podeu trobar a trespams-vim, crec que és una bona configuració, però tot i la potència de Vim tanmateix no faig servir ni un 20% de les possibilitats que m'ofereix l'editor. El que sí que crec que és important és dominar-lo, ja que de tant en tant convé editar via ssh i saber fer anar vim amb condicions és un avantatge.

La cosa doncs és que vaig decidir donar una altra ullada a Geany, ja que vaig veure a la web que havien llançat una nova versió, la 0.2 més moderna que la que tenia ja instal·lada a Ubuntu. Una cosa que a mi en va molt bé és el ressaltat de plantilles per Django (cosa que Gvim té), així que per a ser justs, el primer que vaig fer va ser mirar si Geany també ho tenia: requereix una mica de configuració, però sí, us explic:

Cercant per Google vaig arribar a la plana de drevans, on explica com podem activar el ressaltat, és prou senzill, basta fer

cp /usr/share/geany/filetypes.html  ~/.config/geany/filedefs/

editar l'arxiu que acabam de copiar i cercar la secció lexer_properties i afegir

lexer.html.django=1

Amb això ja tenim colorejat per la sintaxi de plantilles Django. Una cosa ja feta.

Superat el primer obstacle ja sols és cosa de veure quin conjunt de característiques té Geany comparat amb altres editors o IDEs i quines no té, i el grau d'importància relativa que tenen per mi. Deix de banda coses que podem donar per pressuposades a un editor modern: ressaltat de sintaxi per múltiples llenguatges (fonamental ressaltat de javascript dins html) i edició de múltiples documents.

  1. Gestió de projectes. És una característica que classificaria com a important. Estalvia molt de temps que l'entorn et situi directament al directori i mantengui la llista dels darrers arxius que es van obrir al projecte.

  2. Treball amb UTF-8 i format Unix. La nostra configuració de feina per defecte és UTF-8, quatre espais per tabular i salts de línia en format Unix. Si ja no té això no me mir l'editor, així que és una característica obligatòria.

  3. Autocompletat. Realment no necessit que tengui un autocompletat de llibreries (al cap i a la fi Python no és Java) però si ho té millor, i sobretot el que va molt bé és tenir un autocompletat basat en que un ja ha escrit en el document, ja que evita molts errors tipogràfics.

  4. Reasaltat de sintaxi per HTML i Javascript dins el mateix document El ressaltat de sintaxi va molt bé a l'hora de programar, pots detectar errors sols pel colorejat de l'editor, per això és important que a l'hora d'editar HTML on cada cop és més comú que hi pugui haver javascript, el ressaltat sigui prou inteligent per detectar que estic a la part javascript del codi i adapti també el ressaltat.

  5. Integració amb un comprovador de sintaxi per Python com pylint o pyflakes i pep8. Es pot fer la comprovació per línia de comandaments, però és interessant no tenir que sortir de l'entorn. És doncs una característica interessant però no fonamental.

  6. Parseig de símblos Va molt bé que un editor per a programació sigui capaç de parsejar el codi font i et mostri les classes i funcions que tens definides dins el document, estalvia molta feina a l'hora de navegar pel codi o trobar el que t'interessa. No és una característica fonamental, però pot ajudar a decidir.

  7. Maneig de bookmarks Cada cop faig servir més aquesta característica a Vim ja que em permet navegar ràpdament entre distintes seccions del codi. No és fonamental però també molt convenient.

  8. Cerca potent De les millors que he vist són les d'Eclipse i Netbeans que et permeten cercar per tot el projecte.

  9. Baix consum de recursos. Per mi és important poder fer servir l'editor en qualsevol dels equips que tinc. Fer feina sempre amb el mateix editor fa que a poc a poc un s'ho vaig fent seu i n'aprofiti millor les funcionalitats. Si triam un editor gràfic hem de tenir en compte que a més convindrà dominar un poc les quatre coses d'un editor en moda consola com Vim. Si l'entorn consumeix molts recursos ens podem trobar que no hi hagi prou memòria per engegar altres aplicacions que necessitam, sobretot en equips més vells. Vaig deixar de fer servir Eclipse i després Netbeans per aquest motiu. Per fer modificacions xorres necessitava esperar gairebé un minut per posar tot l'entorn en marxa. Netbeans a més ha deixat de suportar Python, així que ho he descartat tot i les darrers millores.

  10. Integració amb control de versions Interessant però com en el cas del comprovador de sintaxi o precompilador és quelcom que sovint és més ràpid fer per línia de comandaments.

La resta de característiques que pot tenir un IDE poden estar molt bé i potser un les fa servir un cop o dos al llarg d'un projecte, però per mi i amb el tipus de projectes que feim, crec que no compensen el tenir que carregar amb un entorn feixuc.

Geany compleix amb gairebé totes les funcionalitats que he exposat aquí, fins i tot l'autocompletat va un poc més enllà i es capaç d'autocompletar a partir de les llibreries Python. La integració amb Pyflakes y Pep8 es pot fer i els missatges d'error o avís apareixen a la finestra de missatges. Tot i això he de dir que li faltaria ponder fer clic damunt un missatge d'error i anar directament a la línia, per això s'ha de configurar un poc, anirem a la secció Munta i a on diu "Error regular expression" posarem (.+):([0-9]+):[0-9]+ això ens servirà tant per pyflakes com per pep8, de fent a la meva configuració actual tinc com a compilador pyflakes "%f" associa a la tecla F8 i associat a F9 pep8 "%f" per saber si es compleixen les convencions de codi.

El que he trobat molt úlil a Geany és que té una secció on pots veure tots els documents que tens oberts classificats en la carpeta on es troben. Quan fas feina amb Django on tots els models són models.py et permet navegar ràpidament pels arxius que tens oberts.

Genay també ve amb un conjunt de plugins per estendre la funcionalitat de l'editor. El més interessant que he trobat és un formatejador d'XML, ja que m'estalvia tenir que fer servir un altre programa i realment no carrega gens l'editor.

Geany té també la possibilitat de definir plantilles de codi, com entorns molt més grans i que és una de les característiques que m'agraden més de Vim. D'entrada el conjunt de plantilles que duu per defecte són molt poques, però és molt bo de fer crear-ne més.

En conclusió, Geany és un editor potent, senzill de fer anar i amb un consum de recursos de màquina realment petits. Me pareix que serà el meu proper editor de capçalera.


Traducciones/Translations by apertium

2 comentaris, 0 trackbacks (URL) , Tags: Python Django


Celery, Redis and Django


Escrit per Aaloy a 03 de April , 2011 a les 9:46 p.m.

Disclaimer: This is my first English post is a free translation of the original catalan post

In previous posts have written about Celery and Django Celery, a system to manage queues and tasks in Python and Django.

Celery in its documentation recommends RabbitMQ as message broker, that is, as the application that receives and distributes the tasks that the application sends between the different workers we have configured in our system.

Once the worker has done the task it leaves the result (if we have configured to do it) to the results backend, usually it is the same one as the message broker, that is RabbitMQ acts as a message broker and as a result backend.

The architecture of Celery is very powerful in the sense it allows us to scale up and down and replace the parts we need to configure the application to our needs. So we could have applications that needs some sort of message or task distribution, but they don't need to deal with the complexity nor the system requirements of RabbitMQ. With Celery we can even use a database as a message broker where could save the results, we can replace the serialization routines, the results storage. So, although in the documentations we have a prefered configuration we can change it the needs of our application.

In this post I'll try to present is a configuration that fits in the middle of the complexity of a RabbitMQ solution but enough powerful to fit most application needs.

What's the problem we'll try to solve?

We have an application that we want to run in an small server or in a shared server that needs some sort os distributed tasks or periodic task than we want to manage inside the application itself. We would like:

  • Minimum complexity to install and configure the task system.
  • We'd like not to have a dedicated broker.
  • We'd like to monitor what's happening in our application
  • We'd like to manage our system easily.
  • We'd like to debug our application and run everything on a local server before run the application using a distributed task configuration.
  • We'd like our task broker could have very low memory requirements

We can imagine lots of scenarios in what that requirements would fit, a news aggregation, an e-comerce application that needs to send the invoices, an small document management system that makes some sort of format translation. That is, systems that need a small response time to the user and that could make the heavy task in an asynchronous way, where the reliability of the tasks system is not critical for the application

For that kind of applications Celery with RabbitMQ is overkill, so we're going to diet it a bit

The broker

We want the distribution of tasks to be powerful and flexible, but without the complexity of RabbitMQ. So what will be do is install Redis , a NoSQL a database that works in a similar way memcached does.

Redis is very fast and comsumes few machine resources, allows the persistence of periodic data and the application is generic enough to be used in our applications in addition to task management. A [presentation by Simon Wilson] (http://simonwillison.net/static/2010/redis-tutorial/) summarizes very well the possibilities of this database.

Redis has, however, and important requirement that we must know: in its standard configuration requires that all data has to fit in memory and that periodically synchroniZes the changes to disk. So we must monitor our application to be sure that Redis does not grow without notice consuming all the available memory.

Installing Redis

Readis is present in major Linux distribution, and in Debian based distros is enough to type

sudo apt-get install redis-server

as we're going to use Redis in Celery we must install also the Python API

pip install redis

inside our virtualenv (I suppose everybody is using virtualenv ...)

In a brand new installation in a Ubuntu 10.10 redis consumes 3271B of virtual memory and 1516B of resident memory in a single process.

In a production environment for sure we would like to configure some parameters:

  • bind, to link the redis instance to an IP
  • loglevel is verbose in the default configuration, in production notice or warning would be enough.

The configuration file for redis is in /etc/redis/redis.conf in the Ubuntu, is extensively documented to allow us to adapt it to our needs.

The results storage

As mentioned Celery also allows us to define where to store our data. Redis is a general purpose database, so in addition to the tasks broker we can use it to save the results of the tasks. As pointed before, we have to monotor Redis if we plan to store lot of data o if we store big results. Redis mantains all the database in memory.

Usually in a task/queue system we want to keep the results a just the time enought to see that everything is going well and then we don't need the results anymore.. That is, the results do not necessarily have to remain in the database, the amount of time we need to keep the results in the database would greatly depend on our application.

Let me explai myself. We use Celery in a B2C application to update the information we have about the hotels. We launch the update information periodicaly to update a the information and each task is able to run another taks. Once the information is received the information is processed. So the results just needs to be in the database the time that a worker needs to process it, after that we can delete it. As the process is quite fast is much simpler to make the results expire in 60 seconds than to write the code to delete it.

If we're need to create a task to send an invoice we do not need to save the invoice in Redis, we just need to update our database to mark the invoice as sent once the worker has finished the pdf generation and the mail is sent.

So if we want to mantain our low memory requirements we have to tune our application to not store a lot of information in the Redis database.

Using Redis as a broker and as a database makes us to reach our objective of reusing the technology, but we can use Redis as a cache backend for Django and to [store sessions]((https://bitbucket.org/dpaccoud/django-redis-sessions/src).

Our settings.py

First at all in our INSTALLED_APPLICATIONS we have to add djcelery and now we have to configure Redis as a broker and database backend.

BROKER_HOST = "192.168.1.33"
BROKER_BACKEND="redis"
REDIS_PORT=6379
REDIS_HOST = "192.168.1.33"
BROKER_USER = ""
BROKER_PASSWORD =""
BROKER_VHOST = "0"
REDIS_DB = 0
REDIS_CONNECT_RETRY = True
CELERY_SEND_EVENTS=True
CELERY_RESULT_BACKEND='redis'
CELERY_TASK_RESULT_EXPIRES =  10
CELERYBEAT_SCHEDULER="djcelery.schedulers.DatabaseScheduler"

import djcelery
djcelery.setup_loader()

192.168.1.2 is the virtual image in which I have installed a fresh Ubuntu and that runs Redis, as in this post I'd like to emulate a simple production environment with two servers. As you can see I have no password protection and Redis runs in its default port.

Note that on BROKER_VHOST we have to configure the database Redis will use for the broker system. It can be the same one as the REDIS_DB but we could choose to have the results and the task communication in different databases. CELERYBEAT_SCHEDULER CELERY_TASK_RESULT_EXPIRES is just 10 seconds, time enough for our purposes. CELERYBEAT_SCHEDULER is configured to allow us to create periodic task from our Django application. As this needs new database tables, we would need to run syncdb to create the tables that the scheduler needs.

Development mode

On development on of the first goals is to be sure everything works properly, so we don't need the noise that the broker and storage puts on our development process. Celery has a special configuration

CELERY_ALWAYS_EAGER=True

so our application would not use nor the worker neither the broker and is executed as a common application, just invokes the task in a synchronous way.

Lets start the workers

When you start with Celery it's important to have a global vision about what's happening in our application. I have found that terminator is a good tool to run our console commands, splitting our terminals in order to see what's happening.

So lets open a console in our application environment and run

python manage.py celeryd -E -B --loglevel=INFO -n w1.d820

This will run a worker, configured to run the default number of processors, which depends on the number of CPUs available on our server. We have configured the worker to send monitoring signals (-S) and to run an additional process to deal with the periodic tasks (-B).

It's important to remark that just one worker can have the -B parameter, so perhaps is better to make this fact more visible and run the periodic task process using a dedicated command

python manage.py celerybeat --loglevel=INFO

Running celerybeat as a standalone process it will inform us about its configuration

[2011-04-03 11:16:46,808: WARNING/MainProcess] celerybeat v2.2.5 is starting.
[2011-04-03 11:16:46,863: WARNING/MainProcess] __    -    ... __   -        _
Configuration ->
    . broker -> redis://@192.168.1.33:6379/0
    . loader -> djcelery.loaders.DjangoLoader
        . scheduler -> djcelery.schedulers.DatabaseScheduler

As we want to monitor the tasks and have more than just one worker is important to name them. This can be done with the -n parameter. I like to add the worker number and the server name. In the example the name of my laptop.

Run a second worker is as easy as:

python manage.py celeryd -E --loglevel=INFO -n w2.d820

 -------------- celery@w2.d820 v2.2.5
---- **** -----
--- * ***  * -- [Configuration]
-- * - **** ---   . broker:      redis://@192.168.1.33:6379/0
- ** ----------   . loader:      djcelery.loaders.DjangoLoader
- ** ----------   . logfile:     [stderr]@WARNING
- ** ----------   . concurrency: 2
- ** ----------   . events:      ON
- *** --- * ---   . beat:        OFF
-- ******* ----
--- ***** ----- [Queues]
--------------   . celery:      exchange:celery (direct) binding:celery

As we can see we have not add the -B parameter and Celery informs us that the beat process is off.

We can increase or decrease the number of default processes that the worker is going to star with the --concurrency parameter. The final number is a matter to test and see.

python manage.py celeryd -E --concurrency=10 -n w3.d820

Monitoring: what's happening in my application?

If we have added logs on our applications in each worker we can check and see the output, but perhaps we have no logs o our workers could be distributed in different servers. Celery provides us with some monitoring that are nice to know. To use such tools the first step is to start the monitoring service:

python manage.py celerymon

celerymon 2.2.5 is starting.
Configuration ->
    . broker -> redis://@192.168.1.33:6379/0
    . webserver -> http://localhost:8989
celerymon has started.

As we can see Celery has started a server on port 8989. We can connect to that server and see the registered workers and tasks. It's some sort of raw information but it could be enough

[{"heartbeats": [1301824037.784225],"hostname": "w1.d820"}, 
{"heartbeats": [1301824018.90294], "hostname": "w2.d820"}]

As we have configured the DatabaseScheduler we could see the tasks in the Django application itself, but there is another tool on colole mode that give us nearly realtime information, the celeryev

With python manage.py celeryev we will start an console application that will show us what tasks are being processed, we can see the result of each tasks and even revoke a task. If we want more control about the monitoring tools Celery provides an API to get the information, and of course you can look at the source code for celeryev.

It's important to monitor also the Redis server

sudo tail -n 100 -f /var/log/redis/redis-server.log

we'll see what's happening on the Redis side,

==> /var/log/redis/redis-server.log <==
[677] 03 Apr 09:56:10 - Accepted 192.168.1.32:38923
[677] 03 Apr 09:56:10 - Client closed connection
[677] 03 Apr 09:56:10 - Client closed connection
[677] 03 Apr 09:56:10 - Accepted 192.168.1.32:38924
[677] 03 Apr 09:56:10 - Client closed connection
[677] 03 Apr 09:56:10 - Client closed connection
[677] 03 Apr 09:56:10 - Accepted 192.168.1.32:38925

Redis provides also a client console, redis-cli that we could use to get more information and make a lot of management task. Some useful commands are:

  • KEYS * shows us the active keys
  • DBSIZE informs us about the size of the active database
  • INFO give us a lot of information about our database, it's really useful to check the memory consumption

    process_id:677
    uptime_in_seconds:5349
    uptime_in_days:0
    connected_clients:14
    connected_slaves:0
    blocked_clients:4
    used_memory:1551228
    used_memory_human:1.48M
    changes_since_last_save:1111
    bgsave_in_progress:0
    last_save_time:1301824662
    bgrewriteaof_in_progress:0
    total_connections_received:509
    total_commands_processed:7060
    expired_keys:0
    hash_max_zipmap_entries:64
    hash_max_zipmap_value:512
    pubsub_channels:1
    pubsub_patterns:0
    vm_enabled:0
    role:master
    db0:keys=8,expires=0
  • FLUSHDB cleans all the database removing all the keys

  • MONITOR shows us in real time what's happening, what commands are being executed, and the keys and information that is stored in the database.

To summarize

With Django, Celery and Redis we have a simple task distribution, scalable and with very small server requirements.

We can use Redis as a broker, as as data store and in other tasks of our Django application: as another database, as a session database, as a cache server.

If we want to work using tasks to split the work we have to

  • Develop our application thinking in tasks and asynchronous processes.
  • Install and configure Redis
  • Run the workers
  • Run celerybeat if we have periodic tasks
  • Run the monitor

And of course we have to monitor all the application. Enjoy!


Traducciones/Translations by apertium

0 comentaris, 0 trackbacks (URL) , Tags: Python Django


Celery i Redis


Escrit per Aaloy a 03 de April , 2011 a les 12:11 p.m.

Link to Celery i Redis

En anteriors apunts he parlat ja de Celery i de Django Celery, un sistema per a la gestió de cues i tasques per Python i Django.

Celery a la seva documentació recomana RabbitMQ com a gestor de missatgeria, és a dir, com a aplicació que reb i distribueix les tasques que li envia l'aplicació entre els diferents worker que tenguem al nostre sistema.

Una vegada el worker ha realitzat la tasca deixa el resultat (si així ho hem indicat) al contenidor de resultats, que normalment serà el mateix que el broker de missatgeria, és a dir RabbitMQ.

L'arquitectura de Celery és molt potent en tant que ens permet escalar cap a baix i substituir peces segons necessitem. Així per aplicacions que necessitin d'un sistema de distribució de tasques però no de la complexitat de RabbitMQ podem utilitzar altres sistemes de notificacions, fins i tot fer servir una base de dades. On es guarden els resultats o com es serialitzen els missatges també es pot canviar. En definitiva, encara que hi hagi una configuració recomanada per a entorns que necessitin de molta potència en el sistema de distribució de tasques i coes, podem personalitzar Celery al nostre gust i a les nostres necessitats.

En aquest article el que presentaré és una configuració a mig camí entre el que seria la configuració més complexa de Celery i una configuració simple basada sols en base de dades.

Plantejant el problema

Tenim doncs una aplicació que no és molt gran, però a la que aniria molt bé tenir un sistema de distribució de tasques.

  • Volem que la instal·lació i configuració sigui senzilla.
  • El que instal·lem si pot ser hauria de poder aprofitar-se per quelcom més que no el sistema de tasques.
  • Volem poder monitoritzar el que està passant.
  • Volem poder gestionar fàcilment l'entorn
  • Hem de poder depurar fàcilment el que està passant i assegurar-nos que l'aplicació funciona sense tenir que muntar tot l'entorn.
  • El gestor de tasques ha de consumir pocs recursos i ser bo de controlar.
  • El gestor de tasques ha de permetre l'execució de tasques periòdiques.
  • Volem poder tenir accés als resultats.

Podem imaginar molts escenaris en que això s'ha de complir, per exemple un agregador de notícies, en un sistema de e-comerce l'enviament de factures, en un petit gestor documental la conversió de formats, ... És a dir, sistemes en els que volem que la resposta cap a l'usuari final sigui el més ràpida possible i que la feina feixuga no necessàriament es tengui que fer de manera síncrona, però on tampoc passa res si el sistema de missatgeria cau i perd alguna tasca, simplement es pot tornar a executar.

Amb aquestes condicions la configuració estàndard de Celery i de Django Celery és massa complexa, així que el que farem és aprimar-la un poc.

El broker

Volem que el sistema de distribució de tasques sigui prou potent i flexible, però sense la complexitat de RabbitMQ. Per això el que farem serà instal·lar Redis una base de dades NoSQL molt semblant al que seria un memcached.

Redis té l'avantatge de que és molt ràpid, ocupa molt pocs recursos de màquina, permet la persistència periòdica de les dades i és una aplicació prou genèrica com per poder ser utilitzada en les nostres aplicacions a més de per fer la gestió de les tasques. Una presentació de Simon Wilson crec que resumeix molt bé les possibilitats d'aquesta base de dades

Redis té un emperò important que hem de conèixer, és una base de dades que en la seva configuració estàndard requereix que totes les dades hi càpiguen en memòria i que aquesta es sincronitzi de manera periòdica al disc. Així doncs hem de procurar monitoritzar la nostra aplicació i l'ús que en fa de Redis per a no consumir més memòria de la que ens vulguem permetre.

La instal·lació de Redis

Redis està com a paquet en les principals distribucions, així que per distribucions basades en Debian bastarà fer:

sudo apt-get install redis-server

i com que també l'utilitzarem des de la nostra aplicació convé instal·lar també el l'API de connexió per Python, amb pip mateix

pip install redis

dins el nostre entorn virtual (perquè està clar que feis servir virtualenv a les vostres aplicacions, no?).

En una instal·lació neta dins una màquina virtual Ubuntu redis està ocupant 3271B de memòria virtual i 1516B de memòria resident a un únic procés.

En producció segurament ens interessarà tocar alguns paràmetres de Redis per fer la configuració més segura:

  • bind ens permet lligar redis a una IP concreta.
  • loglevel per defecte està a verbose, a producció amb notice o warning serà suficient.

l'arxiu de configuració de redis es troba a /etc/redis/redis.conf i està molt ben documentat per a poder adaptar-lo a les nostres necessitats.

On guardam els resultats?

Com hem dit Celery ens permet definir també on guardar els nostres resultats. Donat que Redis és una base de dades de propòsit general, a més de fer les tasques de missatgeria l'aprofitarem per a que guardi els resultats de les tasques.

Aquí hem de tenir en comptes el que dèiem de Redis, si guardam moltes dades i no pensam en anar fent neteja la memòria de Redis anirà creixent fins a ocupar tot el que tinguem.

Normalment a un sistema de tasques i cues ens interessarà guardar els resultats un temps per veure que tot està anant bé i després ja no els necessitam. Es a dir, els resultats no tenen perquè quedar forçosament dins la base de dades Redis, això ja dependrà de la nostra aplicació.

M'explicaré. Una de les aplicacions on feim servir Celery ens permet actualitzar la informació que tenim d'hotels. Es van llançant les peticions d'actualització i el worker se n'encarrega de baixar-se la informació llançant a la seva vegada una altra tasca i de processar-la una vegada l'ha rebuda. La informació sols necessita estar al magatzem el temps just i necessari per poder monitoritzar que tot va bé i que el worker ha rebut i processat la informació.

En el cas de la generació d'una factura no hem de guardar necessàriament el pdf de la factura dins Redis, basta poder dir que la factura s'ha realitzat correctament o directament suposar que ha anat tot bé i periòdicament tornar a llançar les tasques d'enviament per a tots aquells clients que han sol·licitat la factura i no se'ls ha enviada.

Així doncs utilitzarem també Redis per guardar els resultats i configurarem la nostra aplicació per a que no els guardi per sempre.

Amb això ja hem aconseguit que Redis faci una doble funció, però és que a més podem utilitzar Redis per a guardar les sessions de Django o fer-la servir com a Cache. Així doncs estam aprofitant els recursos que és un dels nostres principals objectius.

La configuració del settings.py

A INSTALLED_APPS hem afegit djcelery i per configurar Redis com a broker i com a magatzem de resultats feim:

BROKER_HOST = "192.168.1.33"
BROKER_BACKEND="redis"
REDIS_PORT=6379
REDIS_HOST = "192.168.1.33"
BROKER_USER = ""
BROKER_PASSWORD =""
BROKER_VHOST = "0"
REDIS_DB = 0
REDIS_CONNECT_RETRY = True
CELERY_SEND_EVENTS=True
CELERY_RESULT_BACKEND='redis'
CELERY_TASK_RESULT_EXPIRES =  10
CELERYBEAT_SCHEDULER="djcelery.schedulers.DatabaseScheduler"

import djcelery
djcelery.setup_loader()

El 192.168.1.33 és la màquina virtual on tenc instal·lat Redis, per tal d'emular un entorn de producció amb dues màquines. El port és el port per defecte i no he protegit redis amb usuari i password.

Important, el BROKER_VHOST és per redis el nom de la base de dades que es farà servir. Per defecte Redis fa servir la base de dades zero (0) però res ens impedeix tenir una base de dades diferent per les tasques i una altra pels resultats.

A CELERY_TASK_RESULT_EXPIRES podem veure com hem posat que els resultat expirin als 10 segons, més que suficient per la configuració de l'aplicació.

CELERYBEAT_SCHEDULER ens permet utilitzar la nostra aplicació d'Django per a gestionar les tasques periòdiques. Necessitarem fer un syncdb per a crear les estructures de dades, però a canvi podrem definir períodes i tasques.

Desenvolupant

En desenvolupament ens interessarà tenir molt present que tenim un sistema de coes i tasques, però realment el que més ens interessa és provar que tot funciona

CELERY_ALWAYS_EAGER=True

Aquesta configuració fa que l'aplicació s'executi com si no tingués coneixement del gestor de tasques, la qual cosa ens permetrà crear i depurar la nostra aplicació com sempre hem fet.

Posant en marxa els workers

Per tal de monitoritzar millor el que feim podem utilitzar una aplicació com terminator, una consola que ens permet agrupar consoles i veure d'una ullada el que està passant. A una d'aquestes consoles farem:

python manage.py celeryd -E -B --loglevel=INFO -n w1.d820

Això posa en marxa un worker, configurat amb un nombre de processos per defecte (2 en el meu cas) i li deim que envii els senyals de monitorització (això és el paràmetre S) i que a més engegui un procés addicional per a que gestioni les tasques periòdiques.

Hem de tenir en compte que sols hi pot haver un procés de gestió de tasques periòdiques, així que o bé es llança des d'un sol worker o bé podem fer servir l'aplicació celerybeat

python manage.py celerybeat --loglevel=INFO

Recordau! O una manera o l'altra però no les dues i mai per duplicat a dos workers.

Si l'executam per separat celerybeat ens informa de que està engegat i de las configuració que farà servir:

[2011-04-03 11:16:46,808: WARNING/MainProcess] celerybeat v2.2.5 is starting.
[2011-04-03 11:16:46,863: WARNING/MainProcess] __    -    ... __   -        _
Configuration ->
    . broker -> redis://@192.168.1.33:6379/0
    . loader -> djcelery.loaders.DjangoLoader
        . scheduler -> djcelery.schedulers.DatabaseScheduler

Com que volem controlar i monitoritzar bé el que passa i potser tenir més d'un worker és convenient posar-los nom, això es fa amb el paràmetre -n, a mi m'agrada donarlos un nom junt amb el nom de la màquina.

Arrancaré un segon worker:

python manage.py celeryd -E --loglevel=INFO -n w2.d820

 -------------- celery@w2.d820 v2.2.5
---- **** -----
--- * ***  * -- [Configuration]
-- * - **** ---   . broker:      redis://@192.168.1.33:6379/0
- ** ----------   . loader:      djcelery.loaders.DjangoLoader
- ** ----------   . logfile:     [stderr]@WARNING
- ** ----------   . concurrency: 2
- ** ----------   . events:      ON
- *** --- * ---   . beat:        OFF
-- ******* ----
--- ***** ----- [Queues]
--------------   . celery:      exchange:celery (direct) binding:celery

Fitxem-nos que en aquest cas ens diu que els events estan activat però que no hi ha el beat (el responsable de les tasques periòdiques actiu per aquest worker).

Podem ampliar o limitar el nombre de processos que arranca cada worker amb el paràmetre --concurrency, la configuració per defecte que depèn del nombre de CPUs disponibles sol anar bé, però sempre dependrà de la nostra aplicació i de les limitacions de recursos que li vulguem donar. Per exemple:

python manage.py celeryd -E --concurrency=10 -n w3.d820

Monitoritzant el que passa

Si a la nostra aplicació hem posat logs a cada worker podem veure el que està passant, però potser no sigui així, o tinguem els workers distribuïts a vàries màquines. Per això Celery ens dóna vàries eines de monitorització.

El primer que hem de fer és engegar el servei de monitorització:

python manage.py celerymon

celerymon 2.2.5 is starting.
Configuration ->
    . broker -> redis://@192.168.1.33:6379/0
    . webserver -> http://localhost:8989
celerymon has started.

Si anam al servidor web que ha engegat Celery, podem veure un resum de les tasques i dels workers. Per exemple, en el nostre cas:

[{"heartbeats": [1301824037.784225],"hostname": "w1.d820"}, 
{"heartbeats": [1301824018.90294], "hostname": "w2.d820"}]

Podem veure que hi ha dos workers actius.

Si hem fet servir el DatabaseScheduler veurem les nostres tasques dins la pròpia base de dades de Django, però a més hi ha una eina de consola d'allò més interessant celeryev

Amb python manage.py celeryev posarem en marxa una consola en la que ens informarà del que està passat, el nombre de tasques que hi ha executant-se i podrem veure informació damunt la tasca o eliminar (revoke) una tasca de la cua.

Si volem saber més coses o fer les nostres pròpies eines de monitorització Celery ens dóna tot una API per fer-ho, així que no estam limitats a les eines de sèrie.

El que ens queda també per monitoritzar és què està passant amb Redis

   sudo tail -n 100 -f /var/log/redis/redis-server.log

ens informarà del que està passant i de les connexions que es realitzen.

==> /var/log/redis/redis-server.log <==
[677] 03 Apr 09:56:10 - Accepted 192.168.1.32:38923
[677] 03 Apr 09:56:10 - Client closed connection
[677] 03 Apr 09:56:10 - Client closed connection
[677] 03 Apr 09:56:10 - Accepted 192.168.1.32:38924
[677] 03 Apr 09:56:10 - Client closed connection
[677] 03 Apr 09:56:10 - Client closed connection
[677] 03 Apr 09:56:10 - Accepted 192.168.1.32:38925

Si volem anar més enllà podem fer servir la consola de Redis, redis-cli

Algunes comandes molt útils:

  • KEYS * - ens monstra les claus que tenim actives.
  • DBSIZE - ens diu com està el tamany de la nostra base de dades
  • INFO - ens dóna tot un conjunt d'informació de com està la nostra bd, és especialment interessant veure i monitoritzar el tamany de la memòria.

    process_id:677 uptime_in_seconds:5349 uptime_in_days:0 connected_clients:14 connected_slaves:0 blocked_clients:4 used_memory:1551228 used_memory_human:1.48M changes_since_last_save:1111 bgsave_in_progress:0 last_save_time:1301824662 bgrewriteaof_in_progress:0 total_connections_received:509 total_commands_processed:7060 expired_keys:0 hash_max_zipmap_entries:64 hash_max_zipmap_value:512 pubsub_channels:1 pubsub_patterns:0 vm_enabled:0 role:master db0:keys=8,expires=0

  • FLUSHDB - per netejar tota la base de dades activa de Redis.

  • MONITOR - ens mostra què està passant, les claus que es generen, els resultats i les sentències que va executant Redis.

Conclusions

Amb Django, Celery i Redis hem aconseguit tenir un sistema de distribució de tasques simple, escalable i amb molts pocs requisits de màquina.

Redis es pot aprofitar tant pel sistema de cues com per la nostra aplicació, obrint-nos tot un món de possibilitats i mantenint baixa la complexitat de tota l'arquitectura.

Posar en marxa tot el sistema implica:

  • Desenvolupar l'aplicació pensant en les tasques
  • Configurar Redis
  • Executar els workers
  • Executar celerybeat per les tasques periòdiques si en tenim
  • Executar el monitor

I òbviament anar monitoritzant-ho tot. Que ho disfruteu!


Traducciones/Translations by apertium

1 comentari, 0 trackbacks (URL) , Tags: Python Django


Canvi d'oficina


Escrit per Aaloy a 03 de April , 2011 a les 12:23 a.m.

Link to Canvi d'oficina

Aquest divendres passat hem finalitzat la mudança de l'antiga oficina d'APSL, 22 m² de l'Edifici Naorte del Parc Bit que teníem en règim d'incubació cap a la nova oficina, a l'Edifici NTIC, a 100 metres escasos, i ja de prop de 50 m². És una oficina compartida amb Pablo, de Pixelgrafic, no sé si se'n podrà dir co-working però la veritat que si assembla molt.

Encara ens quedaven un grapat de mesos en règim d'incubació al Parc Bit, però amb la incorporació de Juan (aka morenosan) ja ens tocava a poc més de 5 m² per barba i ens impedia rebre als clients i amics que ens venen a veure en condicions. Ara encara ens queda condicionar un poc més el nostre espai, ens falta encara una estanteria o dues i una taula, però temps al temps, el pressupost hi ha d'arribar i per ara era molt més necessari dotar a Juan de bones eines per fer feina, potser encara no tenim les estanteries, però Juan té un i5 amb 6 Gb de RAM i dos monitors de 23 polzades.

Alguns m'heu demanat si farem festa d'inauguració, la veritat és que m'agradaria, però hem de tenir en compte primer el fet que és una oficina compartida i no volem destorbar el nostre company i per l'altra, i potser més important, que les properes setmanes tenim dates d'entrega per a dos projectes i no ens sobra el temps.

Però tot arribarà, potser no farem acte d'inauguració, però alguna cosa farem, hi ha una terrassa molt gran al pis i hem de pensar com aprofitar-la. El que sí he de mirar encara és si encara podrem aprofitar les sales d'actes del Parc Bit, en sortir d'aquestes entregues volem de mirar de fer el primer Creant Bits d'enguany.

El canvi d'oficina també representa un nou repte, passam d'un lloguer molt assequible a un lloguer ja a preus de mercat, amb un contracte mínim d'un any i això significa molta més responsabilitat. La veritat és que estic molt agraït a l'oportunitat que ens ha donat el Parc Bit amb l'incubadora, ens ha donat l'oportunitat de saber si el nostre projecte era viable sense tenir-hi que invertir una gran quantitat inicial. Ara sabem que el projecte és viable, que muntar una empresa dedicada a la programació amb opensource té mercat i que a les nostres contrades també es poden dur a terme projectes importants fent feina amb Python i Django. Poser al final l'època de crisi en que ens trobam ens la jugarà, però no serà perquè la tecnologia o la idea no sigui vàlida.

Estam molt contents de poder fer feina amb Python i Django i al mateix temps encantats del rendiment que ens està donant la tecnologia i l'aprofitament dels servidors que tenim. Poder fer feina d'aquesta manera fa que un s'aixequi al matí i vagi a la feina més content, i sobretot que en surti amb la sensació d'haver fet quelcom de profit.

Així que si anau a l'oficina antiga i no em trobau no oblideu passar per l'NTIC, planta 2, despatx A, al carrer Ada Byron, encara que es digui NTIC l'edifici és ben nou!


Traducciones/Translations by apertium

1 comentari, 0 trackbacks (URL)