martes, 13 de agosto de 2024
lunes, 11 de febrero de 2013
Heroku y PiCloud en acción (draft público)
Resumen
Vamos a utilizar Heroku y PiCloud para implementar en Python un algoritmo genético distribuido utilizando evospace como gestor de la población. La población será almacenada en redis y será accesada por medio del servidor web cherrypy, el cual simplemente servirá como servidor http para la libreria evospace. Por otro lado estarán los workers, que son procesos que tomarán muestras de la población, la evolucionarán localmente por ciertas generaciones y regresarán los resultados de nuevo al contenedor central. Para implementar el algoritmo genético, el código de los workers utilizará la librería deap. Haremos pruebas con 2, 8 y 10 workers ejecutándose simultáneamente de forma asíncrona. Queremos saber que tanto mejora el desempeño al aumentar el número de workers y otros parámetros. También será importante reportar la posibles ventajas de utilizar plataformas como servicio (PaaS) para este tipo de tareas.![]() |
| Arquitectura general |
Heroku
Heroku es actualmente una PaaS multilenguaje que soporta ademas del lenguaje original Ruby, a Java, Node.js, Scala, Clojure y Python. Heroku nos permite utilizar "dynos" que es el nombre que en Heroku le dan a contenedores aislados de procesos de tres tipos: web, worker o cron, los cuales explicaré más adelante. Según van Rooijen en una plática en Quora a cada dyno podemos verlo como una unidad de procesamiento equivalente a una máquina virtual con 512Mb de ram base, 1Mb de memoria swap y un procesador de 4 núcleos (Intel Xeon X5550 @ 2.67GHz). Cada dyno solo puede utilizarse para ejecutar un proceso, Una aplicación web podría utilizar un web dyno para un proceso que esté recibiendo peticiones http (en nuestro caso cherrypy), pero si además utiliza un sistema de base de datos, lo cual es otro proceso a parte, este deberá ejecutarse en su propio dyno. El dyno utilizado para ejecutar el sistema de BD es de tipo worker. Estos se distinguen de los tipo web por que no reciben peticiones http. A parte si queremos utilizar otros procesos de corta vida, por ejemplo un trabajo cron o incluso una conexión ssh pues tenemos que utilizar otro dyno ahora tipo cron. La proupuesta de Heroku es cobrarnos no por un servidor al mes, si no por cada proceso por hora (prorrateando al segundo). Otro aspecto importante de Heroku son los Add-Ons que nos permiten agregar funcionalidad a nuestras aplicaciones de una forma muy rápida. Por ejemplo, si queremos usar como almacenamiento a MongoDB, Memcached, redis, Hadoop etc. solo lo agregamos a nuestra aplicación y listo, estará disponible para nuestro código.¿Y el costo?
Los dynos cuestan $0.05 la hora, prorrateando al segundo. Por ejemplo, si usamos 4 dynos, por cada hora pagaríamos $0.20, si los usamos todo el mes sin parar nos costaría 107 dolares. Mucho más que un VPS 512 de Linode en el cual uno puede ejecutar los procesos que ocupe con un costo fijo de $19.99 al mes. Aún recordando que cada dyno es equivalente a un Linode 512, el costo en Heroku es mayor. Heroku sin embargo tiene sus ventajas, primero nos regala 750 horas por aplicación, es decir que podemos usar un dyno sin parar todo un mes, o claro dos dynos por 15 días, o 4 por 7.5 días etc.Ventajas
El objetivo de este post no es hacer una comparación completa entre las distintas plataformas para desarrollo de aplicaciones web, pero creo que hay que hacer mención de las ventajas que veo en Heroku con respecto a otras opciones basadas en servidores virtuales como Linode.- Administración. Con un VPS una vez elegido el sistema operativo base, hay que instalar todos los servicios que ocupemos: openssh, apache, mysql, python, redis, gunicorn, nginx, etc. Actualizarlos cada vez que sea necesario, aplicar parches etc. En heroku el "deployment" se hace a través de un repositorio git, es decir solo basta con sincronizar nuestro ambiente local con el repositorio en Heroku y listo. Las librerías que requiera nuestra aplicación son instaladas en el servidor y los servicios externos puestos a disposición de nuestra aplicación. La cosa es un poco más complicada que esto, pero si que es rápido.
- Plan de pago. El costo por hora es atractivo para investigadores y desarrolladores los cuales necesitan en ocasiones que experimentar por periodos cortos de tiempo. Si se utiliza en total menos de 750 horas/dyno al mes, la cosa sale gratis.
- Escalabilidad. Heroku está implementado sobre el EC2 de Amazon y se puede incrementar la capacidad de nuestra aplicación fácilmente, con solo ejecutar un comando o mover un slider. Claro, siempre que nuestros recursos lo permitan.
Instalación básica de Heroku
Seguiremos los pasos de la página de Heroku, con una que otra observación especifica para nuestro proyecto. Primero el quickstart, general:Paso 1. Suscribirse al servicio para obtener una cuenta en Heroku, esto es gratis para el servicio más básico, pero cuidado para utilizar Add-Ons u otros componentes como redis, que utilizaremos en este proyecto, es necesario ingresar los datos de una tarjeta de crédito (me temo que para seguir este tutorial es necesario, aunque hay otras opciones como utilizar EC2 ). Este requerimiento lo hacen yo creo, para que no armemos nuestro grid gratis en Heroku simplemente con nuestras cuentas de correo.
Paso 2. Una vez activada la cuenta, estarás en el dashboard ahi debes bajar el heroku toolbelt, para el sistema operativo que estés utilizando. Puedes aprovechar de una vez para validar tu cuenta. El toolbelt consiste en:
- El cliente heroku. Una herramienta de linea de comandos (CLI), para administrar tus aplicaciones.
- Foreman. Una herramienta para ejecutar tus aplicaciones localmente.
- Git. El sistema de control de versiones para subir las aplicaciones a Heroku.
$ heroku login Enter your Heroku credentials. Email: ********************** Password (typing will be hidden):***************** Could not find an existing public key. Would you like to generate one? [Yn] Generating new SSH public key. Uploading ssh public key /Users/adam/.ssh/id_rsa.pub
El comando login utiliza una clave ssh para conectarse de forma segura Heroku. Podemos utilizar la clave generada por el script, simplemente presionando enter en la pregunta. Para probar estos ejemplos utilicé una cuenta de personal distinta a mi cuenta de trabajo. Esto me dio problemas ya que Heroku requiere una clave ssh distinta para cada cuenta. Si tienen requerimientos similares les recomiendo el plug-in hecho por ddollar, que nos permite operar Heroku con varias cuentas, sin cambiar la configuración manualmente. Con eso termina la parte básica de la instalación de las herramientas de Heroku para el deployment de aplicaciones.
Python en Heroku
Prerequisitos
PythonProbablemente ya cuentas cuentas con interprete de python en tu computadora, sin embargo Heroku requiere que el interprete que usas sea la versión 2.7. Puedes bajar el interprete de la página oficial, o yo recomiendo bajar enthought la cual es una distribución más completa del lenguaje, con librerías adicionales para computo científico. Si gustas puedes instalar un ambiente integrado de desarrollo o editores editores de texto apropiados. Yo en particular utilizo PyCharm (con licencia académica) otra buena opción es Komodo.
PIP
Después de instalar python, debemos instalar pip (pip installs packages) que es un instalador de librerías para python, algo así como el apt-get de ubuntu o el anterior instalador de python easy_install. Para instalar pip podemos bajar un instalador y ejecutarlo como administrador:
$ curl -O https://raw.github.com/pypa/pip/master/contrib/get-pip.py $ sudo python get-pip.pyListo. Utilizaremos pip para instalar las otras librerías que ocupamos.
Virtualenv
virtualenv es una herramienta para crear ambientes aislados de desarrollo en python, nos permite tener una versión del interprete y librerías especificas para un proyecto sin que afecte a lo demás. Su instalación con pip es muy fácil:
$pip install virtualenvYa con estas herramientas instaladas procedemos preparar nuestro ambiente local de desarrollo.
Ambiente local de desarrollo
Primero debemos crear el directorio donde estará nuestro ambiente local. Vamos a nombrarlo evotest y nos ubicamos dentro del mismo:$ mkdir evotest && cd evotestAhora creamos el ambiente, lo llamamos venv:
$ virtualenv venv --distribute New python executable in venv/bin/python Installing distribute...........................done. Installing pip................done.
Para trabajar con el nuevo ambiente debemos activarlo:
$ source venv/bin/activate
Al activar el ambiente el prompt mostrará el nombre del ambiente:
(venv)$Ahora con el ambiente activado procedemos a instalar nuestro código y librerías necesarias. Recordemos que el ambiente actual solo tiene las librerías básicas de python y está aislado, lo que significa que aunque ya se hubieran instalado previamente algunas librerías en nuestra máquina, debemos hacerlo de nuevo para este ambiente. En nuestro caso requerimos del web server cherrypy y la librería cliente de redis. también ocupamos el código de evospace y el script de arranque del servicio web.
Para instalar las dependencias utilizamos pip.
$ pip install redis $ pip install cherrypy
git
Antes de instalar el código de evospace, el cual clonaremos de gituhub es necesario crear primero un repositorio para nuestro proyecto:$ git init Initialized empty Git repository in /Users/mariosky/evotest/.git/Agregamos al repositorio los archivos que hemos creado hasta este momento.
$ git add .Ahora agregaremos a nuestro repositorio de git el código de evospace. Como éste se encuentra hospedado en github lo agregaremos como un sub-modulo.
git submodule add https://github.com/mariosky/evospace.gitEl comando anterior creará un subdirectorio con los archivos cherry_server.py y evospace.py. Ya tenemos los archivos necesarios para nuestro proyecto, solo nos falta crear dos archivos que requiere Heroku para saber como configurar el ambiente remoto y que tipos de procesos se utilizarán.
requirements.txt
Heroku sabrá que dependencias instalar por medio de un archivo que debe llamarse requirements.txt. Creamos el archivo de requerimientos usando pip:$pip freeze > requirements.txt
Procfile
Utilizamos un archivo de texto llamado Procfile para decirle a Heroku que tipos de dyno utilizará nuestra aplicación y el comando que arrancará dicho proceso. En nuestro caso es un dyno tipo web y el comando es solo ejecutar el script cherry_server.py . Para nuestro caso el archivo Procfile debe incluir solo esta línea:web: python evospace/cherry_server.py
Antes de agregar el código al repositorio vamos a hacer un archivo .gitignore donde le especificamos a git que archivos debe de ignorar. En nuestro caso tendría las siguientes entradas:
venv
*.pyc
.idea*
La primera línea es para que ignore el directorio del ambiente venv, la segunda para que ignore los archivos de python precompilados los cuales tienen extensión .pyc y en mi caso los archivos de proyecto de PyCharm que empiezan con .idea. Recordemos que los archivos que empiezan con un punto son ocultos en sistemas POSIX.
En este punto la estructura de nuestros archivos debe ser esta:
![]() |
| Archivos de nuestro proyecto |
- Código en el directorio evospace.
- Ambiente virtual de python en venv.
- Archivos por ignorar en .gitingnore.
- Tipo de procesos y comandos de ejecución en Procfile
- Dependencias en requirements.txt
Deployment a Heroku
Como primer paso debemos crear una aplicación en Heroku, esto lo haremos desde la herramienta CLI:$ heroku create
Creating murmuring-mesa-7774... done, stack is cedar
http://murmuring-mesa-7774.herokuapp.com/ | git@heroku.com:murmuring-mesa-7774.git
Git remote heroku added
El comando creará una nueva aplicación vacía y le pondrá un nombre generado automáticamente. Antes de subir nuestro código debemos agregar un almacén redis, donde evospace almacene la población. Una buena opción es el Add-On RedisToGo. Vista la página para ver la información detallada, aquí se muestra una imagen de los precios actuales:
Podemos utilizar la versión Nano la cual está disponible de forma gratuita, recordemos que para agregar Add-Ons es necesario validar la cuenta del usuario lo que requiere una tarjeta de credito. Si intentamos agregar a nuestra aplicación el RedisToGO sin haber validado nuestra cuenta tendríamos el siguiente error:
$ heroku addons:add redistogo:nano Adding redistogo:nano on murmuring-mesa-7774... failed ! Please verify your account to install this add-on ! For more information, see http://devcenter.heroku.com/categories/billing ! Verify now at https://heroku.com/verify
Una vez validada la cuenta, podemos agregar RedisToGo:
$ heroku addons:add redistogo:nano Adding redistogo:nano on murmuring-mesa-7774... done, v5 (free) Your Redis is in your preferred cloud (aws/us-east-1). Use `heroku addons:docs redistogo:nano` to view documentation.
Por fin podemos subir nuestra aplicación a Heroku, solo necesitamos actualizar el repositorio local, comprometer los cambios y subirlo.
$ git add . $ git commit -m "Iniciamos" $ git push heroku master
La instrucción push sube los cambios al repositorio en Heroku, esto desencadena que remotamente se bajen los los submodulos de github, se instalen las dependencias y finalmente se arranque el dyno. Si no hubo errores, desde el dashboard en Heroku podemos ver nuestro servidor y muy importante su costo mensual:
![]() |
| Heroku dashboard |
Monitoreo de la aplicación de la consola
Podemos ver los dynos que están ejecutándose actualmente en nuestra aplicación con el comando ps:$ heroku ps === web: `python evospace/cherry_server.py web.1: up 2013/02/13 23:04:10 (~ 41m ago)
En este caso está funcionando un solo dyno.
Se puede también vistar la página de nuestro proyecto:
$heroku open Opening murmuring-mesa-7774... done
O ver los logs:
$ heroku logs
Cero o más dynos
Mientras este ejecutándose solo un dyno de manera constante, el servicio es gratuito. En caso de ser necesario escalar a más de un dyno podemos aumentar el número de estos. Por ejemplo para aumentar a dos:
$heroku ps:scale web=2 Scaling web processes... done, now running 2
Cuidado por que esto puede ocasionar un costo, claro si los dejamos ejecutando por más de 15 días. Mejor apagaremos los web dynos, escalando nuestra aplicación a cero:
$ heroku ps:scale web=0 Scaling web processes... done, now running 0
Este tipo de operaciones se pueden hacer también desde el dashboard.
PiCloud
El otro componente de nuestro sistema son los workers, estos estarán ejecutándose en PiCLoud. En su sitio, PiCLoud promete ser una plataforma para ejecutar algoritmos en uno o miles de núcleos sin necesidad de administrar un solo servidor. En mi experiencia logran su objetivo y de una forma muy transparente. Para ejecutar una función de forma paralela en la nube, solo se importa una librería llamada cloud ejecutamos la función cloud.call() pasando como parámetros la función a ejecutar y sus parámetros, por eje,plo de forma interactiva podríamos definir la función suma:
Al ejecutar el método cloud.call(suma, 3, 3) el método suma, es enviado como una tarea a PiCloud junto con aquellas librerías de python que se hayan importado anteriormente y sus parámetros. El método regresa inmediatamente un identificador de tarea o "job id", el cual podemos utilizar para ver el estado de la tarea, con la función status. En caso de que ya se haya procesado, es decir que tenga status igual a "done", podemos ver el resultado con la función cloud.result(tarea_id).
Si requerimos ejecutar el método suma tres veces, lo mejor es utilizar la función cloud.map() la cual enviará las tareas en lote para que se procesen de forma paralela:
Indicar el tipo de recurso computacional que requerimos para la ejecución de la función es muy sencillo, por ejemplo:
El igual que Heroku, PiCloud nos ofrece precios que dependen del uso de los recursos, más que una cuota fija. También se cobra por hora de uso del recurso computacional, solo que prorateado al milisegundo. Al contar con más tipos de recursos y cobrar además por el almacenamiento y la transferencia de datos, el calculo del costo es más difícil que en Heroku. Por ejemplo el recurso de computo básico llamado c1, tiene un costo de $0.05/hora, si lo utilizáramos por 10 horas, requiriendo almacenar en el servidor 1GB al mes y con 10GB de transferencia de salida y soporte tipo Básico, tendría un costo de $2.26. La lista de precios y calculadora de costos se encuentra en picloud.com/pricing/. Al igual que en Heroku al nuevo subscriptor y por lo menos en mi caso, cada mes dan como regalo 20 horas de computo. Se puede hacer bastante con estas 20 horas aunque si lo vemos en costo esto es solo $1.00.
Heroku y PiCloud
Una ventaja de utilizar ambas plataformas es que ambas están ubicadas en la infraestructura de Amazon Web Services en la costa este de los Estados Unidos. Por lo que no se cobra la transferencia de datos entre PiCloud y Heroku, además de ser muy rápida. El soporte técnico aún en mi caso que no he pagado un centavo en los breves experimentos que he realizado es muy bueno. Me he comunicado por medio de chat y me han dado sugerencias que me han servido para resolver algunos problemas que he tenido al utilizar la librería deap.
GA Workers
Como caso de prueba, experimentaremos implementando un algoritmo genético (GA) para resolver el problema one max, que consiste en maximizar el número de unos que aparecen en una cadena binaria de longitud n. Dividiremos el GA en workers independientes los cuales tomarán una muestra de la población en evospace (en Heroku) y la evolucionarán por un numero de generaciones, para finalmente regresar la población resultante de la muestra de nuevo a evospace. Esto lo repetirán hasta encontrar el óptimo o hasta que se realicen cierto número de iteraciones. Cada proceso se ejecutará en PiCloud como una tarea. Una prueba sencilla, para ejecutar en PiCloud:
Prueba completa
def suma(a, b):
return a + b
Lo normal es ejecutar la función localmente de la siguiente manera:
>>>suma(3, 3) 6Para ejecutarlo en la nube, importamos a cloud y llamamos a cloud.call()
import cloud >>>tarea_id = cloud.call(suma, 3, 3) >>>cloud.status(tarea_id) 'done' >>>cloud.result(tarea_id) 6
Al ejecutar el método cloud.call(suma, 3, 3) el método suma, es enviado como una tarea a PiCloud junto con aquellas librerías de python que se hayan importado anteriormente y sus parámetros. El método regresa inmediatamente un identificador de tarea o "job id", el cual podemos utilizar para ver el estado de la tarea, con la función status. En caso de que ya se haya procesado, es decir que tenga status igual a "done", podemos ver el resultado con la función cloud.result(tarea_id).
Si requerimos ejecutar el método suma tres veces, lo mejor es utilizar la función cloud.map() la cual enviará las tareas en lote para que se procesen de forma paralela:
import cloud >>>map(suma, [3, 3, 2], [3, 2, 1]) [6, 5, 3] >>>tareas = cloud.map(suma, [3, 3, 2], [3, 2, 1]) >>>tareas = cloud.result(tareas) [6, 5, 3]
Indicar el tipo de recurso computacional que requerimos para la ejecución de la función es muy sencillo, por ejemplo:
import cloud >>>tareas = cloud.map(suma, [3, 3, 2, 3], [3, 2, 1, 3], _type='m1', _cores=4)Se ejecutaría en un recurso de computo m1, llamado "Well-Rounded" que consiste en 3.25 unidades de computo, 8GB de memoria, desempeño medio de I/O y Hyperthreading. Además utilizando 4 núcleos. Para más información ver la documentación.
El igual que Heroku, PiCloud nos ofrece precios que dependen del uso de los recursos, más que una cuota fija. También se cobra por hora de uso del recurso computacional, solo que prorateado al milisegundo. Al contar con más tipos de recursos y cobrar además por el almacenamiento y la transferencia de datos, el calculo del costo es más difícil que en Heroku. Por ejemplo el recurso de computo básico llamado c1, tiene un costo de $0.05/hora, si lo utilizáramos por 10 horas, requiriendo almacenar en el servidor 1GB al mes y con 10GB de transferencia de salida y soporte tipo Básico, tendría un costo de $2.26. La lista de precios y calculadora de costos se encuentra en picloud.com/pricing/. Al igual que en Heroku al nuevo subscriptor y por lo menos en mi caso, cada mes dan como regalo 20 horas de computo. Se puede hacer bastante con estas 20 horas aunque si lo vemos en costo esto es solo $1.00.
Heroku y PiCloud
Una ventaja de utilizar ambas plataformas es que ambas están ubicadas en la infraestructura de Amazon Web Services en la costa este de los Estados Unidos. Por lo que no se cobra la transferencia de datos entre PiCloud y Heroku, además de ser muy rápida. El soporte técnico aún en mi caso que no he pagado un centavo en los breves experimentos que he realizado es muy bueno. Me he comunicado por medio de chat y me han dado sugerencias que me han servido para resolver algunos problemas que he tenido al utilizar la librería deap.
GA Workers
Como caso de prueba, experimentaremos implementando un algoritmo genético (GA) para resolver el problema one max, que consiste en maximizar el número de unos que aparecen en una cadena binaria de longitud n. Dividiremos el GA en workers independientes los cuales tomarán una muestra de la población en evospace (en Heroku) y la evolucionarán por un numero de generaciones, para finalmente regresar la población resultante de la muestra de nuevo a evospace. Esto lo repetirán hasta encontrar el óptimo o hasta que se realicen cierto número de iteraciones. Cada proceso se ejecutará en PiCloud como una tarea. Una prueba sencilla, para ejecutar en PiCloud:
import onemax import cloud, time start = time.time() print "Se inicializa la población" cloud.call(onemax.initialize,300 ,_type='s1', _env="deap") print "Empieza la Evolución" jids = cloud.map(onemax.work, [5,5,5,5,5,5,5,5,5,5] , _type='s1' ) results_list = cloud.result(jids) print results_list, time.time()-start
Prueba completa
Suscribirse a:
Comentarios (Atom)




