viernes, 24 de abril de 2009

Escalabilidad en cuanto a capacidad de poner en producción nuevas funcionalidades

Me ha resultado muy interesante este artículo del blog de uno de los fundadores de FriendFeed (y que anteriormente fue un mando intermedio en Google): http://bret.appspot.com/entry/how-friendfeed-uses-mysql

Con una base de datos con decenas o cientos de millones de entradas, se encontraron un problema de escalabilidad entre otras cosas en la adición de nuevas funcionalidades, en concreto en el tiempo que cuesta añadir o quitar columnas a tablas, o añadir índices o eliminarlos. Estamos hablando de una o varias horas de "no disponibilidad de la BD" en un sistema supuestamente 24x7 :-)

Así que la solución (no sólo para ese problema, sino también por estabilidad en los tiempos de respuesta, cosa que no termino de enteder por cierto) fue la que se describe en la mencionada entrada. Resumidamente, usar MySQL como motor de almacenamiento pero pasar como de la mierda de un modelo relacional...

Enriquecedora lectura, aunque no me aplique... (que yo sepa ;-)

miércoles, 15 de abril de 2009

Java 6u13

Desde hace 3 semanas, está disponible el update 13 de Java 6. Descargas aquí: http://java.sun.com/javase/6/

Recordemos que a partir del update 10, la política de versiones de Java SE es:
  • Las versiones pares incluyen mejoras y/o nuevas funcionalidades (además de parches de seguridad si aplican).
  • Mientras que las versiones impares están reservadas para contener exclusivamente (salvo excepciones).

En este caso, como puede verse en http://java.sun.com/javase/6/webnotes/6u13.html, se han corregido 7 vulnerabilidades y se ha aprovechado para corregir otros 7 bugs no relacionados directamente con la seguridad pero que se han considerado prioritarios.

Seguimos esperando ansiosos la inminente liberación del update 14 (Java 6u16), que supondrá un hito importante en cuanto a rendimiento (es decir incluirá todo lo experimentado en las performance releases del año pasado y más cosas :-)

Y... La 6u14 ya va por la build b04, lo que significa que estamos muy cerquita aunque este update yo creo que necesitará algunos más de lo habitual, seguramente será a mediados o finales en mayo cuando se libere, como llevamos tiempo precidiendo desde este blog. Más información y descargas de los snapshots: http://download.java.net/jdk6/6u14/

miércoles, 8 de abril de 2009

Incremento de un 100% de rendimiento de java.util.Logger (o los detalles sí importan)

Delicioso post de Jeremy Manson, que lleva tiempo teniéndnos "abandonaditos"...:

http://jeremymanson.blogspot.com/2009/04/faster-logging-with-faster-logger.html

A raíz de la necesidad de un cliente, que quería nada menos que un throughput de 2 MB por segundo en la escritura de logs (!), se han hemos una serie de optimizaciones en Logger.log para alcanzarlo, y se ha alcanzado...

Los cambios ya están disponibles en el último build de OpenJDK, y más detalles en http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6797480.

El código de Jeremy es precioso en si mismo (lo siento, seguramente un no-programador no puede entender el adjetivo precioso aplicado a esto). Toda una clase de sincronización y volatilidad. Y es el mejor ejemplo de que el mejor "Escape analysis" sigue haciéndolo el ingeniero...

Pero, y por mucho que él le quite culpas al desarrollador original de esa clase (incorporada en JDK 1.4)... joder ¿eso siempre ha estado ahí? ¿los procesos de entrega de Sun Microsystems no incluyen búsqueda de puntos calientes o locks adquiridos en cada thread?

Lo cierto es que me ha dejado un sabor de boca muy muy agridulce...

jueves, 2 de abril de 2009

Deja de hibernar y despierta de una vez!

Me hago eco de este artículo: "Good Advice on Keeping Your Database Simple and Fast".

Independientemente de si nos parece bien, mal o regular todo lo demás, de si creemos en SimpleDB y S3 o no... e independientemente de si todo este rollo del Cloud mola pero no te aplica porque tus problemas son otros, tú trabajas en un sistema de información interno...

