Archivo

Archive for the ‘programación’ Category

La compleja coreografía porque presionaste la letra A

abril 29, 2014 19 comentarios

Tu teclado detectó que presionaste la letra A, sus chips lo codifican en un scancode, este código es convertido en un señales eléctricas que se transmitirán por el cable USB al controlador que está conectado a la placa del ordenador. Este controlador detecta las señales eléctricas, las reconstruye en números binarios que almacena en un área de memoria del dispositivo, a continuación genera una solicitud de interrupción (IRQ) que será transmitida al microprocesador.

Esta interrupción está codificada y se recibe en el procesador en unas pins especiales para ellas, cuando llega la generada por la tecla que presionaste el procesador decide a qué core o procesador enviar esa petición (enrutamiento de interrupciones). Éste interrumpe lo que estaba ejecutando en ese momento,  analiza el IRQ, accede a una tabla de interrupciones (que fue rellenada cuando el sistema operativo se inició) donde le indica la dirección de la rutina del kernel que debe ejecutar. Cambia los registros necesarios, posiblemente invalida (flush) las cache y TLB del proceso anterior, cambia el nivel de ejecución del procesador a uno de con más privilegios y pasa a ejecutar la dirección indicada en la tabla de interrupciones.

La rutina del núcleo del sistema operativo analiza los registros y llama al gestor del controlador USB, que puede acceder a la memoria del dispositivo vía instrucciones de E/S del procesaor para que copie los datos a la memoria RAM. También llamará al gestor específico de teclado por USB (lo más probable es que sea el usbhdi) que convierte el scancode original en un código de caracteres vía una tabla de conversión (o mapa del teclado).

Una vez realizada las operaciones de transferencia de datos desde el dispositivo, se llaman a las rutinas de E/S de caracteres del núcleo. Éstas analizan qué proceso es el que debe recibir esa entrada de teclado, si usas un GNU/Linux con interfaz gráfica el proceso es el servidor X (X.org), copian los datos al área de memoria de dicho proceso, lo desbloquean y llaman al scheduler para que decida qué proceso debe ejecutar a continuación.

Al desbloquearse el proceso, éste pasa de la lista de procesos bloqueado a la lista de procesos listos para ejecutar. Allí el servidor X competirá por el procesador con otros procesos, eventualmente será seleccionado por el scheduler, este procederá a preparar al procesador (o núcleo) para que lo ejecute (cambio de contexto o context switch), invalidará las caches del proceso anterior, preparará las tablas de páginas básicas, cambia el privilegio del procesador al de uno de proceso normal y finalmente transfiere el control al proceso X.

Éste continúa su ejecución desde la llamada epoll o select que hizo para recibir E/S, analiza los datos que le dejó el sistema operativo y decide que es un letra picada en el teclado (el editor de texto, o la terminal, o el navegador web….), analiza cuál era el proceso interactivo que tiene la ventana activa en ese momento, codifica el evento en el protocolo X11, y se lo envía a dicho proceso vía memoria compartido o socket UNIX.

Al enviar el mensaje a otro proceso, se llama otra vez a una rutina del sistema operativo en un proceso similar al IRQ inicial, pero esta vez iniciado por una instrucción especial (interrupción por software) que hace que el procesador la trate de forma similar, selecciona un procesador para que la trate, analiza el código de interrupción y los registros que dejó el programa, cambia a modo privilegiado y llama a la rutina del kernel que tratará esta interrupción (posiblemente las de UNIX socket).

Esta rutina mira en las tablas de sockets cuál es el proceso receptor (el editor, terminal, navegador…), copia los datos necesarios, desbloquea al proceso moviéndolo a la cola de listo para ejecutar y llama al scheduler.

Eventualmente el proceso que debe recibir esa letra A es seleccionado por el scheduler, pasa a ejecución, continúa su ejecución desde el select o epoll, analiza la entrada, decide que hay que mostrarlo en pantalla, codifica la información necesaria (caracter, tipo de letra, posición, color, etc.) y la envía nuevamente -mediante un mensaje en protocolo X11- al servidor X.

Se repite de nuevo el proceso, interrupción de software, llamada a una rutina del núcleo y desbloqueo del servidor X que eventualmente es ejecutado.

