xml performance jboss ibm-mq mq

xml - ¿Cómo puedo mejorar el rendimiento de una aplicación por lotes basada en MQ?



performance jboss (2)

Tengo una aplicación donde los mensajes siguen llegando a una velocidad de 70K XML por hora. Consumimos estos mensajes XML y los almacenamos en una cola intermedia. La cola intermedia se crea porque necesitamos cumplir SLA para consumir todos los mensajes con 24 horas. Podemos consumir y cargar el XMLS en la cola interna dentro de las 24 horas. Después de cargarlo en la cola interna, procesamos el XMLS (análisis sintáctico, aplicamos muy pocas transformaciones, realizamos muy pocas validaciones) y almacenamos los datos en un modelo de datos muy normalizado. Sé que el modelo de datos puede tener un gran impacto en el rendimiento. Desafortunadamente, no tenemos control sobre el modelo de datos. Actualmente, tomamos 3.5 minutos para procesar mensajes 2K, lo cual es inaceptable. Queremos reducirlo a 1 minuto para mensajes 2K. Esto es lo que hemos hecho hasta ahora:

1) índices aplicados donde corresponda
2) Use XMLBeans para analizar los XML (el tamaño de cada XML no es muy grande)
3) Se eliminaron todas las validaciones, transformaciones, etc. innecesarios

La aplicación se ejecuta en:
Sistema operativo: RHEL 5.4 64 bit
Plataforma: JDK 1.6.0_17, 64 bit
Base de datos: Oracle 11g R2 64 bit (clúster de 2 nodos)
MQ externo: IBM Queue
Almacenamiento temporal interno MQ: JBoss MQ
Servidor de aplicaciones: Jboss 5.1.0.GA (versión EAP)

El orden en que consumimos y procesamos los mensajes XML es muy importante, por lo que no podemos hacer un procesamiento paralelo.

¿Hay algo más que podamos hacer para mejorar el rendimiento?


WebSphere MQ, incluso en un servidor pequeño, puede descargar mensajes MUCHO más rápido que la velocidad que describe. El Informe de rendimiento de Windows para WMQ V7 se probó en más de 2,200 viajes continuos persistentes de 2k (una solicitud y una respuesta) por segundo en canales de clientes. Eso es más de 4,000 mensajes por segundo.

El cuello de botella en su caso parece ser la latencia del procesamiento de los mensajes y la dependencia en el procesamiento de los mensajes en un orden particular. La opción que podría darle el impulso MÁS de rendimiento sería eliminar la dependencia de orden. Cuando trabajaba en un banco teníamos un sistema que contabilizaba las transacciones en el orden exacto en que llegaban y todos decían que este requisito era obligatorio. Sin embargo, eventualmente revisamos el sistema para realizar una publicación memo durante el día y luego volvemos a publicar en un paso posterior. La publicación de memo se realizó en cualquier orden y paralelismo admitido, conmutación por error y todos los demás beneficios del procesamiento de varias instancias. La publicación final aplicó las transacciones en orden lógico (y de hecho en un orden que era más favorable para el cliente) una vez que todas estaban en la base de datos. Las dependencias de secuencia lo bloquean en un modelo de singleton y son un requisito del peor de los casos para la mensajería asynch. Eliminarlos si es posible.

La otra área para mejorar estará en el análisis sintáctico y el procesamiento de los mensajes. Mientras esté atascado con las dependencias de secuencia, esta es la mejor opción para mejorar el rendimiento.

Finalmente, siempre tiene la opción de invertir dinero en el problema en forma de más memoria, CPU, E / S de disco más rápido, etc. Básicamente, se trata de una arquitectura de software con potencia y nunca es la mejor solución, pero a menudo le permite el tiempo suficiente para abordar la causa raíz.