...El primer párrafo del artículo es para enmarcarlo, y traduzco literalmente:
Mantener una base de datos simple y rápida es muchas veces complicado si se usan frameworks de alto nivel como (...) o tecnologías de persistencia de objetos en Java como HIBERNATE. Hay una gran cantidad de "magia" que ocurre fuera de tu vista sobre la que no tienes ningún control. Si tienes que escalar tu aplicación, generalmente son estas tecnologías para acceder a bases de datos relacionales las que se convierten en el cuello de botella tanto de rendimiento como de escalabilidad. (...)

¡Algo sensato! ¡Por fin! Por favor que vuelvan los tiempos del JDBC crudo (dentro o fuera de un EJB). Y no necesariamente implica perder el tiempo en codificar como un mulo.

Ya en el año 2001 en mi anterior empresa ideé y lideré un sistema que llamamos "BeanBuilder" para generar todo tipo de código a partir del esquema de base de datos. Y no sólo me refiero a los EJB con altas/bajas/modificaciones/consultas/filtros/paginación, sino incluso llegamos a generar operativas completas con sus JSP de listado y de formularios de alta en base a plantillas. Para que sirvan como base para modificarlos, ampliarlos, etc. Pero siempre con control sobre el código generado porque generábamos código Java.

Y allá por 2004 el sistema era realmente complejo, admitíamos tomar como punto de partida joins entre varias tablas y generar lo apropiado... Teníamos un formulario en el que elegías el tipo de framework que debía utilizar el código generado (¿EJB o framework propio con POJO? ¿JSP o XSLT? ¿Struts o nuestro framework propio?). Vamos, una herramienta para cualquier proyecto que abordáramos...

Es decir si el objetivo es ahorrar esas horas de desarrollo "que no aportan valor" pero mantener el control sobre lo que potencialmente te va a dar problemas.

No preguntéis el motivo, pero quedó en vía muerta. Si volviera a quella época hubiera lanzado un proyecto Open Source en toda regla...

¡Es hora de despertar de la "hibernación" en que estos arquitectos de salón nos han metido!

miércoles, 25 de marzo de 2009

Un medio, no un fin

Sin que sirva de precedente tiene poco que ver con el tema de este blog (o mucho si se piensa bien).

Me ha llamado la atención el primer párrafo de un artículo sobre ENS (es de 2003, no digo que el estudio en si mismo sea interesante):

"Ejecutivos y gerentes se esfuerzan por satisfacer las necesidades de los clientes y de los accionistas de manera simultánea"
(http://files.epsscentral.info/gery/pdfarticles/Enterprise%20Nervous%20System.pdf)
Ahí está la madre del cordero. El arte de gestionarlo. Como me dijo un sabio (Zape) una vez: no te olvides de quién te paga el sueldo. O lo que es lo mismo, no olvidemos que las cosas las hacemos por un objetivo.

Aunque para obtener ese objetivo como precio a pagar haya que satisfacer al cliente. Esta frase es de otro sabio, Zipi ;-)

La tecnología al servicio del negocio. No al revés. Pero qué fácil es olvidarlo cuando no estás en primera línea...

¡Qué gran pareja estos Zipi y Zape! Lástima que siguieran sus carreras musicales por separado...

Y aplicado a la temática de este blog: el rendimiento y escalabilidad es un medio, no un fin.

:-/

viernes, 20 de marzo de 2009

SaaS, IaaS y PaaS: Las tres clases de Cloud Computing

Lo único que está claro es que Cloud Computing es un palabro guay para poner en las PPT. Es como lo de la Web 2.0 o SOA, que nadie sabe lo que es pero todo el mundo habla de ella. Y en una reunión nadie pregunta qué es por miedo al ridículo.

Esta es la única catalogación clara que hay por ahí en castellano, en Nubeblog:

http://www.nubeblog.com/2008/10/15/saas-iaas-y-paas-las-tres-clases-de-cloud-computing/
Claro y conciso. De verdad.

