2011-06-03 13 views
5

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:¿Cómo puedo mejorar el rendimiento de una aplicación por lotes basada en MQ?

1) Índices aplicados donde corresponda.
2) Use XMLBeans para analizar los XMLs (tamaño de cada XML no es muy grande)
3) que se retiró todas las validaciones innecesarios, transformatios, etc.

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 bits (2 grupo de nodos)
MQ externa: IBM Queue
MQ almacenamiento temporal interno: JBoss MQ
Application Server: 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 en paralelo.

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

Respuesta

1

WebSphere MQ, incluso en un servidor pequeño, puede descargar mensajes MUCHO más rápido que la velocidad que describe. El Windows Performance Report for WMQ V7 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 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 de mejora estará en el análisis 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.

+0

Como dijiste, el rendimiento de MQ Websphere es bastante bueno. El problema que mencionaste ocurre al tratar de procesar los mensajes. Actualmente, no tenemos el lujo de volver a publicar los mensajes, por lo que estamos atascados con 1 publicación simple. Parece que no tengo más carreteras adicionales para tomar. Gastar dinero en hardware también está fuera del camino. Trataré de introducir el paralelismo dentro de cada procesamiento de mensaje tal vez. Gracias de todos modos, solo quería asegurarme de tener todo cubierto. – SJoe

2

Algunas sugerencias fuera de sintonía mensaje de entrega, ya que parece que esto no es su [primaria] cuello de botella:

  • Usted mencionó que está almacenando los 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 todavía dará es mejor buscar tiempos que un viaje a Oracle (a menos que esté en el mismo host, e incluso entonces ....)
  • En última instancia, si cada mensaje requiere muchos viajes redondos a la base de datos, puede beneficiarse de la migración del 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 la preparación de lotes de instrucciones. Esto enviará múltiples inserciones/actualizaciones en una sola llamada al DB.
  • Hablando de declaraciones preparadas, asegúrese de que su JBoss DataSource configuration para Oracle tiene preparado-extracto-caché-tamaño establecido en un 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 almacenamiento en caché).
  • 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, prueba un Pull/Streaming parser. 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 un montón de registro para cada mensaje, le estará costando tiempo, entonces apáguelo.
  • El uso de JBoss MQ como buffer intermediario es elegante, pero probablemente no sea la manera 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 elemento rápido en la mensajería .....

Usted no ha mencionado si estuviera utilizando beans controlados por mensajes con WebSphere MQ, pero si es así, hay un ajuste en el Inbound Configuration llamada PollingInterval la que, en palabras de la documentación, 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 de 5000 ms. Su tiempo de procesamiento mensaje 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 tiempo que recibe el mensaje en su oyente de mensajes JBoss. El tiempo de puesta en cola se puede determinar a partir de estos encabezados de los mensajes:

  • JMS_IBM_PutDate
  • JMS_IBM_PutTime

Con todo, lo mejor va a ser a la manera de paralelizar.

Buena suerte.

// Nicholas

+0

gracias. Veré qué todos se pueden usar en mi situación. – SJoe

Cuestiones relacionadas