Developing Frogtek

El blog del Departamento de Tecnología

Etiqueta: gae

Utilizando gzip en las comunicaciones

Como ya sabéis hace dos semanas estuvimos de ranatón. En mi equipo, uno de nuestros objetivos era optimizar las comunicaciones entre el servidor y el cliente. El objetivo era optimizar todo lo que no habíamos optimizado todavía, ya que, en Colombia (donde están la mayoría de nuestros usuarios), las tarifas de datos aún son muy restrictivas en cuanto a datos enviados/recibidos.

La comunicación actualmente se estaba realizando usando Json y en texto plano.

Tal como este:

{"D":1,"sale_code":"301","type":"sale",
"local_created":"2011-01-05 09:26:57.042","balance_sheet_code":"501",
"customer_code":"-1","products":{"generic1":{"Q":1,"P":300,"F":1}},
"final_price":300,"paid":1,"cash_operation_code":"401"}

En este ejemplo estabamos enviando una operación de tipo venta. Como primera optimización, decidimos acortar los nombres de las propiedades. De este modo nos quedó:

{"D":1,"SC":"301","T":"sale","LC":"2011-01-05 09:26:57.042",
"BS":"501","CC":"-1","PR":{"generic1":{"Q":1,"P":300,"F":1}},
"FP":300,"PD":1,"CO":"401"}

Así conseguimos reducir bastante el tráfico de datos, pero necesitabamos reducirlo todavía más, así que tomamos la decisión de utilizar la compresión gzip, y comprimir todo el texto enviado y recibido por el cliente. Y después de comprimirlo lo convertimos en una string con BASE64, de este modo formateabamos los datos sin retornos de carro y todo quedaba, si cabe, mas uniforme:

H4sIAAAAAAAAADWOzQoCMQyEX0Xm3JW03SrmaMWT
aHU9KR5EiwiyygpeSt/dtCIE8s3kN+H5AuMwrK3toXCNH5GkBT
fgY8ICrBU6L66t9l7ofX5EwVVxDWndkIQb0YzNhN10TK2R8ryT
sqtDvnQ2hcIOnHCLfRzuF114Wy8EsCVSWIrKWfLfCL8PvLyDVpb
lU/4C8o/at7UAAAA=

No es el caso más optimo para comprimir, pero hemos calculado que enviamos un 50% menos de datos al enviar la información comprimida. Para poder medir esto utilizamos WireShark con un filtro tal como este (Gracias Jose):

(ip.src == 192.168.1.9  &&
           ip.dst == 192.168.1.12 &&
           tcp.port == 8080)

Para poder realizar la compresión en el cliente Android utilizamos la clase GZIPOutputStream de este modo:

public static byte[] zipStringToBytes( String input  ) throws IOException
  {
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    BufferedOutputStream bufos = new BufferedOutputStream(new GZIPOutputStream(bos));
    bufos.write( input.getBytes() );
    bufos.close();
    byte[] retval= bos.toByteArray();
    bos.close();
    return retval;
  }

Y en la parte del servidor, nosotros utilizamos Google App Engine:

def decode_client_data(request_object):
    if(request_object.META.get('HTTP_CONTENT_ENCODING',None)!=None):
        gzip_string = base64.standard_b64decode(str(request_object.raw_post_data))
        url_file_handle=StringIO(gzip_string)
        gzip_file_handle = gzip.GzipFile(fileobj=url_file_handle)
        decompressed_data = gzip_file_handle.read()
        gzip_file_handle.close()
        return decompressed_data
    else:
        return request_object.raw_post_data

Gracias a la integración continua podemos asegurarnos de que ningún cliente trabajará contra una servidor que no acepte gzip, pero para evitarnos problemas y poder sacar versiones a producción del servidor sin tener que hacerlo del cliente, decidimos programar el servidor para que acepte operaciones sin comprimir y en versión de nombres de propiedades largas.

Para que el servidor nos envie la información comprimida en gzip es mucho más fácil, puesto que lo hace de manera automática siempre y cuando en las peticiones le digamos que nuestro cliente acepta compresión gzip. Nosotros lo hemos hecho de este modo:

HttpPost httppost = connectPOST(url);
   httppost.setHeader("Accept-Encoding", "gzip");
   httppost.setHeader("Content-Encoding", "GZIP");
   httppost.setHeader("User-Agent", "gzip");