Yo tengo mi propia opinión y creo que hay modelos mixtos y valores añadidos muy diferenciados de un SaaS a otro, como para meterlos en el mismo saco. Pero para gustos los colores: del mismo modo que hay quien asegura que AJAX/RIA no es Web 2.0, hay quien asegura que SaaS no es Cloud, cuando para mi en realidad es el nivel más completo de CC: te doy un software y te lo evoluciono, en una infraestructura remota de la yo gestiono su crecimiento, gestión del centro de respaldo, procedimientos de paso a contingencia, help desk 24x7, y todos los servicios asociados... eso sí que es una nube :-)

Otra cosa es que un SaaS pueda apoyarse (o no) en un IaaS y/o en un PaaS. Pero al cliente final se la debería traer floja...

viernes, 13 de marzo de 2009

Compressed pointers. Compressed oops.

Una de mis optimizaciones favoritas que aparecerán en la update 14 de Java 6 (actualmente en build 1, como os indiqué en un artículo anterior), y que ya estaba disponible en las "performance releases" es la compresión de punteros en la máquina virtual de 64 bits.

En Sun le llaman "compressed oops".

El concepto es sencillo, y en realidad desde hace muuuuuucho lo tiene implementado JRockit, si los objetos mapeados es inferior de 4.000 millones de objetos (unos 32 gigas de RAM), se activa esta optimización, que reduciéndolo mucho puede explicarse de la siguiente manera: no es necesario que los punteros sean de 64 bits, pueden ser de de 32 bits, y hacer la resta con el punto de inicio de la memoria del S.O. utilizada. Esto es una reducción, en realidad es más complejo claro... Según el enlace que pongo abajo, literalmente: "Compressed oops represent managed pointers (in many but not all places in the JVM) as 32-bit values which must be scaled by a factor of 8 and added to a 64-bit base address to find the object they refer to. This allows applications to address up to four billion objects (not bytes), or a heap size of up to about 32Gb. At the same time, data structure compactness is competitive with ILP32 mode."

Esto puede consiguir una mejora general del rendimiento de aproximadamente un 3%: Por un lado se consigue que todas las estructuras internas ocupen menos memoria (los punteros ocupan la mitad, y en algunos informes se habla de un consumo de hasta 1,5 veces mayor porque aquí hay mucho puntero aunque lo primero que nos dicen cuando aprendemos Java es que aquí no hay ni un solo puntero) y por otro lado se incrementa la capacidad de las cachés del servidor y of course por los buses puede trasitar el doble de información (en lo que a punteros se refiere) en el mismo tiempo.

Obivamente el mapeo siempre hay que hacerlo y supone una penalización, pero la ganancia por el otro lado lo compensa con creces. Es decir, la máquina virtual de 64 bits será "casi" tan competitiva como la de 32 bits, no llegará a ser lo mismo pero la diferencia será inapreciable...

Aunque algunos piensan que esta optimización sólo funciona si el heap máximo es inferior o igual a 4 GBytes (por aquello de los 32 bits), no es cierto. Como digo arriba son 2^32 objetos referenciados por los punteros. Claro, si cada punterio apuntara a una estructura de 1 byte, esto sería 2 gigas, pero según las medias estadísticas de tamaño de objetos en heap, en la práctica supone aproximadamente 32 gigas efectivos teniendo en cuenta que esta optimización sólo afecta al código compilado no al interpretado, y en función del caso de uso esto es mucho mayor... vamos que la optimización afecta al 99% de los sistemas del mundo mundial.

¿Te suena la frase de que las máquinas virtuales de 64 bits son más lentas o que consumen más memoria? Bien, pues ya no será una afirmación válida...

Más información sobre compresión de punteros, el primer enlace es el clarificador:

viernes, 6 de marzo de 2009

Los finalizers no son tus amigos (parte II)

Juro por la gloria de que James Gosling que ha sido casualidad... Al hilo de lo que comentábamos el lunes... [Viene del artículo anterior: Los finalizers no son tus amigos]

Estoy suscrito a algunas listas de correo del desarrollo de JDK 7 y precisamente ayer jueves se recibía una notificación de un nuevo changeset que optimiza la gestión de PKCS#11 en el proveedor criptográfico del JDK, gracias a eliminar el método finalize() y cambiar su implementación por una weak reference. ¿Os suena???

