Procesamos los mensajes a través de una variedad de servicios (un mensaje tocará probablemente 9 servicios antes de que se haga, cada uno con una función específica relacionada con IO). En este momento tenemos una combinación del peor de los casos (serialización del contrato de datos XML) y el mejor de los casos (en memoria MSMQ) para el rendimiento.
La naturaleza del mensaje significa que nuestros datos serializados terminan entre 12 y 15 kilobytes, y procesamos aproximadamente 4 millones de mensajes por semana. Los mensajes persistentes en MSMQ fueron demasiado lentos para nosotros y, a medida que los datos crecen, sentimos la presión de los archivos de memoria de MSMQ. El servidor tiene un uso de memoria de 16 GB y crece, solo para poner en cola. El rendimiento también se ve afectado cuando el uso de la memoria es alto, a medida que la máquina comienza a intercambiarse. Ya estamos realizando el comportamiento de autolimpieza de MSMQ.
Siento que hay una parte que estamos haciendo mal aquí. Intenté usar RavenDB para conservar los mensajes y simplemente poner en cola un identificador, pero el rendimiento fue muy lento (1000 mensajes por minuto, como mucho). No estoy seguro de si eso es el resultado de usar la versión de desarrollo o qué, pero definitivamente necesitamos un rendimiento mayor [1]. El concepto funcionó muy bien en teoría, pero el rendimiento no estaba a la altura de la tarea.
El patrón de uso tiene un servicio que actúa como un enrutador, que hace todas las lecturas. Los otros servicios adjuntarán información basada en su enlace de terceros y se reenviarán al enrutador. La mayoría de los objetos se tocan de 9 a 12 veces, aunque alrededor del 10% se ven obligados a dar vueltas en este sistema durante un tiempo hasta que los terceros respondan de manera adecuada. Los servicios en este momento explican esto y tienen comportamientos adecuados para dormir, ya que utilizamos el campo de prioridad del mensaje por este motivo.
Entonces, mi pregunta, ¿cuál es una pila ideal para el paso de mensajes entre máquinas discretas pero con LAN en un entorno C # / Windows? Normalmente, comenzaría con BinaryFormatter en lugar de la serialización XML , pero eso es un agujero de conejo si una mejor manera es descargar la serialización a un almacén de documentos. Por lo tanto, mi pregunta.
[1]: La naturaleza de nuestro negocio significa que cuanto antes procesemos los mensajes, más dinero ganaremos. Hemos comprobado empíricamente que procesar un mensaje más adelante en la semana significa que tenemos menos probabilidades de ganar ese dinero. Si bien el rendimiento de "1000 por minuto" suena bastante rápido, realmente necesitamos ese número más de 10k / minuto. Solo porque estoy dando números en mensajes por semana no significa que tengamos una semana completa para procesar esos mensajes.
=============== editar:
Información adicional
Sobre la base de los comentarios, agregaré algunas aclaraciones:
-
No estoy seguro de que la serialización sea nuestro cuello de botella. He evaluado la aplicación y, si bien la serialización aparece en el gráfico de calor, solo es responsable de tal vez del 2,5 al 3% de la utilización de la CPU del servicio.
-
En general me preocupa la permanencia de nuestros mensajes y el posible uso indebido de MSMQ. Estamos utilizando mensajes no transaccionales y no persistentes para que podamos mantener el rendimiento en cola y me gustaría tener al menos mensajes persistentes para que sobrevivan a un reinicio.
-
Agregar más RAM es una medida provisional. La máquina ya ha pasado de 4 GB - > 16 GB de RAM y cada vez es más difícil eliminarlo para seguir agregando más.
-
Debido al patrón de enrutamiento en estrella de la aplicación, la mitad de las veces que se abre un objeto y luego se empuja a una cola, no cambia en absoluto. Esto se presta nuevamente (IMO) para almacenarlo en algún tipo de almacén de valor-clave en otro lugar y simplemente pasar identificadores de mensajes.
-
El patrón de enrutamiento en estrella es integral a la aplicación y no cambiará. No podemos centrarlo en la aplicación porque cada pieza a lo largo del camino funciona de forma asíncrona (en forma de sondeo) y queremos centralizar el comportamiento de reintento en un lugar.
-
La lógica de la aplicación está escrita en C #, los objetos son POCO inmutables, el entorno de implementación de destino es Windows Server 2012, y se nos permite instalar máquinas adicionales si una pieza de software en particular solo es compatible con Linux.
-
Mis objetivos son mantener el rendimiento actual al tiempo que reduce la huella de memoria y aumenta la tolerancia a fallas con un gasto mínimo de capital.