jueves, 31 de mayo de 2012

Fin de una era

Señores, gracias por haber estado aquí.

Hace mas o menos 15 días que decidí abrir un nuevo blog: www.krenel.org. La idea es la misma que este mismo blog pero con dos diferencias:
  1. El dominio es mío. No quiero usar más blogger como plataforma. Por motivos personales me intento alejar lo mas que puedo de los productos de Google.
  2. Está en inglés. Mira, seamos sinceros: mi inglés apesta. ¿Qué mejor que escribir un blog ténico en inglés para practicar un poco? (sisi, vale echarse una novia inglesa es mejor ¬¬' )
Pues estos dos puntos son el motivo de cambio y cese de este blog. No voy a cerrarlo porque hay artículos que creo son interesantes o alguien le puede sacar partido todavía, pero voy a dejar de escribir en él.

Éste es el post número 127. (2^7-1). Me parece un bonito número.

El primer post lo escribí hace unos tres añitos y estoy muy satisfecho con lo que he ido publicando hasta ahora. Y voy a seguir haciéndolo, pero en otro blog y en otra lengua.

De nuevo gracias y espero que algo de lo que he publicado os haya servido.

Un saludo, Jan.

viernes, 27 de abril de 2012

Erlang (V) HTTP reverse proxy

[Repaso]
Repasemos la infraestrctura: Ahora mismo tenemos un servidor web hecho en Erlang, MochiWeb, que accepta mucha mucha carga.

Este servidor en si mismo no hace el trabajo, sino que deja que un Actor de Erlang (llamado Usuario) se encargue de gestionar la petición. Así conseguimos una concurrencia brutal y soportamos un montonazo de carga[1]. El actor usuario, en caso de recibir un mensaje de otro usuario, devolverá este mensaje al servidor web, que a su vez se lo mandará al usuario final y este lo recibirá en su navegador. Bien. También tenemos en un almacén de datos en memória la gestión de las sesiones (en mnesia): allí se asocia un ID de sessión HTTP con el ID de usuario.

Ahora mismo la arquitectura de la aplicación está pensada para ser ejecutada en una misma máquina, lo que supone algunos problemas: cuando toca reiniciar el equipo debido a actualizaciones de kernel y demás el chat debe permanecer "cerrado". No solo esto, si no que el usuario no recibiría un bonito mensaje de error que diga "We are under maintenance", sinó mas bien un "server not found" o algo así. Algo feo feo. Pero arreglarlo tampoco es algo fácil.

También hay otros pequeños problemas como por ejemplo el logueo de las peticiones HTTP (típico fichero access.log) y ofrecer HTTPS (SSL/TLS).

Veamos una imágen actual de la arquitectura de Gaab Web Chat:




Bien. Tenemos un único punto de entrada directamente al servidor de chat de Erlang. En si mismo esto no está mal, ya que el servidor accepta una concurrencia "que te cagas", pero tenemos los problemas comentados anteriormente. Parece que la solución más simple es (como casi siempre) añadir una capa mas de complejidad y añadir un: http reverse proxy.


[Cherokee]
No explicaré lo que es un reverse proxy (consúltese en la wikipedia, o léase este[2] artículo), pero sí explicaré por qué he elegido Cherokee. Aparte de por que en todos los bencharks tiene unos muy buenos resultados, tiene unos ficheros de configuración con una gestión muy clara, es relativamente nuevo pero tiene un gran comunidad y está publicado bajo GPL es porque el creador del servidor web es español. Si señor. Me ha salido la vena patriótica y me apetece apoyar (ummm... vale, con "apoyar" quizás me he pasado, digamos "usar") un proyecto hecho en casa. Y punto.

Y las primeras impresiones no pueden ser mejores: gestión vía web, creado un virtual host en menos de 1 minuto, creado el http proxy en 5 minutos. Amén. Así da gusto.

La idea es usar Cherokee como balanceador de carga entre diferentes aplicaciones GaabWebChat(Erlang+Mnesia+Aplicacion) que se estarían ejecutando en máquinas distintas. La carga de tráfico sería balanceada entre todas las máquina que pudiese tener la aplicación. En caso de que se tuviese que actualizar la plataforma, sería tan simple como decirle a Cherokee que no mandara más tráfico en aquella máquina, actualizarla tranquilamente, y después volver a dirigir tráfico a la misma.

La arquitectura quedaría algo así:



Mucho mas chula que antes, no? Así Cherokee se puede encargar de gestionar las conexiones HTTP/HTTPS, loguear todos los requests en un fichero "access.log", balancear la carga entre varias aplicaciones y servir contenido estático.


[Mejoras]
Esta plataforma todavía se puede mejorar ya que todavía hay un único punto de fallo, el servidor de Cherokee. Esto se podría remediar poniendo varios Cherokees en diferentes máquinas y balanceando la carga por DNS, por ejemplo. Pero esto ya queda (de momento) fuera del alacance de este post.

Esta solución aquí propuesta es un algo que puede que en un futuro pueda necesitar, pero des de luego no lo incluiré en la primera versión que ponga online, ya que MochiWeb puede soportar muucha carga (estoy seguro que ahora mismo por cada 500MiB de RAM que pueda conseguir en un hosting puede soportar a 5K usuarios).

Pues nada, señores. Un saludo.

P.D: Mierda de Blogger. Las imágenes quedan como el culo, pero tienen que tener este tamaño para que se vean claras. So sorry. Prometo cambiar pronto el blog de sitio :/

[1] Me faltan hacer un par de benchmarks para demostrar que esto es así, pero la pereza puede a uno.
[2] http://www.cherokee-project.com/doc/modules_handlers_proxy.html

jueves, 26 de abril de 2012

Peticiones Ajax en IE8 y cachés: crap, crap, crap


IE8 apesta. Y por extensión Microsoft también.


[Problema]
Las peticiones por Ajax que lanza IE8 son cacheadas. Todas ellas. Si lanzas un requests por Ajax a la url "/check_mail_box" y el resultado de la petición dice que no tienes nuevos mails, tooodos los demás requests que hagas a esta URL estarán cacheados y realmente ni se volverá a lanzar una petición HTTP para comprobar nada. IE8 es inteligente (o almenos esto cree) y dice: ¿si ya tengo la información, para qué voy a volver a pedirla?

¡PUES PORQUE PUEDE HABER CAMBIADO, CACHO RETRASADO! ¡POR ESTO LANZO OTRA PETICIÓN! ¡PARA COMPROBARLO DE NUEVO!

Calémonos.

[Repasando las bases]

El protocolo HTTP hace AÑOS que se usa en el mundo Web. El cliente hace una petición de un recurso, el servidor busca el recurso y se lo devuelve al cliente. En caso de que se haga otra petición, el proceso se repite.

Hace hace años también que dejó de servirse contenido estático y ahora se están sirviendo contenidos dinámicos, generados por PHP, .NET, CGI y un largísimo ETC... Esto significa que si tu pides un recurso, como por ejemplo "/last_users_connected", el resultado de la petición HTTP puede cambiar en el tiempo, ya que es una información CALCULADA en la parte servidor.

Bien.

Ajax. Ha aparecido hace relativamente poco. Es lo mismo que una petición HTTP pero de manera asíncrona. ¿Qué significa esto? Pues que el usuario puede estar navegando tranquilamente mientras, en segundo plano, se descarga otra información. Muy cómodo para no tener que ir recargando la página cada dos por tres. Pero esto de Ajax es solo un artificio creado por el navegador. En realidad se lanzan peticiones HTTP como las "normales". Exactamente iguales. No hay diferéncia entre ellas.


[Acercándonos al problema]
Cada vez que el usuario entra en "www.facebook.com" el navegador lanza una petición HTTP pidiendo el recurso "/index.html". Bien. Si le damos a F5 (refrescar) o volvemos a abrir en otro Tab del navegador "www.facebook.com", vuelve a lanzar la petición y puede que los resultados del primer tab al segundo tab sean diferentes. Obvio.

Imaginemos que el navegador cachea la primera petición a "/index.html" y que a partir de ahora cada vez que entramos en www.facebook.com nos sirve la versión cacheada. Pues vaya inutilidad, verdad?


[Meollo]
Bien, pues esto es lo que hace IE8 con las llamadas de AJAX.  

Se le tiene que decir explícitamente a IE8 que NO haga uso de la caché en las peticiones por Ajax par que funcione de un modo normal. Otro modo de decir lo mismo es que se tiene que instruir a IE8 para que funcione CORRECTAMENTE y como un usuario corriente y moliente esperaría. Va contra la lógica más básica: le estás diciendo al navegador que descargue una información de un servidor (pero de modo asíncrono), y el navegador -por que le sale de los cojones- te devuelve una versión antigua de la misma sin lanzar peticiones ni ostias. Fuck.

[Conclusión]
IE8 apesta.




Y por extensión Microsoft también.


Un saludo, Jan.

P.D: Me pregunto los miles de millones de euros que habrá costado esta decisión por parte del equipo de IE8. Pensadlo, la de librerías que se tienen que adaptar y la de programadores que tienen que aprender la gilipollez esta.
P.D2: He de decir que W7, y IE9 ya parecen SO/navegador decentes, y que parece que las ñapas que había estado haciendo Microsoft hasta ahora (W98, W2000, WMe, WVista, IE{5,6,7,8}) quedan en el pasado. Ya iba siendo hora.








lunes, 9 de abril de 2012

Errores en el manual de bash

Me aburro. No os creáis, me pasa amenudo. Y no lo veo como algo malo, ya que normalmente para quitarme el aburrimiento hago lo que yo llamo "cosas productivas". Como leer el manual de bash, por ejemplo.

$ man bash

Así de fácil. Y la verdad que está bastante interesante y uno se entera de cosas que no sabia, o entiende cosas en las que hasta ahora dudaba. Pero estoy yo tan tranquilo leyendo el manualillo en mi Kindle[0] en el avión, cuando me encuentro con una cosa que no me ha acaba de gustar. En el apartado REDIRECTION, pone lo siguiente:

Bash handles several filenames specially when they are used in redirections, as described in the following table:
/dev/tcp/host/port
If host is a valid hostname or Internet address, and port is an integer port number or service name, bash attempts to open a TCP connection to the corresponding socket.

Bueno, hasta aquí no tengo ninguna queja. Estoy conforme con esto. Pero ya no me parece tan bien el siguiente bloque. ¡Ai señor! ¡Cuánto daño ha hecho el copy-paste!

/dev/udp/host/port
If host is a valid hostname or Internet address, and port is an integer port number or service name, bash >>>attempts to open a UDP **connection**<<< to the corresponding socket.
O sea, exactamente igual que el bloque de anterior, pero cambiando TCP por UDP. Solo que estos dos protocolos no son lo mismo. Y dá la casualidad que en el protocolo UDP no se establecen conexiones. Y no es porque lo diga yo. Si hacemos un "man udp", podemos leer en la primera línea:

This is an implementation of the User Datagram Protocol described in RFC 768. It implements a **connectionless**, unreliable datagram packet service. Packets may be reordered or duplicated before they arrive.

Connectionless, sin conexiones. Por lo que el término "connection" al lado de UDP ya es incorrecto en si mismo, ya que las conexiones UDP no existen (si eso, se implementan en capas superiores en la pila TCP/IP, o sea, en la capa de Aplicación. Pero en el protocolo UDP no existen conexiones). Además, "attemps to open" también es incorrecto, ya que UDP no intenta "abrir" nada, sinó mas bien intenta mandar el paquete a la red. ¿Que el paquete llega? Bues bien. ¿Que no llega? Pues a UDP se la suda. De hecho el protocolo UDP no sabe ni si ha llegado el paquete[1], ni le importa. Repito, no existe el concepto de conexión en el protocolo UDP.

¿Qué todavía no me crees? Vaya, macho... a ver. RFC793, TCP[2]. Ocurrencias de la palabra connection: 271. RFC768, UDP[3]. Ocurrencias de la palabra connection: ninguna!!!

¿Qué propongo? Pues cambiar la frase a algo así:

If host is a valid hostname or Internet address, and port is an integer port number or service name, bash attempts to send a UDP datagram to the corresponding socket.

Ya he mandado un email al mantenedor del manual de bash, en mi perfecto inglés de mierda (gracias hermana por ayudarme a corregir mi inglesanalfabetismo). A ver que dice. Ya os diré cosas cuando conteste. A ver que le parece a él.

Un saludo, Jan.


[0] Noooo! Tranquilos!! No soy tan bruto como para inslarle Linux en un Kindle! Es simplemente que quería decir que me había comprado el juguetito ^_^
[1] no debería decir paquete sinó datagrama, para ser mas exacto, ya que lo que comunmente llamamos paquetes se trata siempre del nombre del PDU de Capa de Red, o sea, protocolo IP, y ahora estamos hablando de la capa de tranmisión de datos, donte tenemos datagramas en el caso de UDP y segmentos en el caso de TCP, pero bueno..... sé que diciendo paquete ya nos entendemos! Y recordemos que UDP es unreliable y por esto se la suda si llegan o no los paquetes.

sábado, 7 de abril de 2012

Actualizando el microcódigo de la CPU (microcode.ctl)

[Explicación]
Los procesadores tienen un firmware, también llamado microcódigo. El firmware está situado entre el hardware y el lenguaje ensamblador. Mas o menos la cosa iría así:

hardware -> firmware (microcódigo) -> ensamblador -> kernel -> S.O. y aplicaciones

Es un bloque de instrucciones máquina que establece la lógica a más bajo nivel y que está fuertemente ligado a la electrónica subyacente. Pero así mismo, es un cacho de código. O sea, software.

Cuando compras una CPU en una tiena, o te compras un portátil estás adquiriendo un modelo concreto, que viene con una revisión (versión) de firmware concreta. Pero ¿Qué passa si Intel saca una nueva versión de firmware con mejoras, optimizaciones, uso de algoritmos mas eficientes y con menor consumo de energía, corrección de bugs, etc? Pues que no los puedes disfrutar, a menos que instales el firmware nuevo. Y...¿Cómo se consigue actualizar el microcódigo? Pues normalmente no te queda otra que actualizar la BIOS de tu máquina actualizando así el microcódigo de tu procesador.

Pero ya sabes que actualizar la BIOS no siempre es buena idea. Si mientras la estás actualizando se vá la corriente, puedes tirar el procesador directamente, que es irrecuperable. Es algo peligroso. Se puede hacer, pero no es algo que quieras hacer muy amenudo. Enserio.

Cagonlaputa. Entonces, ¿no hay alternativa posible? Si. Si la hay. Almenos en Linux si.

[Conociendo la herramienta]
Hay un hermoso paquete llamado microcode.ctl que hace éste trabajo por nosotros y que se encarga de cargar el microcódigo de manera dinámica en nuestro procesador. Esto significa que no flashea el procesador (no hace los cambios permanentes) sinó que actualiza el firmware del procesador al vuelo y en tiempo de ejecución cada vez que se inicia el S.O. Esto tiene varias ventajas:
  1. Lista numeradaNada de actualizar la BIOS del modo tradicional, por lo que nos evitamos un procedimiento peligroso (y tedioso).
  2. Se descarga automáticamente las nuevas versiones sacadas por Intel y las aplica en el próximo reinicio.
  3. En caso de que se descargue una versión que por lo que sea falla y nos dá problemas, solo debemos desactivar el daemon que se encarga de actualizar el microcódigo del procesador cada vez que se inicia el sistema, y santas pascuas.
[Instalación]
Pff.... ¿enserio que tengo que hacer esta sección? Si las secciones de "instalación" siempre son iguales en Linux :/
$ sudo aptitude install microcode.ctl

...y a correr. En la instalación te pedirá si te quieres descargar también el paquete propietario intel-microcode que contiene las últimas versiones de los microcódigos. Obviamente la resuesta es SI, QUIERO. Y punto. Si vas a ver el fichero /var/log/syslog puede que te encuentres con estas bonitas líneas (pero dependen de la versión de firmware que tengas, claro):

microcode: CPU0 sig=0x20655, pf=0x10, revision=0x2
microcode: CPU1 sig=0x20655, pf=0x10, revision=0x2
microcode: CPU2 sig=0x20655, pf=0x10, revision=0x2
microcode: CPU3 sig=0x20655, pf=0x10, revision=0x2
microcode: Microcode Update Driver: v2.00 , Peter Oruba
microcode: CPU0 updated to revision 0x3, date = 2011-09-01
microcode: CPU1 updated to revision 0x3, date = 2011-09-01
microcode: CPU2 updated to revision 0x3, date = 2011-09-01
microcode: CPU3 updated to revision 0x3, date = 2011-09-01

Un saludo!


viernes, 6 de abril de 2012

Gestor de portapapeles

Entrada rápida. Parcellite[1] es un gestor de portapapeles. Simplemente pulsando Control+Alt+H te aparece un listado con las últimas cosas que has copiado mediante Control+C, seleccionándolas con el ratón o mediante el teclado. Elige un elemento de la lista y para pegar pulsa una de las siguientes combinaciones de teclas:
  • Control+V
  • Shift+Insert
  • Control+Shift+V
Para programar con Vim es una monada. Pruebalo. Ya. Te encantará.

En mi configuración (a través de GTK) en la pestaña Behavior tengo marcadas solo las opciones:
  • Use Copy (Control-C)
  • Use Primary (Selection)
  • Syncronize clipboards
  • Save history
Y todo lo demás desactivado.

Un saludo.

jueves, 5 de abril de 2012

Erlang (IV) Semana 2

La Semana 1 construímos un core de servidor de chat que hacía bastante bien su trabajo. Ahora el paso lógico es:
  1. Integrar este core con un servidor HTTP
  2. Crear una User Interface (UI) bonita y amigable
[Servidor HTTP]
El primer punto, que al principio no acababa de ver claro, ha sido muy simple. Lo primero de todo era encontrar un servidor HTTP para Erlang. Mis requisitos eran:
  • Escrito 100% en Erlang. Para no liarnos con otras tecnologías
  • Que pueda soportar mucha concurrencia. Por motivos obvios en la aplicación que queremos crear.
  • Con un sistema muy simple de hacer dispatch de llamadas, con controladoras y todo el tinglado. Quería algo que ya te lo diese un poco mascado, pero que fuera altamente personalizable.
El servidor web MochiWeb cumple con todos los requisitos anteriores. El trabajo principal ha sido crear un pequeño dispacher para cada una de las llamadas, para poder ofrecer una interfície restful simple, limpia y clara pero que nos sirva para nuestros propósitos. Para saber exactamente cómo está implementado, que se mire el código (mas sobre esto al final), pero para dar una idea general os enseño la API REST que he creado:

  • Acción: /login Método: GET. Parámetros: N/A. Explicación: Renderiza la pantalla de login
  • Acción: /login Método: POST. Parámetros: username, password. Explicación: Loguea el usuario, en caso de que los datos sean correctos, mediante el establecimiento de una cookie.
  • Acción: /logout Método: GET. Parámetros: N/A. Explicación: Lo obvio
  • Acción: /msg Método: GET. Parámetros: N/A. Explicación: Éste es el mas importante de todos. Está pensado para ser llamado por AJAX y manetener la conexión abierta durante 20 segundos. Recibe como respuesta un JSON con los mensajes que puedan haber enviado enviado otros usuarios durante estos 20 segundos, la notificación de que otro usuario se ha logueado, etc... Más sobre esto, luego.
  • Acción: /msg Método: POST. Parámetros: msg, to Explicación: Envia el mensaje msg al usuario to. ¿Fácil, no?
  • Acción: /users_list Método: GET. Parámetros: N/A. Explicación: Devuelve un JSON con el listado de amigos conectados en este momento.

¿Simple, verdad?

La acción mas interesante es /msg per método GET. Vamos a explicarla un poquito mas. Como comentaba mas arriba, esta llamada devuelve un MIME-type application/json. Nada de XML ni líos, JSON nos va perfecto para este caso, ya que esto lo recibe la parte cliente y tiene que interpretarse en Javascript. Sabiendo que JSON significa JavaScript Object Notation, queda claro que para este caso ésta es la elección ideal. Esta acción está pensado para ser llamado por AJAX, pero también puede ser llamada por el método tradicional sin problemas. Cuando se cree la conexión, ésta permanecerá abierta durante 20 segunos. Durante este tiempo, si se produce algún evento en la parte servidor como por ejemplo recicibir un mensaje, se mandará el mensaje hacia el usuario a través de esta conexión. Si no hay nada que notificar en 20 segundos, se cierra la conexión y se espera que el cliente abra otra inmediatamente después, esperando así indefinidamente a recibir algún tipo de mensaje.

¿Qué tipo de información devuelve éste método? Pues información que tenga que ver con cambios de estado, mensajes de chat, notificaciones, etc... Veamos los JSON's de posibles resultados:
  • {"action":"message", "user":"inedit00", "msg": "Hello world!"}
  • {"action": "friend_logged", "name": "foo"}
  • {"action": "friend_unlogged", "name": "bar"}
  • ....
Como podeis ver la interfície es muy clara y legible. El action determina qué tipo de mensaje es, y cada mensaje tiene los campos con la información necesaria. Procesar esto en JS es prácticamente un chiste. Mirad, así, en pseudo-javascript y para que os hagáis una idea:


MessageHandler = {
message: function(request) { alert(request.msg) },
friend_logged: function(request) {alert("The user " + request.name + "logged in")},
.....
}
var process_http_response = function(html) {
json = JSON.decode(html)
MessageHandler[json["action"]](json)
}
nada... un juego de niños. La ventaja de utilizar algo así es que para añadir una acción más, simplemente hay que mandar un mensaje distinto y crear su handler en el código JS. Obviamente el código JS está pensado para ignorar todos los mensajes con un action para los que no tiene handler.

Total, que con todo esto ya tenemos una manera de mandar mensajes a otros usuarios en el sistema des de la parte cliente (JavaScript) y que sean recibidos por otros usuarios mediante HTTP. Genial.

[User Interface]
Bueno, esto simplemente es HTML+CSS+JS. Aquí no hay mucho que contar. Si alguien se lo quiere mirar que vaya al repositorio y mire el código fuente de todo el percal (es poquito y simple). Os dejo con el número de líneas que he usado para cada una de las cosas, y un par de capturas de pantalla, y arreando....
  • Página principal /index 37 líneas de HTML
  • Página de login /login 31 líneas de HTML
  • Fichero con todos el CSS's del proyecto: 98 líneas
  • Fichero con todo el JS del proyecto 195 líneas. Incluye la creación, cambio de tamaño/posición de las ventanas de chat, control de las conexiones por AJAX al servidor y los handlers que procesan las respuestas (mensajes nuevos, usuarios conectados/desconectados, etc....)....
Nhá... ha quedado todo muy pequeñito y limpio. Por supuesto nada de estilos inline, ni CSS en bloques style dentro de los ficheros HTML, ni Javascript inline en atributos HTML (¡aberración!) ni demás guarradas varias en el código. Sabéis que si hacéis estas cosas vais a ser sodomizados por Diox durante toda la eternidad, ¿verdad?
En el HTML hay dos imports, uno al CSS y otro al fichero JS y palante toda. Y mas o menos el tema luce así (que siiiiiii, que sé que todo lo anterior que os he contado os la sudaaaa, que coméis por los ojos!! ):




Ahora mismo solo hay un usuario conectado con el que pueda hablar (yo mismo en otro navegador ¬¬'). En las ventana de chat soporta modificación de tamaño, ponerla donde quieras en la pantalla, cerrarla y puedes tener abiertas tantas conversaciones de chat como quieras (siempre que tengas mas amigos, obviamente). Para ser una primera versión sacada en una tarde (HTML+CSS), estoy muy contento con el resultado.

Y nada.... esto es básicamente todo lo que tiene que ver con UI. Los ficheros interesantes del repositorio que tienen que ver con UI son:
  • /templates/index.dtl
  • /temlates/login.dtl
  • /priv/www/js/gaab.js
  • /priv/www/css/gaab.css
[Repositorio]
¿Repositorio? ¿Quién dijo repositorio? Pues claro que si, hombre! Si trabajas con código y no lo versionas es que te gusta vivir peligrosamente. Seguramente tus hobbies puedan ser hacer puenting sin cuerda, hacer la danza de pescado crudo en playas infestadas de tiburones en Madagascar o intentar ligar con la chica buenorra con el novio culturista.... a saber.

Todal, que tengo todo este código subido a un repositorio de bitbucket para uso y disfrute de todo quien quiera verlo:


y esto es todo... quien quiera preguntar alguna cosa, sugerir alguna otra, pedirme que explique algo un poco mas o tenga curiosidad en lo que sea: que me mande una caja de cerveza...... digooooooooo..... que deje un comentario!

Un saludo!

Vim y sus plugins

Menos pizzas, Vim puede hacerte todo lo demás. Si tienes complejo de pulpo (aka te gustaría tener un par de manos mas para poder usar Emacs como es debido), este post no es para ti.

He empezado a programar con Erlang y hay un par de pluguins a instalar que son indispensables. Es importante recalcar la importancia que tiene tener un entorno de trabajo cómodo y eficiente, para que el trabajo salga mas rápido y mejor.

[Plugin para Erlang]
En el caso de erlang me he instalado
vimerl[1] que entre sus muchas características como syntax highlight, code completion, auto-indent, etc... tiene una cosa que es una pasada que ellos llaman el QuickFix. Cada vez que guardas un fichero, comprueba si hay errores de sintaxis, variables no declaradas, variables no usadas, funciones no usadas, y demás... muy cómodo para no tener que hacer el proceso de: compilar, buscar errores en la consola, ver qué fichero y en qué línea han ocurrido, etc... E aquí un ejemplo. Fijaos que en la parte inferior de la pantalla nos pone una descripción del error en donde tenemos el cursor:


Los warnings los marca de color amarillento, mientras que los errores te los pone en rojo. Muy cómodo ya que cada vez que guardas el archivo puedes ver si tienes errores en el fichero o no. Muy chulo.

[Plugins generales]
Mas cosicas. Pues mira, uno que es básico, pero que hasta ahora no me gustaba mucho, es el NerdTree[2](vaya puto nombre feo le han puesto a la criatura). Le he dado una oportunidad y de momento va de lujo. Es un explorador de ficheros, con el que se puede navegar por la estructura de directorios des de Vim:


Cómodo y fácil de usar. Hay dos configuraciones que te pueden hacer la vida mas fácil. La primera es para poder ignorar ficheros, y que no aparezcan en el listado. Añadiendo en el .vimrc la siguiente línea, se consiguen omitir los resultados que hagan match a las expresiones regulares de la lista (en mi caso ignorar loc ficheros *.pyc )
let NERDTreeIgnore=['.*pyc$']
La segunda es añadir un keybinding para mostrar/ocultar el NerdTree. Esto se consigue añadiendo ésta línea en el .vimrc:
map :NERDTreeToggle
El pulsar F2, se abre/cierra el NerdTree. Muy cómodo también.

Y por último, un pluguin que complementa al NerdTree: CommandT[3]. Básicamente es un listado de tooodos los ficheros del proyecto y escribiendo un par de letras puedes abrir el fichero que quieras. Ejemplo:
Digamos que tenemos un fichero en www/back/back/controlers/dashboard.mako. Sería suficiente con escribir 'dash', como para que él ya te lo encuentre. Pero vamos a otro caso mas complicado en el que tenemos:
/www/back/back/templates/foo
/www/back/back/templates/bar
/www/back/back/templates/lala
/www/back/back/widget/foo/template.mako
/www/back/back/widget/bar/template.mako

En este caso, si quremos encontrar el fichero "/www/back/back/widget/foo/template.mako" será suficiente con escribir: "wifte", que se corresponde a:
  • "wi" de "widget"
  • "f" de "foo"
  • "te" de template
Aparte de mi burda explicación que he hecho aquí, recomiendo que mireis el screencast[4] hecho por el mismo creador del plugin.

También crearemos un keybinding para este plugin, de modo que la pulsar F3 se abra automáticamente CommandT. El comportamiento por defecto para ejecutar CommandT es pulsar la combinación t. La tecla es la tecla "\", que en teclado inglés está en una posición muy cómoda, pero en el teclado castellano está a tomar por culo. Para esto la mayoría de gente se redefine la tecla a la coma ",".
map :CommandT
let mapleader = "," " Change the key from \ fo ,


Con estos pluguins tenemos una combinación ideal, ya que si no sabemos qué buscamos, tenemos el NerdTree para navegar por los directorios y encontrar el fichero buscado. Si sabemos el nombre exacto, podemos usar CommantT para localizar el fichero, y palante toda. Por falta de recursos, que no sea.

He probado mas plugins (para buffers, tabs, cerrar paréntesis automáticamente, escribir html automáticament, etc..) pero ninguno de ellos me ha gustado. Pero la verdad que ha valido la pena encontrar estos tres plugins ya que mejoran mucho mi entorno de desarrollo.

Y nada mas por hoy. Un saludo, Jan.


[2] http://www.vim.org/scripts/script.php?script_id=1658 pero otra vez recomiendo mejor bajar la última versión de https://github.com/scrooloose/nerdtree
Post relacionado http://inedit00.blogspot.com.es/2010/04/dandole-cana-vim.html . Ahora que lo veo me parece super elemental, pero oye, que de esto hace 2 años y digamos que esto ya lo tengo bastante "mascado", jeje.

lunes, 26 de marzo de 2012

Dig Your Own Hole

[Flame]
Linux es genial, maravilloso, chulo, rápido.... y asquerosamente inseguro. De hecho, cualquier SO de hoy en día lo es, pero cualquier distribución de Linux, por su naturaleza, es mas vulnerable.

[Introducción]
El mejor sysadmin que he conocido me enseñó algo: la seguridad física no existe. És algo muy fácil de entender: si alguien tiene acceso físico a tu máquina, no hay nada que hacer. Des de DoS apagando la misma (ya sea desenchufando el cable o pulsando una divertida combinación de teclas[1]), pasando por ataques de David Hasselhoff[2], borrado de archivos, escalado de privilegios (des de una shell o haciendo truquillos en el grub), poner backdoors o, en caso de que nos pongamos mas serios el mismo robo del equipo y posterior análisis de los datos del disco duro, ataques de red MITM (ARP poisoning, ICMP redirect), hijacking de cookies que viajan por redes WiFi sin protección, y un laaargo etc. El tema está que el ataque se puede producir en cuestión de minutos y hay pocas formas de protegerse contra el.

Una vez el sistema ha sido "tocado" físicamente por alguna otra persona que no seas tu mismo, la máquina deja de ser segura y no te puedes fiar nunca mas de ella. ¿Exagero? Esperad y veréis.

Bueno, vale. Volviendo a la primera frase-flame del post quiero aclarar (o acotar) un poco la afirmación: Todas las distribuciones de Linux por lo general tienen implementaciones de red seguras. Los bugs de software (tanto en los programas en general como en el kernel) son arreglados en muy poco tiempo y uno tiene la opción de ver el código fuente de la mayoría de programas para asegurar que no incluyen sopresas, etc.... y todo esto está genial. Si la máquina se mantiene actualizada es difícil encontrar zero-days o exploit para ganar privilegios. Pero todo esto no es necesario ya que existe algo que se llama
consola. Que es muuy potente. Y que en manos de una persona agena (por no bloquear el portátil al ir a responder una llamada de móvil, o en un despiste tonto), y con muy pocos comandos, puede comprometer un sistema en un momentín. Y exactamente sobre esto va esta serie de posts.

Aquí se pretenden recopilar una série de comandos con los que se podrá comprometer un sistema en caso de tener acceso a una consola.

[Al lío]
Ejecutar en una consola:
$ alias sudo="sudo touch /root/owned && sudo"
Nótese que ya se ha `infectado` la consola actual. En caso de que ahora el usuario legítimo ejecute cualquier comando usando "sudo", se le pedirá la contraseña, se ejecutará un comando arbitrario con privilegios de administrador (en nuestro comando de ejemplo 'touch /root/owned'), y después se ejecutará el comando que el había puesto, sin que el usuario se percate que ha ejecutado un comando adicional. Para hacer permanente el cambio se puede ejecutar:
$ echo 'alias sudo="sudo touch /root/owned && sudo"' > ~/.bashrc
Y por ejecución de "comando adicional" podríamos entender: crear un usuario de sistema con privilegios de administrador, ejecutar un borrado de todo el disco, instalar un backdoor, programación de una tarea de descarga de un script remoto y ejecutarlo con privilegios de root o peor todavía: cambiar el fondo de pantalla[2].... Vamos, que tenemos privilegio de root y podemos hacer lo que nos dé la gana.

Ahora simplemente tenemos que esperar que el usuario teclee algo así como:
$ sudo aptitude update #por ejemplo
[sudo] password for inedit:

Y ya hemos comprometido el sistema. Bonito, ¿verdad?
$ ls -l /root/owned
-rw------- 1 root root 0 Mar 26 20:48 owned

Seguro que si alguien hace algo así en tu máquina no te hace tanta gracia.

[Prevención]
¿Modos de prevenir esto? Pues pocos, la verdad. El comando alias es un funcionalidad del bash (man bash) que puede ser desactivada mediante el comando:
$ shopt -u expand_aliases
Pero también puede ser activado por el mismo atacante con el comando ("shopt | grep expand_aliases" para ver el estado actual):
$ shopt -s expand_aliases

Este método sólo aplicaría a bash. Si se usara una consola xterm o ksh se tendría que buscar el modo concreto de hacerlo en estas otras consolas, pero seguro que existen vías similares (si no iguales)

[Moraleja]
Que nadie toque tu portátil/PC. Nadie. Y muchos menos si es alguien que tiene conocimientos medios en sistemas Unix-like. Os pueden hacer un traje. Cuando el PC/portátil queda desatendido, debe ser bloqueado de algún modo (pidiendo contraseña, etc...). Y aún así uno no puede estar seguro que salga un zero-day[3] (que en realidad era un feature!!!) y te jodan el tinglado de mientras vas a echar un meo. Los sistemas Linux son muy versátiles, pero esta versatilidad puede jugar en tu contra algunas veces. Si alguien ha tocado tu sistema, aunque no sepa la contraseña de root te puede tangar sin problemas. Y si no la sabe pero la quiere existen otros muchos recursos que ya veremos mas adelante.

Un saludo.


[1] http://inedit00.blogspot.com.es/2009/10/reset-en-linux.html
[2] http://www.seginformatica.net/2012/03/ataque-de-david-hasselhoff-evolucion.html
[3] http://seclists.org/oss-sec/2012/q1/191

sábado, 17 de marzo de 2012

Erlang (III) Semana 1

Semana 1

Después de hacer una Semana Cero* de: aprender, aprender, aprender, aprender, aprender.... he empezado el proyectito.

La primera semana simplemente es para jugar y hacer pruebas. Quería empezar creando una primera versión de mi chat. En realidad he rehecho el código 4 veces des de cero, mejorando cada vez la versión anterior. El objetivo primero era conseguir dar de alta usuarios (login), y que pudiesen mandarse mensajes entre ellos. Todo a través de la línea de comandos (intérprete de Erlang). Después también he pensado que estaría bien hacer un poquito de benchmark para probar si la idea básica funciona, o todavía necesito aprender más cosas antes de empezar.

Básicamente estas "iteraciones" de ir rehaciendo código y mejorándolo según los errores y problemas aprendidos ha sido algo así:
  1. Escrito código 100% custom que se encarga de la gestión de mensajes, sin hacer uso de OTP. Básicamente se disponen de dos módulos: gaab_server y gaab_user. El primero sirve para saber qué usuarios que están registrados en el chat, el segundo módulo tiene todas las funcionalidades de un usuario, y dispone de funciones tales como send_message, receive_message, talk_with, ....
  2. Reescrito el código ahora haciendo uso de records para manter el estado e implementando una interfície muy parecida a gen_server, pero todavía hecho todo 100% custom.
  3. Usar gen_server tanto para el gaab_server como para gaab_user, quitar toda la funcionalidad custom que ya me dá gen_server.
  4. Creado un Makefile, organizado el proyecto en las carpetas correspondientes (src, ebin,...) y demás.


[Cómo funciona]

Explico un poquito más cómo funciona el tema... Tenemos un agente de gaab_server que se encarga de almacenar los usuarios logeados. Básicamente el flujo normal será loguearnos en gaab_server y éste creará un agente de tipo gaab_user, y nos devolverá su Pid. El servidor también tiene una función llamada pidof/1 que devuelve el Pid del usuario pasado como parámetro. Simplemente se encarga de saber qué usuarios están logueados en el sistema.

El agente gaab_user tiene funciones para hablar con otros usuarios, y siempre está a la espera de recibir mensajes dirigidos hacia el, que imprime por pantalla. Todo muy simple, por ser una primera versión.

[Benchmarcks]

Vamos a lanzar un par de tests para comprobar que, efectivamente, el servidor soporte algo de carga. Se van a medir básicamente dos cosas: coste de CPU y coste de memória. Los dos parámtros con los que jugamos son básicamente dos: número de usuarios conectados al mismo tiempo y número de mensajes por segundo enviados entre usuarios. La máquina con la que trabajamos es la siguiente:

Memória RAM: 6GiB DDR (1066).

CPU: Intel i5 - M540 2.53GHz (2 cores + 2 de Hyperthreading)


Empezemos.

Prueba 1. Aumentar número de usuarios

1.1 - Número de Usuarios: 10K. Mensajes por segundo: 500.

Carga de CPU ~50% de carga en un core (~13% de el procesador).

Memória total del proceso: 46.336 Kbytes. Memória por usuario: 2,98 Kb.

1.2 - Número de Usuarios: 20K. Mensajes por segundo: 500.

Carga de CPU ~50% de carga en un core (~13% de el procesador).

Memória total del proceso: 78.656 Kbytes. Memória por usuario: 3.11 Kb

1.3 - Número de Usuarios: 30K. Mensajes por segundo: 500.

Carga de CPU ~50% de carga en un core (~13% de el procesador).

Memória total del proceso: 87.692 Kbytes. Memória por usuario: 2.37Kb


Prueba 2. Aumentar el número de mensajes/segundo
2.1 - Número de Usuarios: 10K. Mensajes por segundo: 500. (prueba 1.1 anterior)

Carga de CPU ~50% de carga en un core (~13% del procesador).

Memória total del proceso: 46.336 Kbytes.

2.2 - Número de Usuarios: 10K. Mensajes por segundo: 750.

Carga de CPU ~75% de carga en un core (~20% del procesador).

Memória total del proceso: 37.244 Kbytes.

2.3 - Número de Usuarios: 10K. Mensajes por segundo: 1000.

Carga de CPU ~85% de carga en un core (~23% del procesador).

Memória total del proceso: 30.366 Kbytes.


**Nota: El proceso de Erlang por si solo ocupa 16.508 KBytes.

[Conclusiones]
Pues todo exactamente como esperébamos. Crear muchos usuarios no tiene coste computacional, solo un coste de memória. Ahora mismo los actores son muy chiquititos y pesan unos 3Kbytes. Aún así esta cifra es muy subjetiva ya que dentro de poco la aplicación empezará a crecer, y los usuarios tendrán que guardar un poco más de información, pero no mucha mas. Esto significa que, a priori, con 1GB de RAM podemos tener unos 300K usuarios activos, en este momento ( ya veremos cuando pongamos conexiones TCP por enmedio, jeje... ). Si quisiéramos llegar a 1 millón de usuarios al mismo tiempo, con 4GB para los procesos de usuario, de momento debería ser suficiente (pero lo dicho, ya veremos).

Si los usuarios se mandan muchos mensajes entre ellos aumenta el consumo de CPU. Normal. A más mensajes, más carga. Hombre, 1.000 mensajes por segundo son unos cuantos, no está nada mal, pero prácticamente ocupan un core de CPU, por lo que el consumo no es nada despreciable. Tampoco tengo muy claro en aplicaciones grandes cual es el ratio de número_de_usuarios/número_de_mensajes_por_segundo. Pero bueno, ya lo descubriremos.


Pues nada. Este es el resumen de mi Semana 1. La próxima entrega incluye el servidor web MochiWeb, interfazes web, HTML+CSS+JS, AJAX y la integración de lo que hemos venido haciendo hasta ahora con todo lo anterior.

Un saludo, Jan.

* En realidad Semana Cero es un modo de hablar. Aprendiendo las bases de Erlang me ha llevado entre 2-3 semanas de una o dos horitas al día (cuando todavía trabajaba).

Post siguiente: Erlang (IV) Semana 2

martes, 13 de marzo de 2012

MOC ha muerto. Exaile sube al ring.

Pues esto, el reproductor de consola moc ha muerto. Me parece que ha sido después de una actualización de algún paquete de audio o algo así, que hace que moc no funcione bien; consume un 100% de CPU, no cierra el cliente de ncurses.... vaya, que me había quedado sin música.

Y esto no puede ser.

He intentado instalar el rhythmbox pero me ha dicho que tenía que descargar 60 paquetes, descargar 50,7MB y resolver chorrocientas dependencias. Já! Estás que instalo yo algo así. He buscado un poquitín y me he encontrado con el reproductor Exaile: liviano, muy simple de usar, controles muy simples y se puede pausar/pasar canción/etc des de el try-icon. Está en los repositorios de debian, por lo que mola. Una pena que no sea una aplicación por consola, pero bueno... me acostumbraré.

Aunque no sea un programa 100% por consola, no quita que no se le puedan pasar parámetros al programa por consola. Esto nos dá libertad total para crear shortcuts. Por ejemplo, hacer que Control-Alt-P ejecuten "exaile --play-pause" y así poder poner play/pause con una simple combinación de teclas (y evitamos tocar el ratón).

Pues nada, que me ha gustado. Cuando hagan el fix en moc, me vulevo a pasar a la aplicación de consola, pero de mientras iré tirando de exaile.

Edit1: Anónimo1 me ha propuesto probar cmus, y la verdad es que me ha molado. Mas complejo, pero está chulo. Todavía no he descubierto si tiene la capacidad de reproducir emisoras de radio...
Edit2: Parece ser que el bug de Moc que me llevó a escribir este post ya está arreglado. Puedo usar Moc de nuevo.... pero seguiré usando Cmus una temporada, que en la variedad está el gusto (es algo que mi exnovia no entendió)

jueves, 8 de marzo de 2012

Erlang (II) Aprendiendo lo básico

Erlang. Erlang. Erlang. ¿Por dónde empezar a aprender?

Pues por muchos sitios. Hay un montón de documentación disponible, y un montón de tutoriales. Es suficiente con buscar un poquitín, para encontrarse con material de mucha calidad. Hoy recopilaré las fuentes que me han ido ayudando a aprender lo poco que sé de Erlang.

He decicido no hacer otro manual de Erlang mas, ya que toda la informaicón que se puede encontrar en Internet es mas que suficiente, y lo único que estaría haciendo sería repetir contenido.

[¿Qué es erlang?]
Lo explico con mis palabras (seguro que con inexactitudes e imprecisiones) y después pongo un par de enlaces ineresantes y un poco mas serios. Erlang es un lenguaje de programación funcional, de propósito general y altamente enfocado a la concurrencia. Se creó por la compañía Ericsson para ser usado en temas relacionados con la telefonía (programación de PBX, etc). Una de las características de la telefonía es que necesita acceptar mucha concurrenicia (número de llamadas al mismo tiempo), tiene que ser tolerante a fallos (si una llamada ocasiona un problema, las demás llamadas deben continuar), tiene que tener un downtime mínimo por lo que implementa un sistema de cámbio de código "en caliente" (ya que siempre hay llamadas establecidas, y una parada de sistema significa dejara sin servicio a los clientes), no existen datos comparitos, ( de este modo se eliminan muchos problemas de concurrencia y bloqueos ), los procesos, también llamados Agentes o Actores, son partes de código que se ejecutan de modo independiente, y que se comunica entre otros procesos mediante mensajes (no son procesos de Sistema, estos "procesos" son gestionados por la máquina virtual de Erlang ). Crear Actores (o procesos) de Erlang es *muy* barato computacionalmente, o sea 1µs. En C# o Java crear un proceso (de sistema) tarda unos 300µs. En erlang se pueden crear literalmente millones de procesos, mientras que en Java/C# no se puede crear mas que unos 2.000. Otra característica muy chula del lenguaje es que estos Procesos-Erlang (o también llamados Agentes o Actores) se pueden ejecutar en cualquier Core o CPU de tu ordenador. De hecho, se pueden ejecutar en otra máquina especificando un parámetro adicional. Esto nos dá la libertad de poder escalar horizontalmente de una manera increíble. Normalmente el mismo Erlang ya hará uso de toda la capacidad de procesamiento de un mismo ordenador (usando todos sus cores), de manera transparente para el usuario y sin tener que programar un línea de código adicional. Pero si se añade una máquina más, es tan simple como decirle a Erlang "'ei! Te he añadido mas recursos. ¡Úsalos!".... y punto :)

Bueno, vayamos con las definiciones mas serias.

Obviamente tenemos la web de wikipedia, pero la vamos a usar sólo para echarle un vistazo general a las definiciones de qué es Erlang y ver un poquito cómo se vé el código en este lenguaje. Erlang es un lenguaje funcional, lo que quiere decir que hace uso intensivo de recursividad y demás. Las variables solo pueden ser asignadas una vez (sisi, literalmente. Solo una vez. Divertido, ¿verdad?). Que estos conceptos no te asusten. Es simplemente cambiar el chip. En uno de los manuales que enlazaré mas adelante se explica todo, y queda todo muy claro.

Después lo mejor será que el mismo Joe Armstrong, uno de los creadores principales de Erlang, nos cuente sus bondades (las de Erlang, no las suyas). Hay otra charla exactamente igual en contenido pero para un publico mas senior (o mas enterprise, no lo tengo muy claro) y por lo tanto menos divertida. Esta está muy chula.

[Empezando a jugar]
Para ir metiéndonos en tarea, podemos echarle un vistazo al curso de la web oficial de Erlang, que dicen que está un poco desfasado, pero está muy bien explicado cómo usar las features claves del lenguaje. Todo muy escueto, pero bastante útil para entender los conceptos básicos y saber qué nos vamos a encontrar. Hay cinco módulos: History, Sequential Programming, Concurrent Programming, Error handling y Advanced Topics. Recomiendo que se lean con calma e intentando entender todo lo que se pueda. También hay un apartado de ejercicios para practicar lo aprendido. Muy útil.

Y aquí viene el punto fuerte. La guía definitiva. Learn you some Erlang[1]. La polla en bicicleta. Cuando acabe de leerme la guía entera me voy a poner en contacto con el tío y le mandaré 50€ para que se vaya a tomar unas cervecitas al bar, porque la verdad que se lo ha currado. Son 30 capítulos. Cada uno explica una parte de Erlang. Empieza primero con la história, cómo instalar el intérprete de erlang, tipos de datos, los módulos, la sintaxis de las funciones y los pattern matching, recursividad, funciones de alto nivel, errores y excepciones, concurrencia, multiprocesos, y un laaaaaaargo etc. Una pasada, oye.

Ya en la introducción el autor dice que es necesario unos conocimientos básicos de programación en lenguajes imperativos (Python, C/C++, Java, Ruby...) y que no hace falta tener conocimientos de lenguajes funcionales (Scala, Haskel, CLisp, Clojure....). Vamos, que empieza des de cero y es muy fácil de ir siguiendo. Todo está con ejemplos de código que podemos ir siguiendo nosotros mismos ( y debemos hacerlo ), y hasta te dá los códigos fuente de todos los programillas que se van creando durante el curso/libro.

Otra cosa muy buena que tiene el autor es que te cuenta lo que es Erlang, y no te lo intenta vender. Te cuenta sus cosas buenas, y sus cosas malas. Para lo que sirve, y para lo que no sirve. Normalmente las guías siempre te dicen: "aprende a programar en el mejor leguaje de programación del mundo" ( yo almenos tengo dos libros en casa que en la portada aparece este lema, siendo lenguajes de programación distintos ). El autor siempre intenta explicarte las bondades del lenguaje, pero te dice cuáles son sus limitaciones. Muy chulo, la verdad.

[Otra información interesante]
Hay una pregunta en Stack Overflow sobre por qué los procesos de Erlang son mas eficientes que los Threads del SO que es muy interesante. También tenemos otra entrada (que sinceramente todavía no he probado[2]) sobre plugins de Erlang para el Vim (resaltado de sintaxis, introspección en los módulos, completion... lo típico, vamos).

Hay otra página, de un tal Richard Jones co-fundador de Last.fm, en donde explica cómo construir una aplicación de un millón de usuarios en Erlang. Son tres entradas muy muy interesantes. Yo me lo leí cuando empezaba con Erlang y me fascinó, aunque sinceramente me enteré de poco. Ahora cada vez lo entiendo mas, y lo utilizo como referéncia para ir cogiendo ideas y ver cómo ha solucionado algunos problemas.

Otro artículo interesante, aunque mucho mas específico, es un ejemplo práctico de cómo usar el framework web MochiWeb. Si quieres crear un servidor web, MochiWeb te puede solucionar la papeleta. Es muy ligero, y te dá todos los recursos necesarios para manejar los request/responses. En éste artículo te explican cómo crear un pequeño dispacher de los requests que llegan, y un modo de devolver las respuestas de manera simple.

Y nada, de momento esto es todo. Te animo a que le des una oportunidad. No es difícil: Es diferente. Pero muy divertido, y con el que se pueden hacer cosas realmente chulas. Yo estoy difrutando un montón. Para cualquier cosa, dudas, preguntas o aclaraciones, no dudes en dejar tu comentario.

Un saludo, Jan.

Edit: Añado otro vídeo muy chulo de Joe Armstrong.
Edit[2]: Vale, ya he probado el pluguin para el Vim y aquí están mis impresiones.
Siguiente post: Erlang (III) Semana 1
Post anterior: Erlang y WebChats (I)
[1] Hay un grupo en argentina que está traduciendo este magnífico trabajo, para al que no le vaya demasiado bien esto del inglés.

Generar una clave pública a partir de una clave privada (SSH)

Típica tontería. Tenemos la llave privada SSH en nuestro PC pero por lo que sea hemos perdido la llave pública de esta clave.
Solución? Pues generar la clave pública otra vez, que se puede recalcular a partir de la clave privada.
El comando es muy simple:

$ ssh-keygen -f ~/.ssh/key -y > ~/.ssh/key.pub

Nos pedriá la contraseña de la clave privada ( ¿por que que tenemos cifrada la clave privada, verdad? )
Y estamos listos.

Si quisiéramos sacar el fingerprint de la clave[1], sería tan fácil como ejecutar

$ ssh-keygen -l -f ~/.ssh/key.pub
2048 71:1a:34:94:1b:61:60:09:0c:00:54:e8:ad:17:97:ec key.pub (RSA)


[1] http://inedit00.blogspot.com/2009/11/comprobar-fingerprint-en-ssh.html

martes, 6 de marzo de 2012

Erlang y WebChats (I)

[INTRODUCCIÓN]
¿Sabes esta sensación que te recorre el cuerpo cuando te miras a los ojos con otra persona y estás seguro de que es tu alma gemela, de que has encontrado el amor de tu vida, y que no quieres mas que pasar el resto de tu vida con ella?

Pues yo no.

Pero supongo que algo parecido me ha pasado con Erlang. Bromas aparte. Es un lenguaje de programación que me ha encantado y al que le pienso dedicar muchas horas en los próximos meses. No se si ha sido amor a primera vista, o que simplemente me pilla en un momento en el que me molan las cosas chungas, extrañas y muy diferentes.

[PROBLEMA]
Os explico de donde viene todo esto. Resulta a través de highscalability.com acabé en una página del blog de What'sApp[1] en donde pone algo tal que así:

[...] Over the past few months we have been making a lot of improvements to our servers to increase the performance, uptime and scalability. Today we have tuned some knobs, shifted some traffic around and achieved 1 million established tcp sessions on a single machine [...] For those curious how we did it, the technology on the backend is simple: FreeBSD + Erlang [...]
Un millón de conexiones TCP. En una sola máquina ¡Wow!

Justo cuando lo leí me entró muchísima de curiosidad por el tema. Las únicas pistas que daban eran FreeBSD (SO que Unix-like, que ya he probado en casa alguna vez) y.... Erlang. ¿Qué es Erlang? Pues de la wikipedia[2] sacamos (y marco las partes que me llamaron la atención):

Erlang es un lenguaje de programación concurrente. El subconjunto de programación secuencial de Erlang es un lenguaje funcional, con evaluación estricta, asignación única, y tipado dinámico. Fue diseñado en la compañía Ericsson para realizar aplicaciones distribuidas, tolerantes a fallos, soft-real-time y de funcionamiento ininterrumpido. Proporciona el cambio en caliente de código de forma que éste se puede cambiar sin parar el sistema. Originalmente, Erlang era un lenguaje propietario de Ericsson, pero fue cedido como software de código abierto en 1998.

Bueno, suena genial. Pues solo con esta información, o sea, sabiendo que WhatsApp había conseguido tener 1M de conexiones TCP en una misma máquina, y viendo mas o menos las caraterísticas principales de Erlang me dije: Si ellos han podido, yo también puedo.

[NUDO]
Umm.... si lo piensas así en frio puedes decir: cágate, lorito. Y entonces me comentarías:
- A ver, Jan. No sabes cuantos empleados tiene What'sApp. Ni la pasta que manejan. Ni los cracks que puedan tener contratados. Ni muchas otras cosas que pueden influir en el éxito de un proyecto así.... ¿No crees que te estás pasando un poquitín?
Y yo te voy a contestar:
- Pues no. Ellos han conseguido hacer un millón de conexiones TCP's a una sola máquina. Y si ellos pueden, yo también. Y punto.

[PRESENTACIÓN DEL PROBLEMA/EJECRCICIO]
Bien. Entonces necesito pensar en un proyectito que sea chulo, y con el que aprender Erlang. A la vez tiene que ser algo lo suficientemente simple como para que el problema no me sobrepase al inicio, pero que lo pueda ir complicando bastante a medida que vaya aprendiendo. Y, ¿en qué he pensado? Pues en un Web Chat!

¿Que qué es un web chat? Pues hombre, algo como "el chat de facebook" ( ¬¬' así seguro que todo el mundo lo entiendea).

Pues nada, la gracia es hacer un WebChat que soporte mucha carga. Se tendrá que desarollar tanto la parte cliente (HTML+CSS+JS), como el servidor web (en Erlang), así como proceso de chat en si mismo (en Erlang también) y el posible acceso a datos.

¿El objetivo cuál es? Pues conseguir un servidor de chat que soporte mucha carga. De momento me conformaré con tener 10.000 usuarios funcionando al mismo tiempo (problema C10K[3]). Después intentaremos mejorar lo posible para llegar a 100K usuarios, y si no veo muy negro el tema, el objetivo final será conseguir 1M de usuarios (conexiones TCP al mismo tiempo) contra una misma máquina y obviamente que puedan hablar de manera flúida entre ellos y demás.

[RETO]
Cagonlaputa. Resulta que los de WhatsApp me están retando. Seguro que lo han hecho aposta. Han publicado un nuevo post en el blog[4] titulado "1 million is so 2011". El artículo dice:

Happy 2012 everyone!
A few months ago we published a blog post that talked about our servers doing 1 million tcp connections on a single box[1].

Today we have an update for those keeping score at home: we are now able to easily push our systems to over 2 million tcp connections!

Vale. Ya está. Si ellos han conseguido 2M de conexiones TCP en una misma máquina, des de luego que yo puedo conseguir 1M. En el mismo artículo también comparten información sobre lo que ellos entienden por una misma máquina y..... bueno.... ejem

hw.machine: amd64
hw.model: Intel(R) Xeon(R) CPU X5675 @ 3.07GHz
hw.ncpu: 24
hw.physmem: 103062118400

¡¡¡Alaaaaaa!!! ¡Vaya maquinón! 24 cores a 3.07GHz cada uno, y 103GB de memória RAM. ¡Trabajar así da gusto! Ya veremos si yo puedo acercarme o no... esto no me desanima, sino que hace que el reto sea mejor =)

[DESENLACE] (Hay desenlace porque a mi me contaron en el cole que tenía que haber siempre una presentación-nudo-desenlace)

Pues nada, que próximamente vendrán toda una serie de entradas sobre el tema. Aprender Erlang, ver sus cosas buenas y sus cosas malas, enlazar un motón de documentación útil, ver algunos ejercicios propuestos, ver qué es OTP, ver el enfoque que le damos al tema del WebChat, los benchmarks que van saliendo, las mejoras que se hacen y demás. Lo más seguro que el proyecto acabe siendo publicado en un repositorio de github/bitbucket con una licencia OpenSource ( mi primer proyecto OpenSource!! =) )

¿Que te mola el rollo? pues sigue el blog y las entradas que voy publicando. Te van a gustar. ¿Que no te mola?, no lo leas; me la suda[5].


Muy señores míos, un saludo!!



(haré como los de What's App, que queda super molón)
P.S. - Ahora mismo no busco trabajo pero las ofertas siempre son bienvenidas. Si estás interesado en contratarme, envia información de algún proyecto chulo a inedit00 [2] gmail [.] com. (Yo también busco becarias para hacer summer-interships ;)

[1]: http://blog.whatsapp.com/index.php/2011/09/one-million/
[2]: http://es.wikipedia.org/wiki/Erlang
[3]: http://www.kegel.com/c10k.html
[4]: http://blog.whatsapp.com/index.php/2012/01/1-million-is-so-2011/
[5]: http://inedit00.blogspot.com/2009/09/mi-primera-vez.html