El webrev completo puede verse en: http://hg.openjdk.java.net/jdk7/tl/jdk/rev/da9d0283a496

La descripción es:
Issue: SSL stress test with GF leads to 32 bit max process size in less than 5 minutes with PCKS11 provider.
Summary: Removed finalize() and add more error handling to native code.

Author: valerie
Reviewed-by: vinnie

lunes, 2 de marzo de 2009

Los finalizers no son tus amigos

Gracias al artículo de este mes de javaspecialists.eu (http://www.javaspecialists.eu/archive/Issue170.html), he redescubierto que hay que evitar la implementación del método finalize() siempre que sea posible.

¿Por qué? Porque se añaden handlers a todas y cada una de las intancias de una clase que tenga ese método implementado. ¿Y qué? pues por un lado se añade más footprint de memoria a cada objeto, pero lo más importante: porque un objeto con finalizador es más costoso de alojar, y más costoso de eliminar: la VM añade un hook al objeto que causa que la instancia "sobreviva" a muchos de los pasos de la recolección de basura en lugar de ser retirado rápidamente, por lo que se promociona de forma prematura (y posiblemente innecesaria) dicha instancia a la zona de "old generation". Y esto a su vez hace que el old generation GC tenga más trabajo y se haga más lento y consuma más CPU. Según se apunta por ahí, esta situación puede mejorarse tuneando los ratios de tamaños, pero aún así el coste es importante.

Pero... -te estarás diciendo- si yo necesito un finalizador para cerrar un stream!!! (o cualquier otro recurso). Bueno, puede que sí, puede que no. Revísalo ¿seguro? ¿o lo haces por comodidad? ¿o porque no te fías de que la VM haga lo que tiene que hacer? ¿o porque quieres ayudar al GC (y la cagas, como siempre)? :-)

Si sigues estando seguro de que lo necesitas, dos comentarios:
  1. Ok, pues no pasa nada. No he dicho que no uses finalizadores, sólo que los uses cuando sea absolutamente necesario. Ten en cuenta que este tip es de un nivel muy "fino". Si ese objeto no afecta al rendimiento global por no ser uno de los más utilizados ni entrar en hotspots, pues no te preocupes, recuerda la regla del 90-10.
  2. Si necesitas tunear un caso concreto, y no has visto la forma de simpliciarlo reordenando otras partes del código, siempre puede reemplazarse un método finalize por un establecimiento de una referencia débil (weak) al objeto, y llamando explícitamente aun método equivalente que libera recursos cuando dicha referencia se establece a null.
Nota: esto es así siempre que el finalizador sea "no trivial" (entendiendo por trivial = vacío en tiempo de ejecución) es decir que si dejamos el método en nuestra clase pero su cuerpo está vacío, o si el optimizador del Hotspot mediante inlining lo vacía ("if (false) {...}"), lo dicho anteriormente no se considera: sólo se añaden hooks a objetos con finalizadores no triviales.

Más información:

Ahora repite conmigo:
Los finalizers no son mis amigos.... Finalizer malo, finalizer malo...

[Continúa en el siguiente post: Los finalizers no son tus amigos (parte II)]

martes, 24 de febrero de 2009

Java 6u12 (production) y Java6u14 (early access)

Pues como anuncié en el post Schedule de siguientes updates de Java 6. Versiones de Hotspot y compatibilidad entre ellas, Sun se está ciñendo al calendario que me pasó mi contacto del equipo de Hotspot:

Ya está disponible Java 6 update 12 para descarga general y soporte para su uso en producción (http://java.sun.com/javase/downloads/index.jsp):
  • Las mejoras de rendimiento parecen únicamente ceñidas (una vez más!) al entorno cliente y gráfico.
  • No contiene corrección de ninguna vulnerabilidad de seguridad
  • La lista de bugs corregidos es importante, aunque los relativos a hotspot y a las bibliotecas core es muy reducida.
  • Soporte a Windows 2008 Server
  • [pero no incorpora Hotspot 12 sino que se mantiene Hotspot 11, supongo que han dejado en vía muerta las versiones 12 y 13]
Asimismo, lo que confirma a mi juicio la fecha estimada de mayo, podemos ya descargar Java 6 update 14 "Early Access" desde https://jdk6.dev.java.net/6uNea.html y http://download.java.net/jdk6/6u14/.
  • Esta versión incorpora la esperada V14 de Hotspot (que ya traía la fracasada versión 6u6p)
  • Y el anunciadísimo colector de basura Garbage-First (G1), que será el futuro recolector por defecto en entornos servidor aunque en este early access no está habilitado por defecto (ver instrucciones para hacerlo).
  • Todavía es el build 01, así que viendo la media de builds por versión, aún quedan tres :-)