Hay que tener muy presente que el gzip automático por parte de GAE no funciona en local.

Si tenéis alguna duda o sugerencia no dudéis en comentarla.

Eficiencia en Google App Engine: Appstats

Nuestra elección a la hora de subir datos a la nube fue Google App Engine, el servicio que permite ejecutar aplicaciones web en la infraestructura de Google. El desarrollo  en esta plataforma presenta ciertas características que obligan a cambiar el chip desde un primer momento y que nos fuerzan implícitamente a tener en cuenta la eficiencia y, sobretodo, la escalabilidad. Dicho esto, siempre hay momentos a lo largo del camino en los que uno se plantea revisar la eficiencia global de la aplicación para mejorar su tiempo de respuesta, reducir los consumos de cpu y, de paso, reducir la factura cobrada por Google.

La primera vez que nos enfrentamos a esta situación decidimos usar cProfile y pstats para estudiar los tiempos de nuestro código Python centrándonos en aspectos clásicos como optimización de búsquedas, mejora de la eficiencia en la manera de concatenar cadenas, reducción del número de iteraciones en un bucle…la verdad es que de poco nos sirvió, ya que, veíamos que la mayor parte del tiempo de proceso se gastaba en algo que en el profile se indicaba con líneas como esta:

_apphosting_runtime___python__apiproxy.Wait

Es decir, que la mayor parte del tiempo nuestra aplicación estaba esperando a que se completase el proceso realizado por una llamada a alguna API de Google.

Estudiando en detalle el lugar del código en el que aparecen estas líneas, se puede averiguar a qué API se están refiriendo pero, por suerte, todo ese trabajo dejó de ser necesario gracias al descubrimiento de Appstats:

Appstats es una herramienta creada por  Guido van Rossum (creador de Python y actual empleado de Google) que forma parte del SDK y nos permite ver en detalle en qué emplea realmente el tiempo nuestra aplicación mediante el estudio de las RPC, es decir, las llamadas remotas que nuestra aplicación hace a las distintas API’s de Google. Su instalación es muy sencilla y podemos instalarla incluso en producción porque consume muy pocos recursos.

En  el siguiente video, el propio Guido, nos explica las bondades de esta herramienta indispensable:

En el video se muestra cómo instalar y usar la herramienta, una breve explicación de su funcionamiento y consumo, posibilidades de configuración y algunos ejemplos de uso como, por ejemplo, detección de ciertos patrones de ineficiencia comunes a muchas aplicaciones : Patterns of Doom!

Servidor de desarrollo

Servidor de desarrollo

Os presento a nuestro servidor de desarrollo: DarwinFrog.

Debido a nuestra pasión por la integración continua, las revisiones de código, las herramientas de calidad y los tests automáticos; el pobre servidor está pluriempleado.

A modo de recuento las herramientas que habitan nuestro servidor y nos ayudan en nuestras tareas diarias son:

  • Hudson servidor de integración continua, lleno de plugins para adaptarse al desarrollo en Android y Gae.
  • Subversion en estos momentos nuestro sistema de control de versiones, estamos pensando migrar a algo más moderno como Git o Mercurial, pero no encontramos el momento adecuado.
  • Sonar plataforma de control de calidad del código, muy completa y visual.
  • Review Board herramienta de revisión de código muy útil y fácilmente enlazable con Subversion y otros sistemas de control de versiones.
  • Nexus gestor de repositorios muy útil para almacenar artefactos propios generados por Maven y así no tener que preocuparse de las versiones de las librerías, ni de las dependencias.
  • Seleniumhq plataforma para realizar tests funcionales web, versátil y fácilmente integrable con Hudson. Permite grabar los test de forma muy sencilla desde firefox entre otros.

En próximos posts intentaremos entrar en más detalle y contaros más a fondo como utilizamos y para que cada una de las herramientas.

¡Hola Mundo!

¿Quién nos iba a decir cuando hace menos de un año nos apuntamos a esta aventura que es Frogtek la cantidad de cosas interesantes que íbamos a aprender en tan poco tiempo?. Nadie fue capaz de prevenirnos sobre cuánto iba a cambiar nuestra forma de trabajar y lo enriquecedor que iba a ser el principio del camino a recorrer (porque esto no ha hecho más que empezar). Era toda una apuesta. Salir, en alguno de los casos, de debajo del ala de grandes empresas tan rígidas, como cómodas para montar una empresa pequeña entre todos, desde cero, sin corsés, sin ideas predefinidas… y sin red. Y en ello estamos.