Éste analiza el mensaje, detecta que tiene que dibujar una letra en la pantalla y llama a sus rutinas de dibujo de fuentes TrueType. Estas rutinas recuperan la información de la fuente necesaria (consisten de puntos en 2D), aplican los fórmulas necesarias que definen cómo debe dibujarse en la pantalla y llaman a las rutinas de DRI del kernel que lo harán, vía ayuda del gestor de la placa gráfica, en un complicado procedimiento de sincronización entre el servidor X, el gestor de la placa y la propia placa gráfica (que es otro ordenador muy potente y complejo, con su propio “sistema operativo”).

La letra A es dibujada así en la memoria del back buffer de la tarjeta, también se dibujan las otras ventanas con complicadas combinaciones y copias (compositing) para intentar minimizar todo lo que hay que re-dibujar. Cuando el back buffer está completo, se notifica a la placa gráfica que lo intercambie con el front buffer (lo que se visualiza por la pantalla), ésta espera que llegue el momento justo de sincronización con el monitor (para que no parpadee con mezcla de imágenes de ambos buffers) y finalmente hace el cambio y puedes ver lo que esperabas:

La letra A

Esta maravillosa coreografía de sincronización y paso de información ocurre cada vez que presionas una tecla, o mueves el ratón un pixel, o se empieza a bajar una imagen de la web. Y no sólo en tu PC o Mac, ocurre lo mismo en tu teléfono móvil, tu router WiFi, tu lector de libros, o tu smartwatch.

Todo esto que acabo de explicar ya funcionaba prácticamente igual desde finales de los años 70. Explico estas interacciones y algoritmos en mis clases de sistema operativo desde hace más de 20 años, pero nunca deja de maravillarme al nivel de complejidad y sofisticación al que hemos llegado en pocas décadas de informática.

 

 

 

Una técnica útil para el programador solitario (o sea, yo)

abril 24, 2014 13 comentarios

No sé si os pasa a todos, yo creo que sí, pero tenía serios problemas de organización y productividad en el desarrollo de Menéame. Quizás sea un caso especial, es un sistema complejo:

  • software relativamente grande y soy básicamente el único programador responsable de todos los módulos,
  • diversidad de lenguajes, PHP para la web, Python para scripts y programas “off line”, Perl por herencia de hace años,
  • base de datos grande e imposible de hacer alteraciones de las tablas por el tamaño de las mismas (ya veremos con el MySQL 5.6),
  • mucha manipulación de datos en la base de datos,
  • interacciones complejas de usuarios,
  • muchos controles de entradas y acciones de usuarios “externos”,
  • los usuarios piden muchas modificaciones, correcciones y detectan bugs que ni se te pasaron por la cabeza que podían ocurrir,
  • cada vez que se implementa una nueva característica (cada vez más complejas), aparecen nuevos bugs y sobre todo, los usuarios demandan muchas modificaciones y ań nuevas características complementarias.

Con todo esto, a veces me ocurría que me bloqueaba porque no sabía por dónde comenzar, o que pasos seguir, o cuál era el trabajo pendiente, cuáles son importantes, cuáles son urgentes, y cuáles secundarios que pueden esperar hasta tener ese momento de inspiración. Soy bastante desorganizado, y odio profundamente usar programas (los tipos “gestión de tickets”) para esto. Ya demasiado tengo con ventanas de editores, consolas de administración y páginas de manuales para encima tener que estar buscando una ventana perdida para ir leyendo y apuntando lo que estoy haciendo.

Leer más…

Tendencias (“trends”) históricas del uso de palabras con Sphinx

febrero 13, 2014 4 comentarios

Hace unos días quise saber desde cuándo se empezó a hablar de desahucios y suicidios en la prensa en España. Fui a Google Trends y el gráfico mostraba una evolución demasiada plana, que no se correspondía con tantas noticias que leímos en la prensa española. Me pregunté si, y cómo, podía obtener esas estadísticas en Menéame. Se me ocurrió que debería haber un truco relativamente sencillo usando los índices de de búsqueda de Sphinx (lo usamos para el buscador de Menéame). Así fue que en pocas horas pude implementar un sistema similar a Google Trends en Menéame.

Esto es lo que salió con las tendencias de esas dos palabras por su frecuencia de aparición por meses:

Evolución de suicidios y deshaucios

Leer más…

No basta con ser ingeniero (y II), un ejemplo práctico

noviembre 30, 2013 7 comentarios

Hace unos días ya comenté el problema de que eliminaron una función importante en KitKat con la excusa de que no estaba documentada y por lo tanto “no oficial”, pero es una limitación seria para millones de usuarios y casi una traición para miles de desarrolladores. Hoy veo el siguiente comentario en el hilo del bug:

You broke file-uploading and released 4.4 without a ready replacement or workaround? O_o

So even if app devs manage to hack around it, they’ll have to maintain the hack forever to support phones stuck on 4.4 even after 4.5+ introduces a proper replacement function?

I need a Kitkat bar.

Es una observación clave.

Una pésima decisión de los ingenieros tendrá consecuencias negativas a largo plazo para desarrolladores, usuarios, y hasta toda la plataforma. No lo meditaron, todavía no se han percatado que las decisiones de ingenieros tienen efectos muy reales sobre las personas. Por eso, para ser un ingeniero hay que ser más que un ingeniero.

De nuevo queda en evidencia que los programadores vamos muy justitos en el tema, incluso para el nivel de programadores del sistema Android. Me genera una mezcla de decepción y cabreo, y me hace admirar cada vez más las “visión social” a largo plazo de Linus Torvalds: literalmente se enfurece cuando alguien le propone cambiar la interfaz (ABI) del kernel Linux que genera incompatibilidades con aplicaciones existentes, aunque tengan más de 10 años. Eso es ser más que un ingeniero.

PS: La única opción para remediar el problema es que parcheen las librerías de Android Kitkat para re-implementar la función openFileChooser() que eliminaron. Otra cosa es que asuman el error y lo hagan. Lo dudo, ojalá esté equivocado.

Android KitKat… ¿pretenden matar el HTML5 en Android?

noviembre 27, 2013 13 comentarios

La pregunta no es tan sensacionalista como parece. Hace unos días me avisaron de problemas para subir fotos a Menéame con Android KitKat. Era muy raro que diese problemas, está todo programado respetando estándares de HTML5 y Javascript. Descubrí que ese caso se debía a problemas de la gestión de memoria de Android y cómo la trataba Chrome (al ejecutar otro programa para seleccionar la imagen, si necesita memoria se la quita al Chrome, por lo que hay un “cambio de configuración”, al volver a Chrome, éste recarga la página completa, en vez de “reconstruir” lo que tenía). Pero descubrí otro error aún peor y que sucede siempre: es imposible subir una fotografía. Lo probé con el Nexus 4 y con el 7, en ambos el mismo problema, da un error “fatal” al seleccionar cualquier foto.

Lo probé con el Firefox sobre los mismos dispositivos, y no hubo problemas (además de sorprenderme la velocidad de Firefox, ¡cómo ha mejorado!). Se puede observar el fallo (“Error abrir archivo seleccionado” [sic]) en el siguiente vídeo que hice en el Nexus 4:

Visto lo visto, y que no parecía simple de solucionar, además que quería solucionar lo de compartir más fácilmente a Menéame desde un móvil, me decidí a desarrollar una pequeña app:

app Menéame de pruebas

Esta app sólo crea una actividad, basada en WebView, que empotra el renderer HTML. Hasta la versión 4.3 de Android, este renderer era el del “webkit” básico, a partir de 4.4 (KitKat) ya se usa el Chromium (el proyecto libre del Chrome). Todo iba bien, y funcionaba muy rápido… hasta que probé la subida de ficheros: imposible, no funciona en KitKat, y es imposible arreglarla (al menos en teoría y con la información que hay hasta ahora).

Las WebView tienen una pequeña interfaz con unas pocas clases de Java para controlar cosas básicas, y también para que el programa haga algunas de las cosas que no hace la vista por sí misma, por ejemplo, seleccionar ficheros para el <input type=”file”> de HTML. Resulta que no había un API para ello, pero dado que es imprescindible para casi cualquier aplicación HTML5, la gente analizó el código fuente del navegador estándar de Android y encontró la función que se llama cuando se selecciona el campo de subir fichero. La implementé tal cuál, adaptadas a las diferentes versiones de Android:

WbeChromeClient

Pero no funcionaba en KitKat, sólo en las versiones anterior, sin problemas. En KitKat ni se llaman esas funciones, no hace nada cuando se selecciona el campo.

Así fue que busqué, y veo que eliminaron esa interfaz, sin ninguna alternativa. Sólo dicen “no estaba documentada como oficial, y ya pensaremos una alternativa para futuras versiones de Android”. En los comentarios queda claro cómo afecta a tantas aplicaciones, sobre todos a las de PhoneGap, que están basadas completamente en HTML5: con KitKat es imposible subir ficheros de apps programadas en HTML5.