Lo dicho, yo me espero a verano y migraré directamente de la u11 a la u14... lo cual no quita para que este comienzo de año sea emocionante desde el punto de vista de mejoras de rendimiento en Java, las cuales afortumadamente están aplicando a Java 6 y no sólo a la versión-que-algún-día-dejará-de-ser-beta Java 7.

P.D: Los últimos builds del JDK 1.7 ya incorporan el Hotspot 15...

:-)

martes, 10 de febrero de 2009

Good bye Mr. Monson-Haefel

Hace tiempo que soy fan de Richard Monson-Haefel, que es el padre de muchas cosas, gurú de los EJB y del JMS y autor de varios libros de O'Reilly, de esos de tener en la cabecera de la cama.

Creo que desde el año 2000 sigo sus artículos en JGuru, en The Server Side, en Java.net..., he vivido sus aportaciones en revisiones de las especificaciones de EJB y en procesos JSR/JCP, y su participación en Geronimo, OpenEJB y finalmente Groovy...

En realidad viví de lejos su incursión en el mundo de plataformas RIA desde 2004 (me anclo en el pasado, hace ya 4 añitos que oficialmente dejó el mundo Java EE, aunque a seguido dando guerrilla desde entonces...), y ahora -aunque se veía venir- se ha pasado del todo al lado oscuro :-)

Ha decidido reenfocar su carrera profesional desde finales de 2008 hacia el muldo Multitouch, digo que se ha pasado al otro lado porque es un gran fan de Microsft Surfaces :-)

Valiente decisión para alguien que tenía a huevo aceptar uno de los múltiples y comodones puestos ejecutivos en grandes consultoras que le habían ofrecido, o dedicarse a ser conferenciante...

Gracias por todo, Clever monkey. Seguiremos tus evoluciones en ese giro de 180 grados que has dado... así que este post es un pequeño y muy humilde homenaje, por mucho que no me hayas aceptado todavía como amigo en el Facebook ;-)

Su blog, ahora reenfocado a la multitouch: http://theclevermonkey.blogspot.com/

viernes, 30 de enero de 2009

Balanceo de cargas de EJB en un clúster Java EE. "Collocation Optimization" y cómo afecta al diseño de procesamiento BATCH de alto rendimiento



Me gusta Java EE. Y me gustan los EJB. Siempre en su justa medida, me explico y no me fustiguéis los amantes de Spring Framework, que seguramente llevo más tiempo que vosotros en esto y las viejas costumbres son imposibles de cambiar...

To EJB or not to EJB

El concepto de componente empresarial (EJB) no es algo por lo que rasgarse las vestiduras, siempre que estemos hablando de Stateless Session Beans o Message-Driven Beans y no de Stateful Session Beans, o peor aún, de los infames Entity Beans (por muchas vueltas que le hubieran dado en la especificación 3.0 y lo que queda por dante con la 3.1 que se liberará este año...).

Lo de los Entity Beans es lo de siempre, mapeo O/R y por mucho que haya otras aproximaciones más potentes como Hibernate y similares, a mi lo que me gusta es tener el control. JDBC y SQL, tío. Que trabajar con SQL también es programar, y te aseguro que vas a tener menos problemas, la "magia" se termina pagando, en un proyecto es más el tiempo que se pierde en depurar las cosas raras de los mapeos O/R o conseguir optimizar una consulta o que haga un puto join de 8 tablas en lugar de 300 consultas a base de datos.

Pero me estoy yendo del asunto principal. Sigamos...