En menos de un año y liderados por un CEO, David, de energía inagotable, e inversamente proporcional a su aversión al cambio (que es nula), hemos construido un grandísimo equipo técnico, flexible, motivado, con ganas de aprender y de enseñar. Se comenzó trabajando los fines de semana, dando forma a un prototipo cuya especificación estaba siempre obsoleta (waterfall,  :$  sí, todo el mundo tiene un pasado oscuro que esconder). Seguimos con un rudimentario SCRUM mucho más apropiado para lidiar con un producto final que desconocíamos a priori (las start-ups ya se sabe… siempre buscando) y unos clientes, los pequeños comerciantes en países emergentes (¡ahí es nada!) tan remotos, como desconocidos. Por aquel entonces, verano del 2009, llegó el momento de la decisión, de tirarse a la piscina, mudarse a una oficina y dedicarse al 100% a Frogtek. La oficina y una empresa de verdad trajo también un SCRUM más “de verdad”, herramientas como el AgileBuddy y nuevos compañeros de viaje. Más adelante nuestra escasa fortuna estimando, reuniones de planificación interminables y la naturaleza demasiado informal de nuestros clientes finales (no es posible tener al tendero medio latinoamericano una vez cada dos semanas en el sprint review) hizo que nos pasáramos al ScrumBan y decoráramos nuestra ya de por sí bonita oficina con una más preciosa aún tabla de Kanban y post-its de todos los colores que hacen las delicias de nuestro programador daltónico, responsable a su vez de nuestros primeros pinitos con el TDD (¡gracias a Carlos Blé!). Buscamos entonces un Tester y encontramos un Responsable de QA y él (junto con el resto) nos ha dado Integración Continua, Test Automáticos, métricas…

En marzo de 2010 empezábamos a tener un departamento de Tecnología en condiciones con un proceso cogido con alfileres pero que apuntaba maneras. Y llegó el momento de conocernos con el resto de la empresa. Aparte de nosotros, había una persona en Nueva York, dos en Bogotá y otra en México DF… y daba la casualidad de que aunque hablábamos diariamente vía skype, ninguno los doce había visto en persona al resto de los “Frogtekeros”. Nos juntamos todos en Huesca la última semana de marzo y durante esos días pasó algo curioso. Les pedimos a los desarrolladores que hicieran una presentación para mostrar cómo era su día a día y en lugar de Power Point van y nos salen con esto…

… supongo que es el tipo de cosas que hace un equipo cuando tiene libertad y está motivado. El vídeo fue un éxito de crítica y público y un poco la semilla para crear este blog. Semilla que germinó en idea tras la sobredosis de entusiasmo y agilismo (menudo palabro) que tres de nosotros tuvimos la suerte de recibir en la CAS 2010. Escuchar a los gurús de las metodologías ágiles y conocer las historias de éxito y de fracaso de distintas empresas nos hizo pensar que también nosotros teníamos algo que contar: nuestra humilde historia, las pequeñas grandes cosas que hemos aprendido y las incontables que nos quedan por aprender.

Este blog surge como nuestro primer “FrogtekLabs”, en él vamos a hablar de nuestro trabajo, de nuestra evolución, de nuestros cambios en definitiva, porque no hacemos más que cambiar. De métodos ágiles, de palabros en japonés, de Android, de Google App Engine, de cualquier cosa que nos interese… Somos ocho, así que no esperes consistencia, espera estilos muy distintos, distintas frecuencias, posts de gestión, de programación pura y dura, de TDD, sobre cómo usar SONAR o configurar Eclipse. Ni siquiera esperes que no nos llevemos la contraria alguna vez. Espera también errores y ayúdanos a corregirlos.

Nos declaramos fans de Ángel Medinilla (¡tenemos su autógrafo!) y de Rodrigo Corral. Somos maqueros y linuxeros y alguno hay que aún echa de menos Windows. No estamos en Silicon Valley, sino entre Huesca y Zaragoza, pero no renunciamos a trabajar como Google. Y por encima de todas las cosas… queremos pasarlo bien. ¡Que empiece la fiesta!.