2011-08-03 11 views
27

Como el RingBuffer por adelantado asigna objetos de un tipo dado, ¿cómo se puede usar un solo buffer de anillo para procesar mensajes de varios tipos diferentes?¿Cómo se debe usar Disruptor (Disruptor Pattern) para construir sistemas de mensajes del mundo real?

No puede crear nuevas instancias de objetos para insertar en el ringBuffer y eso anularía el propósito de la asignación inicial.

Por lo que podría tener 3 mensajes en un patrón de mensajería asincrónica:

  1. NewOrderRequest
  2. NewOrderCreated
  3. NewOrderRejected

Así que mi pregunta es ¿cómo nos referimos a utilizar el patrón disruptor para los sistemas de mensajes del mundo real?

Gracias

Enlaces: http://code.google.com/p/disruptor-net/wiki/CodeExamples

http://code.google.com/p/disruptor-net

http://code.google.com/p/disruptor

Respuesta

31

un enfoque (nuestro patrón más común) es para almacenar el mensaje en su forma movilizados, es decir, como una matriz de bytes . Para solicitudes entrantes, p. Ej. Los mensajes de reparación, mensaje binario, se extraen rápidamente de la red y se colocan en el búfer de anillo. Los EventProcessors (Consumidores) manejan el desemparejamiento y envío de diferentes tipos de mensajes en ese búfer de anillo. Para solicitudes de salida, el mensaje se serializa en la matriz de bytes preasignada que forma la entrada en el búfer de anillo.

Si está utilizando una matriz de bytes de tamaño fijo como la entrada preasignada, se necesita alguna lógica adicional para manejar el desbordamiento de mensajes más grandes. Es decir. elija un tamaño predeterminado razonable y, si se supera, asigne una matriz temporal que sea más grande. Luego, deséchelo cuando la entrada se reutilice o consuma (según su caso de uso) volviendo a la matriz original de bytes preasignados.

Si tiene diferentes consumidores para diferentes tipos de mensajes, puede identificar rápidamente si su consumidor está interesado en el mensaje específico ya sea conociendo una compensación en la matriz de bytes que lleva la información de tipo o pasando un valor discriminador en la entrada .

Además, no existe ninguna regla contra la creación de instancias de objeto y referencias de paso (lo hacemos también en un par de lugares). Se pierden los beneficios de la preasignación de objetos, sin embargo, uno de los objetivos de diseño del disruptor era permitir al usuario elegir la forma de almacenamiento más adecuada.

+1

En relación con su comentario "Se requiere alguna lógica adicional para manejar el desbordamiento ...": esto es incorrecto. Mire el video de LMAX en http: //www.infoq.com/presentations/LMAX, el tamaño de la matriz ringbuffer siempre es constante (usó 20 millones de entradas), y en la práctica está prácticamente vacío (el sistema funciona bien) o lleno (hay algo mal, y no hay cantidad de expansión) el tamaño de la matriz lo arreglará). Martin señaló que el patrón Disruptor es tan rápido que el cuello de botella se convierte en la E/S de la red o del disco, por lo que nunca se llenará en la práctica. – Contango

+31

Lo sé, estuve en esa presentación. Soy uno a la izquierda. Me doy cuenta de que mi respuesta no es particularmente clara, estaba hablando del tamaño de las entradas individuales. No es posible saber qué tamaño tendrán todos sus mensajes, pero puede adivinar muy bien y manejar el caso excepcional mediante una ruta de código más lenta. –

+1

dijiste que el enfoque más común es usar una matriz de bytes como el tipo de almacenamiento para el Disruptor. Mi pregunta es: ¿hay alguna desventaja al usar tipos de datos que no sean POD como el almacenamiento de Disruptor? Si utilizo una estructura que contiene un java.String, por ejemplo, ¿dará lugar a errores de caché? ya que la variable de miembro String podría estar en alguna ubicación lejana de la matriz en el RingBuffer. Gracias. – weima

6

Hay una biblioteca llamada Javolution (http://javolution.org/) que te permite definir objetos como estructuras con campos de longitud fija como string [40] etc. que dependen de byte-buffers internamente en lugar de tamaño variable objetos ... que permiten que el anillo token se inicialice con objetos de tamaño fijo y, por lo tanto, (afortunadamente) bloques contiguos de memoria que permiten que el caché funcione de manera más eficiente.

Estamos usando eso para pasar eventos/mensajes y usar cadenas estándar, etc. para nuestra lógica comercial.

Cuestiones relacionadas