La historia de Java EE no empieza en J2EE sino en JPE, allá por 1998 (sorpresa, su primer nombre no fue J2EE). Y antes de eso, en 1997 salió la especificación EJB 1.0 y Servlet 1.0 allá porfinales de 1997:


Sí hay que agradecerle a Spring que haya conseguido poner las pilas a los chicos del JCP, ya que la especificación 3.0 importó algunos de los conceptos de Spring Framework, en concreto lo que respecta al uso de Anotaciones para eliminar los deployment descriptors y simplificar el carajal de desarrollar y mantener un componente, que los servidores de aplicaciones inyecten código en tiempo de despliegue/ejecución. También, desde algo antes, la 2.1, se permite definir interfaz local además de (o en lugar de) la remota, por lo que en tiempo de ejecución cada vez el tema es también más ligero, amén de que los fabricantes de servidores de aplicaciones compatibles cada vez hacen las cosas un poquito mejor...

No quiero hacer un alegato a favor de Java EE o en contra de Spring. Basta con decir que Spring, igual que Struts o Hibernate son lo que son, y estamos en manos de un sólo proveedor (o una sola comunidad pero visto lo visto con JBoss o con el propio Spring, tarde o temprano la gente quiere llevar las judías a casa, lógico). Y Java EE es una especificación con múltiples implementaciones, y no está en manos de lo que a Sun le apetezca hacer con sus cosas, sino que son "estándares" (JSRs) del Java Community Process (JCP), que por mucho que esté liderado por Sun (faltaría plus) no es lo mismo, amigo...
Por cierto, aparte de todo el miedo que ha habido en 2008 con el cambio de política de licencia y releases de Spring (ver artículo de Cmaj), también he oído voces que las nuevas versiones del susodicho cada vez son más complejas y pesadas. Oh, oh, ¿no era la comlejidad de Java EE y la simplicidad que deberían mantener las aplicaciones empresariales lo que hizo a Rod Johnson tirarse a crearlo allá por 2002?

Qué aporta el Contenedor de EJB

El concepto de EJB está ya maduro, pues, y el servidor de aplicaciones / contenedor de EJB provee dos servicios/características fundamentales que los hace muy atractivos:
  • Demarcación transaccional. Pudiendo definir el comportamiento transaccional de cada método de negocio de forma declarativa mediante anotaciones. Vamos, para los de antes, el contenedor de EJBs actúa como MONITOR TRANSACCIONAL.
  • Distribución. La interfaz remota de un EJB es un punto de potencial separación en múltiples instancias o servidores de aplicaciones. Es decir, además de otros mecanismos en la capa de Contenedor HTTP / Motor de servlets, ahí tenemos un punto de potencial balanceo de cargas y failover.

En realidad es lo único que me gusta del modelo. Pero no es poco.

Como decía, como todo, las cosas con mesura. Las dos penúltimas arquitecturas que diseñe para clientes se basaban en un único EJB fachada de toda la lógica distribuida en POJOs normales (o unos pocos EJB, para no mentir). Granularidad muy gruesa, amigo. Me gustan las ventajas pero la sobrecarga excesiva.


Balanceo de cargas y optimizaciones que dificultan las cosas

Pero hay una trampa, siempre hay truco. El balanceo de cargas / failover que nos proporciona un clúster de servidores de aplicaciones a nivel de EJB no es tan automático como parece, sino que puede llevar alguna sorpresa.

Y esto es debido a que está clarito-clarito que la arquitectura Java EE está pensado en el mundo online, orientado a peticiones remotas (de un navegador o de una aplicación remota) que requieren un procesamiento extrarápido y extraescalable. Lo cual hace que por defecto los servidores de aplicaciones se pasen por el forro de los cojones la distribución de cargas entre invocaciones de EJB. Es decir, si ya hemos balanceado en la capa http / servlet, ¿para qué volver a perder el tiempo en balancear la ejecución de cada componente involucrado en esa operativa si se da la premisa de que la sobrecarga de cada invocación remota (calcular_round-robin->serializar->enviar_por_la_red->deserializar->ejecutar->serializar->respuesta_por_la_red->deserializar) seguramente es más costosa que los milisegundos de ejecución de ese método de negocio?

