LinkedIn ha puesto en línea sus presentaciones realizadas durante la pasada JavaOne 2008: LinkedIn - A Professional Social Network Built with Java™ Technologies and Agile Practices y LinkedIn Communication Architecture. En estas presentaciones, la gente de la empresa detallan la evolución de su aplicación web hecha en JEE a lo largo del tiempo para poder soportar un creciente número de usuarios. Oren Hurvitz en su blog, da un resumen bastante completo e interesante de estas presentaciones:
Estadísticas del sitio:
- 22 millones de usuarios registrados
- 4+ millones de visitantes únicos por mes
- 40 millones de page/views al día
- 2 millones de búsquedas al día
- 250K invitaciones envíadas por día
- 1 millón de respuestas publicadas al día
- 2 millones de mensajes enviados por correo al día
El software que usan:
- Solaris (sobre plataformas Sun x86 y Sparc)
- Tomcat y Jetty como servidores de aplicación
- Oracle y MySQL como bases de datos
- Ningún ORM (como Hibernate), usan JDBC de forma directa.
- ActiveMQ para JMS. (Particionado por tipo de mensajes y respaldado en MySQL).
- Lucene para búsquedas
- Spring como pegamento
- Muchas otras librerías Java como DWR para Ajax, Quartz para calendarizar y orquestar procesos, Grails y Spring MVC para la capa Web.
- Eclipse como IDE
Utilizan una metodología TTD (Test Driven Development), por lo que su aplicación cuenta ahora con más de 6500 units e integration tests y alrededor de 500 HtmlUnit tests. Además de esto, usan
Hudson como servidor de integración continua.
Como podrán observar en el resumen de Oren, el sitio ha evolucionado de acorde a las necesidades y la arquitectura del mismo ha cambiado bastante desde que comenzaron. Los desarrollodres de LinkedIn destacan las siguientes épocas de su aplicación:
2003-2005: Usan una sola aplicación web monolítica y una sola base de datos central. El grafo de la red social de LinkedIn se almacena en memoria en la nube. Lucene es usado para las búsquedas y corre en el mismo servidor que la nube. La aplicacón web actuailza directamente la BD y ésta a su vez actualiza la nube.
2006: Se agregan BD réplicas de sólo lectura, gestionadas por una aplicación servidor. La aplicación de búsqueda se cambia a un servidor propio. Se añade el Databus, un middleware encargado de actuailzar la nube, la aplicación de búsqueda y las BD réplicas.
2008: La aplicación web ya no realiza nada de lógica de negocio. Esta lógica se mueve a componentes externos llamados Servicios que son llamados desde la aplicación web, de esta forma esta aplicación se convierte en nada más que un GUI. Cada servicio tiene su propia BD con los datos de su dominio. Con esta arquitectura SOA, fue posible construir otras aplicaciones además del sitio web para acceder a LinkedIn, por ejemplo , aplicaciones especiales para recruiters y anunciantes.
Por otro lado, la nube de LinkedIn es la responsable de almacenar en memoria toda la red social existente. Sobre ella han dado los siguientes datos:
- Tamaño de la red: 22 millones de nodos, 120 millones de aristas (edges es aristas?)
- Requiere 12GB de RAM
- Existen 40 instancias en producción
- Reconstruir una instancia toma 8 horas
- Se actualiza en tiempo real usando el Databus
- Persiste a disco cuando es apagada
- El cache está implementado en C++ y se usa JNI para accederlo desde Java. Han elegido C++ para usar tan poca RAM como sea posible y porque las pausas del Garbage Collector si usaban Java eran mortales.
La nube almacena toda la red de LinkedIn, sin embargo cada usuario debe ver la red desde su punto de vista. Como computacionalmente es costoso calcular eso, lo hacen una sola vez cuando el usuario inicia sesión y lo almacenan en cache. Esto toma 2 mb por usuario y esta cache no se actualiza mientras exista la sesión a menos que el usuario agregue o quite un contacto.
Además usan ehcache para almacenar los perfiles de los usuarios, de 22 Millones, tienen 2 millones actualmente en este cache. Mencionan que al principio usaban el algoritmo LFU (Least Frequent Used que cuenta el uso de los elementos y descarta los menos usados) pero ehcache se bloqueaba 30 segundos cada que tenía que recalcularlo así que han cambiado a usar LRU (Least Recently Used que descarta los usados hace más tiempo).
Sobre su arquitectura de comunicaciones: está implementada sobre JMS asíncrono. Las notificaciones se entregan tanto a través de Pull como de Push. Usan Spring con extensiones propietarias para esto.
Sobre cómo escalaron esta arquitectur, lo han hecho básicamente particionando:
- Particionamiento funcional: enviados, recibidos, archivados, etc
- Particionamiento por clase: buzones de correo de los usuarios, de los invitados, de empresas.
- Particionamiento por rango: id de usuario, rango lexicográfico del email.
- Todo es asíncrono
Por último, los desarrolladores nos dan algunos tips para escalar aplicaciones;
- No puedes usar solamente una base de datos. Usa muchas, particiónalas horizontal y verticalmente.
- Debido al particionamiento, olvídate de integridad referencial y de Joins entre diferentes dominios.
- Olvídate de tener una integridad de datos del 100%.
- Una vez que has crecido, spammers y data-scrapers te visitarán.
- ¡Cache!
- Usa flujos asíncronos.
- Los informes y los análisis son un reto: tenlos en cuenta desde que estás diseñando el sistema.
- Espera que el sistema falle.
- No sobrestimes tu crecimiento.
Bastante interesante este caso práctico sobre una aplicación real que ha tenido que crecer al ritmo en que sus usuarios lo hacen. Como ya se ha dicho anteriormente en este sitio, JEE parece no ser tomanda en cuenta a la hora de construir este tipo de aplicaciones, sin embargo LinkedIn es un caso donde han elegido Java y han probado que funciona a este nivel. Otro caso que me viene a la mente es el de Hi5 que tienen el clúster de Tomcats más grande del que he oído.