Algunas sugerencias fuera del ajuste de entrega de mensajes, ya que parece que este no es su cuello de botella [principal]:

  • Usted mencionó que está almacenando datos en una base de datos altamente normalizada. Esto invariablemente significa uno o más datos de referencia o búsquedas de PK que crean varios viajes adicionales a la base de datos para obtener estos datos. Para evitar o reducir esto, crea un caché local con todos tus datos de referencia y actualiza el caché a medida que avanzas. En las búsquedas de memoria será significativamente más rápido que un viaje a la base de datos.
  • Si cree que tiene memoria RAM insuficiente para almacenar en caché todas sus decodificaciones y datos de referencia, tome una caché basada en disco (por ejemplo, EHCache que hará RAM, Disco o Overflow) o una DB local ligera como HyperSonic o H2 que le dará una mejor búsqueda veces que un viaje a Oracle (a menos que esté en el mismo host, y aun así ...)
  • En última instancia, si cada mensaje requiere muchos viajes redondos a la base de datos, puede beneficiarse al migrar el procesamiento del mensaje al propio DB, donde puede implementar el proceso en PL / SQL o Java.
  • Si su escritura en la base de datos para un mensaje procesado implica múltiples inserciones / actualizaciones, asegúrese de usar el procesamiento por lotes de declaraciones preparadas. Esto enviará múltiples inserciones / actualizaciones en una sola llamada al DB.
  • Hablando de declaraciones preparadas, asegúrese de que su configuración de JBoss DataSource para Oracle tenga preparado-statement-cache-size en algún número lo suficientemente alto como para manejar todas las declaraciones preparadas creadas durante el procesamiento (y no el predeterminado que es cero, o no caching).
  • El analizador XML que está utilizando puede estar imponiendo más sobrecarga de la necesaria, incluso (o especialmente) para mensajes pequeños. Si está utilizando JAXB, asegúrese de que no está recreando el unmarshaller más de una vez (o más de lo necesario). Alternativamente, pruebe un analizador de extracción / transmisión . Si está usando un analizador DOM, la memoria adicional requerida puede estar causando una gran cantidad de recolección de basura.
  • Una tontería, pero vale la pena mencionar, si está ejecutando una gran cantidad de registros para cada mensaje, le costará tiempo, así que apáguelo.
  • Usar JBoss MQ como un buffer intermediario es elegante, pero probablemente no sea la forma más rápida de almacenar sus mensajes para el procesamiento diferido ya que la persistencia es más compleja y generalizada para todo tipo de tipos de mensajes JMS. En ese sentido, si JBoss MQ persiste en Oracle de todos modos, parece improbable que un procedimiento de persistencia personalizado no sea más rápido. Si JBoss MQ está almacenando en HyperSonic (como lo hace de manera predeterminada), aún puede superar el rendimiento de la tienda del mensaje JMS con algún código personalizado. Esto también significa que necesitará un nuevo mecanismo para extraer el mensaje de la base de datos para su procesamiento, pero al igual que con la tienda JMS, un proceso personalizado puede superar el procedimiento más general implementado por JBoss MQ.
  • El almacenamiento de mensajes intermedios en la base de datos también puede proporcionar más flexibilidad de consulta para determinar dónde no es necesario procesar los mensajes en serie. (Tal vez, por ejemplo, los mensajes que se originan en diferentes clientes no necesiten procesarse en secuencia). Por supuesto, también puede hacer esto con JBoss MQ colocando los encabezados apropiados en los mensajes intermedios. Esto le permitiría paralelizar utilizando diferentes selectores en múltiples oyentes / procesadores de mensajes diferentes.

Un artículo rápido sobre mensajes .....

No mencionó si estaba usando beans controlados por mensajes con WebSphere MQ, pero si lo está, hay una configuración en la Configuración entrante llamada pollingInterval que, para citar de los documentos, significa:

Si cada escucha de mensajes dentro de una sesión no tiene un mensaje adecuado en su cola, este es el intervalo máximo, en milisegundos, que transcurre antes de que cada escucha de mensajes intente de nuevo obtener un mensaje de su cola. Si con frecuencia ocurre que no hay ningún mensaje adecuado disponible para cualquiera de los oyentes de mensajes en una sesión, considere aumentar el valor de esta propiedad. Esta propiedad es relevante solo si TRANSPORT tiene el valor BIND o CLIENTE.

El tiempo de sondeo predeterminado es 5000 ms. Su tiempo de procesamiento de mensajes actual es

(3.5 * 60 * 1000/2000)

= 105 ms por mensaje.

Si introduce una pausa de 5000 ms aquí y allá, eso reducirá seriamente su rendimiento, por lo que es posible que desee analizar esto al medir la diferencia continua entre el tiempo de puesta en cola del mensaje y el momento en que recibe el mensaje en su Escuchador de mensajes JBoss. El tiempo de puesta en cola se puede determinar a partir de estos encabezados de mensaje:

  • JMS_IBM_PutDate
  • JMS_IBM_PutTime

Con todo, tu mejor apuesta será descubrir cómo paralelizar.

Buena suerte.

// Nicholas