Pues mejor no hacerlo. Y así es cómo actúan casi todos los servidores de aplicaciones cuando están en Clúster. al menos Weblogic, Glassfish y Websphere. E infiero que también el resto: si se invoca a un EJB desde dentro de un servidor de aplicaciones que está en clúster, el servidor de aplicaciones SIEMPRE invocará una instancia local del componente (que está desplegado en esa isntancia) y nunca a una de otro nodo del clúster. Es lo que se llama "optimización por colocación" que no es exactamente lo mismo que "afinidad de servidor".

A modo de ejemplo, pego un extracto de la documentación de Weblogic 10, que tiene su toque de ironía por cierto:

http://download.oracle.com/docs/cd/E11035_01/wls100/cluster/load_balancing.html

WebLogic Server always uses the local, collocated copy of Object A, rather than distributing the client’s calls to other replicas of Object A in the cluster. It is more efficient to use the local copy, because doing so avoids the network overhead of establishing peer connections to other servers in the cluster.

This optimization is often overlooked when planning WebLogic Server clusters. The collocation optimization is also frequently confusing for administrators or developers who expect or require load balancing on each method call. If your Web application is deployed to a single cluster, the collocation optimization overrides any load balancing logic inherent in the replica-aware stub.

If you require load balancing on each method call to a clustered object, see Recommended Multi-Tier Architecture for information about how to plan your WebLogic Server cluster accordingly.


Y, todo esto, son conclusiones para generalizar el comportamiento de los servidoresd e aplicaciones líderes del mercado, pero podría no ser así con el servidor de aplicaciones que hayas elegido...

Pero... ¿y la especificación EJB / Java EE no deja clarito estos comportamientos?

Pues lamentablemente no, curiosamente la especificación no dice absolutamente nada de cómo debe comportarse un clúster de servidores de aplicaciones. Bueno, miento, en realidad lo dan por sentado: los "contratos" que establece la especificación que deben cumplir los fabricantes de servidores de aplicaciones indican cómo debe esperar un diseñador/desarrollador que se comporte su aplicación y sus componentes. Pero en el alto nivel, nada de balanceo. Volvemos a lo mismo que decía antes con la magia del mapeo O/R o con las implicaciones del RMI/IIOP o con las curiosidades del protocolo HTTP: los pollos de las especificaciones piensan que un "desarrollador" no debe preocuparse por esas cosas. Pues mira por dónde, yo digo que sí.

Y también hay "zonas muertas" como si el EJB Timer Service debe disparar un trigger sólo en una instancia del clúster o en todas ellas (esto lo digo como curiosidad)...

En cualquier caso, créeme, lo que cuento arriba no es sólo válido para Weblogic, también para el resto, me juego una caña.


Procesamiento por lotes (en batch) de enormes volúmenes de datos

Leches, os diréis, ¿y esta chuminada en qué me afecta a mi? Si parece que es lo correcto ¿no?

Sí, en el 90% de los casos. Es decir, como digo en un procesamiento online normal así es. Pero ¿y qué hay de un peazo de proceso batch para tratar en chuncks millones de registros o hacer procesamientos computacionalmente complejos? ¿cómo beneficiarnos de las N máquinas del clúster en este tipo de procesamiento?

Pues, salvo que utilicemos aproximaciones menos transparentes (que desaconsejo), la única forma de hacerlo es que la clase que invoca al EJB esté fuera del clúster, en otro servidor de aplicaciones, o clúster administrativo separado.

Incluso en este caso, hay que tener cuidado porque en la misma URL de Weblogic que referencio, hablan de la "Transactional Collocation", es decir dentro de una misma transacción, si se invoca a métodos de negocio del mismo EJB aunque nos hayamos asegurado de que sea remoto... el muy cabrito invoca siempre a la misma instancia del clúster elegida en el round-robin para la primera invocación.