Sumado a eso, el propio Chrome de Google también falla para subir imágenes.

Es decir, miles de apps que dejarán de funcionar en Android KitKat, por decisiones [estúpidas] de eliminar la única interfaz posible para poder subir ficheros desde el “navegador empotrado” para apps, y por fallos increíbles en el navegador por defecto, Chrome.

La pregunta es: ¿están perjudicando así a aplicaciones en HTML5 por simple estupidez? ¿O es una estrategia para que se usen apps completamente nativas? No hay otra explicación, en cualquier caso, vaya ceguera y/o ineptitud enorme de los ingenieros que toman decisiones de desarrollo en Android. Para miles de :facepalm:.

PS: Mientras tanto, si tenéis Android KitKat y queréis subir fotos en Menéame o cualquier otro sitio, tenéis que usar Firefox u Opera Mini. Si habéis desarrollado una app que usa WebViews, estáis jodidos, porque no hay otra alternativa, al menos hasta que salga el GeckoView for Android, pero le falta todavía mucho tiempo :(

Nota: cómo hacer esos vídeos de la pantalla.

Técnicas y trucos para la versión móvil “responsive” del Menéame

noviembre 18, 2013 19 comentarios

No sé si habréis notado, pero si accedéis a Menéame desde un móvil o tableta, se carga muy rápido y están disponibles prácticamente todas las funcionalidades de la versión “normal” de la web. Aunque en realidad no se tratan de dos versiones diferentes, es la misma pero con cambios muy pequeños en la lógica del servidor, y muy poco de Javascript.

El 30% de los accesos a Menéame son desde móviles, antes teníamos una versión más reducida (sigue disponible en m.meneame.net), pero recibíamos quejas por ser muy limitado en cuanto a funcionalidades. Por otro lado, era demasiado trabajo mantener dos versiones diferentes.

También queríamos adaptar la web para los monitores Retina y de alta definición que tienen la mayoría de teléfonos y tabletas de gama media y alta (su densidad de pixels por pulgada es mayor -hasta dobla- a los típicos 96 px/pulgada de los monitores tradicionales), para ello hay que detectarlos y servir en estos casos una imagen del doble de resolución.

Así, hace unas semanas nos pusimos a tope para lograr una única versión integrada, con pocas diferencias en la lógica del backend, y casi ninguna modificación hecha con Javascript en el lado cliente. Aunque el PageSpeed no es una medida cualitativa absoluta, sí que da bastante idea de velocidad y ligereza:

Image

Como se puede deducir, las mejoras de velocidad de carga para móviles también afectó positivamente a la versión normal del web. A continuación describiré cuáles fueron los trucos y técnicas más importantes.

Leer más…

Para ser ingeniero no basta con ser ingeniero (y los programadores vamos justitos)

octubre 29, 2013 50 comentarios

Hace una hora iba conduciendo, llevaba mi teléfono en el bolsillo delantero derecho del pantalón, de golpe empieza a vibrar y sonar. Una vez, dos, tres, cuatro… parecía que llevaba se había desatado una batalla campal entre mis pantalones (y no eran mis tripas ni el Viagra). Me empiezo a asustar, debe ocurrir algo grave para que alguien conocido me esté escribiendo de esa manera, pensé que podía ser problemas de familia o Menéame (que ni aún así insisten tanto).

Detuve el coche en cuanto pude, saqué el teléfono, era el Hangouts (el reemplazo de Google Talk para Android) de Google. Me habían metido en un texto-vídeo hangout con muchas personas (no sé cuántas, pero eran muchas),  todos escribiendo a la vez. Después del susto que me pegué, ¡qué cabreo! Primero con el irresponsable (no sé quién fue, salí inmediatamente) que abrió una vídeo conferencia de muchas personas. Pero luego lo pensé mejor.

¿Cómo es posible que un programa me meta automáticamente en un sala de vídeo conferencia? No lo podía creer. Nunca había configurado nada así. Voy a mirar la configuración del Hangouts -que recuerdo que es un reemplazo del Gtalk de Android- y veo que Google, y sus programadores, decidieron que me iba aceptar automáticamente conversaciones de toda la gente que tengo en mis círculos de Google+, y ¡también a la que no!. También incluye a las que tengo en “My Stream” (gente a la que sólo sigo sus publicaciones en G+).

Alucinante.

Nunca quise eso (en GTalk sólo me podían escribir a los que tenía autorizado), me meten en una sala con mucha gente y a la que ni conozco por el apodo en internet, y en su momento tampoco agregué a gente en mis círculos -o en “My Stream”- para que me puedan abrir automáticamente vídeo conferencias. No sé quién es el genio al que se le ocurrió eso, pero obviamente lo han tenido que implementar programadores. Un burrada que difícilmente se deje pasar tan fácilmente en otras ingenierías.

Estamos rodeados de programas informáticos, no podemos hacer nada sin ellos, y con los móviles estamos “abiertos” al mundo las 24 horas.  Cualquier cosa que haga un ingeniero/programador tiene efectos reales sobre la gente. Te puede molestar y asustar cuando vas en coche, o despertarte cuando estás durmiendo, o molestarte en medio de una reunión o clase. Hasta hace poco teníamos razonablemente bien controlado, hay un botón u opción rápida para que las llamadas no suenen. Pero es bastante más complicado hacer que todas las aplicaciones no molesten (tampoco tiene sentido estar deshabilitando continuamente la capacidad de que te avise si tienes un Whatsapp o chat). Las cosas empeoran cuando te pueden meter sin preguntar en una sala de conferencia, por ejemplo.

Ortega y Gasset ya lo ha dicho “recuerda que para ser ingeniero no basta con ser ingeniero”.

Y tiene toda la razón, lo que hacemos tiene efectos reales sobre la gente, debemos pensar muy bien las causas de lo que implementamos, y corregir inmediatamente si causan problemas. Esta es la responsabilidad de cualquier ingeniero. Pero parece que la tendencia en informáticos es “lo implemento porque se puede”, sin pararse a pensar siquiera en lo básico de privacidad, respeto y no molestar innecesariamente.

Cada día me molesta más este pasotismo y “solucionismo” (como diría Eugeny Morozov) de mis colegas. Últimamente lo pienso cada vez que recibo el aviso, varias veces al día, del sistema de bloqueo de DoS de Menéame (en pocas semanas tenemos ya varios cientos de IPs que hacían “DoS” involuntarios). Bots descontrolados que podrían tirar sitios completos (y/o causar gastos innecesarios), programas que generan cientos de conexiones por segundo, a veces durante meses (como nos pasa con la IP 46.105.237.95 de un servidor de DreaMule). No se salva nadie, tenemos bloqueadas IPs de muchas empresas importantes, incluido proxies corporativos de Google, servidores de Automattic/Wordpress, buscadores e indexadores sociales, y hasta con el bot del buscador Bing de Microsoft [*].

Demasiadas molestias innecesarias causadas por programadores.  Lo de los bots descontrolados que hacen DoS y generan tanto tráfico inútil es de locos, además de las molestias individuales debe tener un coste económico enorme globalmente (¿y cuántos deben pensar que están recibiendo ataques DoS o DDoS cuando es simple irresponsabilidad de programadores). Pero que por defecto y sin preguntar un programa te meta en salas grupales de vídeo conferencia es ya indescriptible: imaginaros que estáis con roaming y no os dais cuenta que vuestro teléfono entró en una conferencia de estas… para daros una idea del daño económico real que puede causar.

No es tan difícil si se piensa un poco, sobre todo si los programas afectan a lo cotidiano de millones de personas, y lo molesto y el daño que pueden causar. Me enerva cada vez más esta incapacidad de pensar profesionalmente en las consecuencias de lo que hacemos. No llegamos ni a ingenieros.

—-
[*] En el caso de Microsoft tuve que darme de alta en Outlook.con, luego agregar los dominios de Menéame, y luego configurar la frecuencia de rastreo para evitar el problema, no ofrecían otra opción. En el caso de Google, envié un email a la dirección de abuse de registros de sus direcciones IP (en ARIN), me devolvió un email automático de que no leen emails, me envió a  un formulario de Google, después de varios intentos, no hubo forma de dejar el comentario. Al final me dijo que lo comente en un foro de Google (que ya ni me acuerdo), nadie me contestó, al final dejamos bloqueadas esas IPs de Google.

Monitorización y “self-healing” de AutoScaler/LoadBalancer de Amazon AWS

octubre 14, 2013 3 comentarios

Aunque está cada vez más fiable y con menos fallas, al principio los fallos de sincronización del AutoScaler con el ElasticLoadBalancer eran bastante frecuentes. Aún así todavía pueden ocurrir errores de programas que ponen la CPU de un servidor al 100%, o que se cuelgue algún servicio, o que deje de responder y el LoadBalancer lo elimine de su lista pero aún así sigan ejecutándose y consumiendo vuestro dinero.

El AutoScaler también tiene otro problema derivado de la extrema simplicidad de las reglas (del CloudWatch) para escalar hacia arriba y hacia abajo, especialmente esta última. Supongamos que para minimizar los costes queréis mantener las instancias entre un 70 y 85% de uso de CPU (así lo tenemos en Menéame), para ello usareis las métricas agregadas del grupo del auto escalador, pero en éste no hay forma de indicar una regla que como:

Cuando la carga con una instancia menos sea menor al 70%, decrementar una instancia

Por ello, en 2009 implementé un programa que monitoriza la carga de cada instancia del grupo que implementa este tipo de reglas. Además este programa monitoriza que todas las instancias estén dentro del margen (entre 70 y 85% de CPU), si alguna se desvía mucho toma otras decisiones. Por ejemplo: si una está cercana al 100% y la diferencia con la media de carga es superior al 50%, asume que hay un fallo en esa instancia y la terminará. Lo mismo hará que para instancias que estén muy cercanas al 0% de CPU mientras las demás están bastante por encima (lo típico de instancias “descolgadas” del LoadBalancer, por ejemplo por fallo de hardware o de algún servicio.

La verdad es que además de ahorrarnos bastante dinero manteniendo a todas las instancias “saludables” y dentro de los márgenes de CPU, me quitó dolores de cabeza. Salvo catástrofes y cosas muy raras, no tenía que preocuparme para nada del estado de los servidores web.

Pero nunca liberé ese código, cuando lo programé (hace casi cuatro años) las librerías de Python y Perl estaban bastante mal documentadas, así que lo hice en PHP porque pude entender las clases muy rápidamente. Pero el código era infumable, y ni quería liberarlo. Ahora que las librerías de Python, las boto, tienen muy buena calidad, me decidí a portar el código a Python. Ya está funcionando, y ahora lo libero y explico brevemente (haced con el código lo que queráis).

Precondiciones

Tenéis que tener instalado el paquete boto. Está probado con la versión 2.14, podéis usar el que trae vuestra distribución si es al mínimo la versión 2, o bien instalar la última con el pip (pip install -U boto). Ya está, eso es suficiente, en principio no necesitáis nada más de software.

Lo que hay que hacer es poner la configuración con vuestras claves en el /etc/boto.cfg o ~/boto. En nuestro caso, que tenemos los servidores en Dublin, la configuración es la siguiente:

[Credentials]
aws_access_key_id = XXXXXXXXXXXXXXXXXX
aws_secret_access_key = YYYYYYYYYYYYYYYYYYY

[Boto]
ec2_region_name = eu-west-1
ec2_region_endpoint = ec2.eu-west-1.amazonaws.com
autoscale_region_name = eu-west-1
autoscale_endpoint = autoscaling.eu-west-1.amazonaws.com
elb_region_name = eu-west-1
cloudwatch_region_endpoint = monitoring.eu-west-1.amazonaws.com

El código

Consiste de tres ficheros Python, los dos primeros obligatorios para hacer los controles, el tercero es para visualizar información de las instancias:

ec2_watchdata.py: Define la clase WatchData que implementa los métodos para leer los datos de AWS, manipular datos y hla lógica de controles.

ec2_watch.py: Es el script que ejecuto desde el cron cada minuto y hace lo que he explicado antes. Intenté que la lógica quede muy sencilla, y se puede cambiar todo por argumentos en la línea de comandos (con -h sale una pequeña ayuda). Permite especificar el nombre del grupo del autoescalador, si se quiere que envíe un email de las “emergencias”, para cambiar los límites de CPU, y otra para que grabe los resultados en JSON en la base de datos de Menéame como “annotation” (usado para poder visualizar el estado vía web). Lo podéis ejecutar como queráis, incluso con la opción -d o –dry si sólo queréis ver qué es lo que va a hacer, yo lo tengo en el cron para que se ejecute cada minuto, que es lo que recomiendo:

* * * * * meneame/scripts/ec2_watch.py -g web -a -m gallir@gmail.com &gt; $HOME/watch.log

ec_instances.py: Es un pequeño script (pero que lo usamos mucho) que también usa la clase WatchData, fudamentalmente para visualizar el estado de las instancias del grupo, y también permite cambiar manualmente el número de instancias deseadas (opción -i), o matar instancias (opción -k). La siguiente captura muestra varias ejecuciones de este script, con un par para cambiar el número de instancias deseadas:

ec2_instances.py

Opcional: Si miráis el código, cuando se indica la opción -a llama a la función store_annotation() en el fichero utils.py. Esta es la que guarda los datos en formato JSON en la base de datos de Menéame y que me permite controlar desde la web y mi móvil:

ec2_watch web

Ejemplos de fallos (provocados)

Primero hice que una instancia se ponga al 100% de CPU (con el comando “yes > /dev/null”), así simulaba el fallo de algún programa. ec2_watch lo detectó y primero incrementó el número de instancias de 2 a 3. Como es una “emergencia”, me avisó por email de lo que pasaba, y lo que hizo:

100% de CPU, incrementa una instancia

Minutos después esa instancia seguía al 100%, por lo que la mató:

100% CPU, la mata

La siguiente es otra prueba, pero a la inversa. Desconecté manualmente una instancia del LoadBalancer, así el uso de CPU se pondría casi a cero, lo detectó a los pocos minutos, la terminó y el autoescalador levantó otra instancia nueva (al no cambiar el número de instancias deseadas):

0% de CPU, mata la instancia

Fin

Espero que os sea útil. No aceptaré sugerencias, pero sí parches ;)

Detección de DoS y bloqueo automático de IPs con el LoadBalancer de Amazon AWS

septiembre 11, 2013 9 comentarios

En Menéame teníamos un problema no solucionado correctamente. Cada vez sufrimos más ataques DoS voluntarios e involuntarios (bots mal programados, como los de Dreamule) que en el mejor de los casos nos ocasionan gastos innecesarios (ancho de banda e instancias adicionales) y en el peor sobrecargan tanto que impiden el acceso normal a las páginas. A esto se suma un gran problema: las instancias webs (que están autoescaladas horizontalmente) están detrás del balanceador de carga de Amazon AWS (ELB, Elastic Load Balancer) y éste no permite gestionar, ni manual ni automáticamente, el bloqueo de direcciones IP.

Por ello había que buscar una solución que detecte los DoS a conexiones que se hacen a las diferentes instancias web, y que sea el propio software de Menéame que lo haga y rechace las conexiones lo más rápido posible, y consumiendo los mínimos recursos. Esto obligaba a que se registren en un sólo servidor todas las conexiones desde las diferentes instancias, se analice en él en “tiempo real” y se guarden los datos en la base de datos para que estén disponibles para todas las instancias. Éstas deberían ser capaces de rechazar esas conexiones consumiendo la cantidad mínima de recursos y ancho de banda (tanto en la de Internet, como a la base de datos, como para enviar los logs al servidor central).

Después de pensarlo durante meses, y de analizar decenas de alternativas, en unos pocos días se me ocurrió la solución “óptima”. Esto ocurrió después de un mes de vacaciones casi completamente desconectado. Es el valor que tiene el descanso, pero eso es otro tema.

Leer más…

Por qué el núcleo Windows NT es peor que Linux: problemas sociales y de incentivos

En el artículo “I Contribute to the Windows Kernel. We Are Slower Than Other Operating Systems. Here Is Why.” se transcribe el comentario (luego eliminado) de un anónimo que se identificó y aportó pruebas como programador de Microsoft. En el comentario explica su opinión de por qué el núcleo Windows NT (el que se usa en todos los siguientes, 2000,XP, Vista, 7 y 8). Más allá de las anécdotas, y de que es una visión parcial y subjetiva, es muy interesante lo que desvela. En pocas palabras, la carencia de calidad y eficiencia son más un problema social más que técnico:

  • Falta de incentivos, o incentivos equivocados.
  • Dar mayor importancia a cumplir los planes establecidos sin desviaciones que aceptar cambios no planificados para mejorar la calidad del producto.
  • La carencia de programadores con experiencia, o el exceso de programadores recién graduados.

Es muy interesante la lectura, desvela los problemas de gestionar y programar sistemas complejos. Cualquier economista explicaría que hay que establecer los incentivos adecuados, sobre todo en entornos como la programación donde se trata de desarrollar sistemas tan complejos que tienen más componentes que el avión más grande del mundo y tantas formas de interacción -muchas órdenes de magnitud superior a cualquier sistema de componentes físicos- que escapan a nuestra capacidad de comprensión.

Ese incapacidad cognitiva de siquiera conocer la magnitud de la complejidad hace que sea imposible hacer un diseño inicial que tenga en cuenta todas las interacciones y casos. Por ello es imposible asegurar que no haya bugs y, por supuesto, que el sistema desarrollado sea eficiente. Eso requiere, tal como ya lo contaba Brooks en los ’70, el “mantenimiento” de los programas, que consiste en la mayor parte del ciclo de vida del software. Ese mantenimiento no consiste sólo en arreglar problemas, también en mejorar el código (para controlar mejor la creciente complejidad) y la eficiencia.

En el núcleo Linux es un buen ejemplo en ese sentido: se usaron las ideas y principios de modularidad de Unix, es software libre con todo a la vista del público (el código, y las discusiones técnicas), la gestión de Linus Torvalds (y los responsables de módulos) han creado una comunidad muy meritocrática (talk is cheap, show me the code) donde el respeto a los clientes (desarrolladores de programas a nivel usuario) es prioritaria, revisión de pares, se debate con dureza cada propuesta y cambio, se critica duro al que presenta propuestas malas, pero también se reconoce y halaga al que consigue mejorar funcionalidades ya establecidas y maduras.

Esa es una de las principales diferencias que se extraen del artículo.

En Microsoft [presuntamente] no funciona así, los responsables de módulos tienen más razones para rechazar mejoras que para introducirlas,  los Project Managers no ven con buenos ojos que haya desvíos del plan de trabajo, los grupos de testing no quieren saber nada de volver a probar y adaptar unidades de verificación. Es decir, no hay incentivos para mejorar las funcionalidades existentes y que no sean prioritarias en la empresa. En consecuencia, la eficiencia de sistemas con modelos de desarrollo más similares a Linux acaban siendo superior, sobre todo en las áreas y funcionalidades ya maduras.

Otro de los problemas que se menciona es el abandono de los programadores senior y la contratación de nuevos que acaban de salir de la universidad. Estos no son capaces de valorar la complejidad del sistema, ni de conocer por qué fueron tomadas las decisiones técnicas anteriores.

Este último punto es interesante, sobre todo en un gremio -y en un país- donde se valora poco la experiencia de los programadores. Salvo las empresas punteras en desarrollo de software equiparan los [excelentes] salarios de los programadores con la de los gestores (no es nada raro que un programador senior de Google cobre 150.000€). Ocurre en muchos países, pero sobre todo en España, tener 40 años y seguir programando parece más un fracaso profesional que el éxito de un programador apasionado.

Tampoco es culpa de las “empresas” o el “mercado”, desde la propia universidad solemos transmitir el mensaje equivocado:

Un ingeniero informático no programa, dirige proyectos

Ese mantra lo oí muchas veces y los alumnos lo escuchan frecuentemente en clases. El error es múltiple, por un lado transmitimos la idea que un ingeniero graduado sabe todo lo necesario, que no hace falta experiencia en programación, y que programar es de pringaos.

Además de lo mejorable que es nuestra educación, y como últimamente me está apasionando el tema de gestión de desarrollo de software, del comentario me han quedado algunas cosas más claras:

  • Los planes y metodologías son herramientas, no un fin en sí mismo, como terminan de creerse sus responsables y evangelistas.
  • Se deben crear incentivos, no sólo monetarios, para motivar a que los programadores desarrollen mejoras para cualquier parte del sistema. Esto implica, entre otras cosas, descontar un porcentaje de los recursos disponibles para implementar nuevas funcionalidades y reservarlos para mejora de la “calidad global”.
  • Valorar debidamente a los programadores experimentados, que empieza por reconocer -sobre todo entre nosotros mismos- las carencias inevitables de un recién graduado, y la rápida evolución de la ciencia y tecnologías informáticas.
  • Debemos empezar a esforzarnos en formar a profesionales cuyo objetivo sean jubilarse como programadores, no sólo un camino intermedio para lograr mejores salarios en otros puestos de gestión o dirección.
  • Sobre todo, reconocer que tenemos problemas cognitivos para visualizar mental y adecuadamente la enorme complejidad de los grandes sistemas informáticos.
Seguir

Recibe cada nueva publicación en tu buzón de correo electrónico.

Únete a otros 461 seguidores