O sea, que la única forma de balanceo real y efectiva es que cada invocación a EJB esté en una transacción distinta (o que el método esté demarcado como REQUIRESNEW). Para un procesamiento batch basado en tratamientos de lotes (o chuncks) de información, esto nos sirve. Es decir, tenemos que procesar 20.000.000 de filas, y -por si lo estábais pensando- es una gilipollez intentar hacerlo en una sola transacción, de modo que la estrategia más ampliamente utilizada es hacerlo en "pequeñas" transacciones, cada una de ellas procesando por ejemplo 10.000 registros. Bien, en este escenario es perfectamente viable puesto que los requerimientos "de negocio" casualmente coinciden con las capacidades del clústering descrito. Siempre que el "master" o "controller" del proceso batch esté fuera del clúster donde se ejecutan los componentes de tratamiento de cada lote.

Últimamente me he hecho experto en procesamiento batch en Java EE. Que por cierto es casi un mundo virgen, qué curioso. Salvo por Quartz como único planificador medianamente serio (ejem si lo comparamos con TWS, anda que no nos queda...), y Spring Batch como único intento de framework para batches de alto rendimiento (aunque no lo recomiendo, sinceramente, aparte de que está muy-muy verde, tiene toda la pinta de que evoluciona hacia el Spring Integrator) con perdón del fantástico artículo High-volume Transaction Processing in J2EE, cuyas bases son impecables pero si tenemos cuidado con la paja mental que acabo de soltar y cuyo framework planteado pego a continuación:

Aunque, ya que estamos, si de verdad estamos hablando de procesamiento batch de eTL de grandes volúmenes de información, dejémosnos de Java EE y vayamos al siguiente nivel de abstracción, los Servidores de Integración (como Java CAPS, que incorpora un bonito módulo de eTL) o herramientas de eTL independientes. Aunque por cierto, en el caso de Java CAPS sospecho que el procesamiento "distribuido" de esas Collaborations de transformación no es tan distribuido, al fin y al cabo una Colaboración se implementa por debajo como un EJB, así que...


¿Y todo esto me afecta para algo o no?

Pues tú sabrás, tú eres el arquitecto :-)

En el 90% de las situaciones no, estáte tranquilo. Tú o tus compañeros de Sistemas Medios han diseñado seguro-seguro una arquitectura que balancea a nivel de motor de servlets, o mejor aún, pode delante de él, con balanceadors de cargas delante de los Apaches para las peticiones de los navegadores.

Pero en situaciones "no tan online" o en las que tu sistema hace procesamiento "de verdad" (y no las puñeteras aplicaciones de gestión que en realidad son las bancas online, comercios electrónicos y otras cosas que nos creemos que son muy avanzadas). O si tienes que precalcular informes estadísticos del último mes, o generar ficheros de extractos para ser descargados por todos tus clientes al día siguiente, no pretenderás hacerlo online ¿verdad? Y aunque la respuesta sea "sí", probablemente te gustaría no infrautilizar los flamantes N servidores que te han puesto ahí y cuyo balanceo "por delante" presupone que hay una homogeneidad en la duración y recursos consumidos por cada operativa o transacción...

También es cierto, que un buen particionamiento de los chunks es la base de un buen proceso batch, y que sólo son paralelizables tareas en las que hay más carga de CPU de tu servidor que de la base de datos que tienes por detrás. Porque como sea ese último caso, ya puedes paralelizar en Java, que el problema no lo tienes ahí... :-)

Pero el rollo de los particionamientos, chunks y otras aves sería motivo de otro artículo bien gordote... (para una introducción, lee el enlace que he referencio arriba, lo pego otra vez: http://www.devx.com/Java/Article/20791/0/page/1 )


P.D: Cada vez me cuesta más encontrar tiempo y fuerzas para escribir...

viernes, 2 de enero de 2009

Historia de versiones del JDK y conceptos de rendimiento en Java

Esta vez simplemente apunto unos enlaces a la Wikipedia.

Son muy-muy buenas recopilaciones aunque la entrada sobre "Java performance" está algo desactualizada y algunas de las optiomizaciones que marca como "futuras" ya están disponibles en Java 6u10 (y otras fueron introducidas en la 6u6-p.

Y no sólo son buenas referencias por su contenido en si mismo, sino porque la bibliografía a la que asimismo referencian es tremenda. Enhorabuena a sus autores: