Empuje o tire de la cola de mensajes, ¿cómo lo hacen RocketMQ y Kafka?

Hoy hablaremos sobre el modo push-pull de las colas de mensajes, que también es un punto de acceso para entrevistas. Por ejemplo, si escribió RocketMQ en su currículum, básicamente le preguntará si RocketMQ usa el modo push o pull. ¿Es un modo de extracción? ¿No hay un PushConsumer?

Hoy hablaremos sobre el modelo push-pull y luego veremos cómo lo hacen RocketMQ y Kafka.


Modo push-pull

En primer lugar, aclarar qué paso de la cola de mensajes se encuentra en el modo push-pull. En general, cuando hablamos del modo push-pull, nos referimos a la interacción entre Comsumer y Broker.

El valor predeterminado es que entre Producer y Broker está el método de envío, es decir, Producer envía mensajes al Broker en lugar de que el Broker los extrae activamente.

Imagine que si se requiere que Broker extraiga mensajes, entonces Producer debe guardar los mensajes localmente en forma de registros para esperar a que Broker los extraiga. Si hay muchos productores, la confiabilidad de los mensajes depende no solo del Broker en sí, sino también Confíe en cientos de productores.

Broker también puede confiar en mecanismos como copias múltiples para asegurar el almacenamiento confiable de mensajes La confiabilidad de cientos de productores es un poco difícil, por lo que el Producer predeterminado envía los mensajes al Broker.

Entonces, en algunos casos es mejor estar distribuido, pero en algunos casos es mejor la administración centralizada.


Modo de empuje

El modo de envío se refiere al mensaje que se envía del corredor al consumidor, es decir, el consumidor recibe el mensaje de forma pasiva y el corredor toma la iniciativa para enviar el mensaje.

Pensemos en los beneficios del modo push.

El mensaje en tiempo real es alto y el corredor puede enviarlo al consumidor inmediatamente después de recibir el mensaje.

Es más fácil de usar para los consumidores, simple, solo espere, y cualquier noticia será pasada por alto.

¿Cuáles son las desventajas del modo push?

La tasa de envío es difícil de adaptar a la tasa de consumo. El objetivo del modelo de inserción es enviar mensajes a la velocidad más rápida. Cuando la tasa del productor que envía mensajes al corredor es mayor que la tasa a la que los consumidores consumen mensajes, el consumidor puede convertirse en " "Rota", porque no hay consumo alguno. Cuando la tasa de empuje es demasiado rápida, como un ataque DDos, los consumidores son estúpidos.

Y la tasa de consumo de diferentes consumidores no es la misma. Como corredor, es difícil equilibrar la tasa de empuje de cada consumidor. Si desea lograr una tasa de empuje adaptativa, debe decirle al corredor cuando el consumidor está presionando, no puedo hacerlo. Empuje lentamente, y luego el Broker debe mantener el estado de cada consumidor para cambiar la tasa de empuje.

En realidad, esto aumenta la complejidad del propio Broker.

Por lo tanto, el modo push es difícil de controlar la tasa de push según el estado del consumidor, y es adecuado para situaciones en las que el volumen de mensajes es pequeño y el consumo de energía es alto y se requiere tiempo real.


Modo de extracción

El modo de extracción se refiere a que el Consumidor solicita activamente al Broker que extraiga mensajes, es decir, el Broker envía mensajes pasivamente al Consumidor.

Pensemos en los beneficios del modo pull.

La iniciativa en el modo de extracción recae en los consumidores, que pueden iniciar solicitudes de extracción en función de sus propias condiciones. Suponiendo que el consumidor actual siente que no puede pagarlo, puede detener el tirón de acuerdo con una estrategia determinada o hacerlo a intervalos.

Broker es relativamente fácil en modo pull. Solo guarda los mensajes enviados por el productor. En cuanto al consumo, naturalmente lo inicia el consumidor. Se le da una solicitud. Se toma el mensaje de donde recibir el mensaje. Dile que es una herramienta persona sin emociones, y no importa si los consumidores no vienen a recogerla.

El modo de extracción puede ser más adecuado para enviar mensajes en lotes. Según el modo de envío, se puede enviar un mensaje o algunos mensajes se pueden almacenar en caché y luego se pueden enviar, pero al presionar, no se sabe si los consumidores pueden manejar tantos mensajes a la vez. El modo de extracción es más razonable: puede referirse a la información solicitada por el consumidor para determinar cuántos mensajes almacenar en caché y enviar en lotes.

¿Cuáles son las desventajas del modo pull?

Después de todo, la demora del mensaje es el consumidor para extraer el mensaje, pero ¿cómo sabe el consumidor que el mensaje ha llegado? Por lo tanto, solo puede tirar continuamente, pero no puede solicitarlo con mucha frecuencia, si es demasiado frecuente, se convertirá en un consumidor atacando al Broker. Por lo tanto, debe reducir la frecuencia de las solicitudes. Por ejemplo, si solicita una vez cada 2 segundos, es posible que se demore 2 segundos cuando mire el mensaje.

Solicitud de mensaje ocupado: Solicitud de ocupado significa que, por ejemplo, el mensaje se recibe varias horas más tarde, luego la solicitud del consumidor no es válida en unas pocas horas y está haciendo un trabajo inútil.


¿Eso es empujar o tirar?

Podemos ver que el modo push y el modo pull tienen sus propias ventajas y desventajas ¿Cómo elegir?

Tanto RocketMQ como Kafka han elegido el modelo pull. Por supuesto, la industria también tiene colas de mensajes basadas en modelos push, como ActiveMQ.

Personalmente creo que el modelo pull es más adecuado, porque la cola de mensajes actual tiene la necesidad de mensajes persistentes, es decir, tiene una función de almacenamiento en sí misma, y ​​su misión es recibir mensajes y guardar los mensajes para que los consumidores puedan consumirlos. lata.

Hay varios consumidores. Como Broker, no debe tener la tendencia a depender de los consumidores. He guardado las noticias para usted.

Aunque en general, Broker no se convertirá en un cuello de botella, porque el consumidor tiene un consumo comercial más lento, pero Broker es un punto central después de todo, y es lo más liviano posible.

Entonces, RocketMQ y Kafka eligieron el modo pull, ¿no temen las deficiencias del modo pull? Asustados, por lo que operan una ola, aliviando las deficiencias del modo pull.


Sondeo largo

RocketMQ y Kafka usan "sondeo largo" para implementar el modelo de extracción, echemos un vistazo a cómo operan.

En aras de la simplicidad, a continuación, describiré uniformemente las noticias que no cumplen con el número y tamaño total de este tirón ya que no hay noticias, de todos modos, no se cumplen las condiciones.


Sondeo largo en RocketMQ

PushConsumer en RocketMQ es en realidad un método para usar un modo pull, pero parece un modo push.

Porque RocketMQ nos ayudó en secreto a acudir al corredor para solicitar datos entre bastidores.

Habrá un subproceso RebalanceService en segundo plano. Este subproceso realizará el equilibrio de carga en función del número de colas de temas y el número de consumidores en el grupo de consumidores actual. La pullRequest generada por cada cola se coloca en la cola de bloqueo pullRequestQueue. Luego hay otro subproceso PullMessageService que obtiene continuamente pullRequest de la cola de bloqueo pullRequestQueue, y luego solicita al corredor a través de la red, para que pueda extraer mensajes en tiempo cuasi-real.

No cortaré esta parte del código, es tal cosa, lo mostraré con una imagen más adelante.

Luego, el método processRequest en el PullMessageProcessor del Broker se utiliza para procesar la solicitud del mensaje de extracción. Si hay un mensaje, se devolverá directamente. ¿Qué pasa si no hay ningún mensaje? Echemos un vistazo al código.

Veamos qué hace el método suspendPullRequest.

El subproceso PullRequestHoldService obtendrá la solicitud PullRequest de pullRequestTable cada 5 segundos, y luego verificará si el desplazamiento de la solicitud de mensaje que se va a extraer es menor que el desplazamiento máximo de la cola de consumo actual. Si la condición es verdadera, significa que hay un nuevo mensaje y se llamará a notifyMessageArriving. Finalmente, se llama al método executeRequestWhenWakeup () de PullMessageProcessor para volver a intentar procesar la solicitud de este mensaje, es decir, volver a hacerlo. El tiempo de sondeo largo predeterminado es de 30 segundos.

En pocas palabras, es hora de verificar el mensaje cada 5 segundos y, si es así, llame a processRequest para procesarlo nuevamente. ¿No parece en tiempo real? ¿5 segundos?

No se preocupe, también hay un hilo ReputMessageService. Este hilo se utiliza para analizar continuamente los datos de commitLog y distribuir solicitudes, construyendo dos tipos de datos, ConsumeQueue e IndexFile, y también habrá solicitudes de activación para compensar cada 5 segundos. Retraso lento

No interceptaré el código, es decir, el mensaje está escrito y se llamará a pullRequestHoldService # notifyMessageArriving.

Finalmente, haré un dibujo para describir todo el proceso.


Encuestas largas en Kafka

Al igual que Kafka, hay parámetros en la solicitud de extracción, que pueden hacer que las solicitudes de los consumidores se bloqueen en espera en el "sondeo largo".

En pocas palabras, el consumidor acude al Broker para extraer el mensaje y define un período de tiempo de espera, lo que significa que el consumidor solicita el mensaje y lo devuelve inmediatamente si lo hay. De lo contrario, el consumidor espera hasta que se agote el tiempo de espera y luego vuelve a iniciar la solicitud de extracción del mensaje. .

Y el Broker también debe cooperar, si el consumidor lo solicita se debe devolver un mensaje de inmediato, si no hay mensaje se establece una operación retrasada y se cumple la condición antes de regresar.

Echemos un vistazo breve al código fuente. Para resaltar los puntos clave, cortaré un poco de código.

Veamos primero el código del consumidor.

La interfaz de la encuesta anterior debe ser familiar para todos. De hecho, usted sabe directamente por los comentarios que de hecho está esperando la llegada de datos o el tiempo de espera. Miremos hacia abajo brevemente.

Echemos un vistazo a lo que llama el cliente final.

La última llamada es el selector envuelto por Kafka, y finalmente se llama a select (timeout) de Java nio.

Ahora que el código del consumidor es claro, echemos un vistazo a cómo lo hace Broker.

La entrada para que Broker procese todas las solicitudes se introdujo en el artículo anterior, justo debajo del método handle del archivo KafkaApis.scala, esta vez el protagonista es handleFetchRequest.

Este método entra, intercepto la parte más importante.

La siguiente imagen es la implementación interna del método fetchMessages. Los comentarios dados por el código fuente ya son muy claros. Puedes acercar y ver.

El nombre de este purgatorio es muy interesante. En pocas palabras, es usar la rueda del tiempo mencionada en mi artículo anterior para realizar tareas de cronometraje. Por ejemplo, se delayedFetchPurgatoryusa específicamente para manejar operaciones de extracción retardada.

Primero pensemos brevemente acerca de qué métodos deben implementarse para esta operación retrasada. Primero, la operación retrasada construida necesita tener un mecanismo de verificación para verificar si el mensaje ha llegado, y luego debe haber un método que debe ejecutarse después de que llega el mensaje, y debe ejecutarse. Qué hacer después de terminar, por supuesto, debe haber un método para hacer después del tiempo de espera.

Estos métodos realmente corresponden a DelayedFetch en el código. Esta clase hereda DelayedOperation y tiene:

  • isCompleted método para comprobar si se cumple la condición

  • tryComplete método que se ejecutará después de que se cumpla la condición

  • Se ejecuta el método llamado después de onComplete

  • El método que debe ejecutarse después de que expire onExpiration

Juzgar si está vencido lo impulsa la rueda del tiempo, pero no puede esperar a ver las noticias cuando termine, ¿verdad?

El mecanismo de Kafka y RocketMQ aquí es el mismo. También recordará estos mensajes de solicitud retrasados ​​cuando se escriba el mensaje. No publicaré el código específico. Puede ver dos métodos más en el método ReplicaManager # appendRecords.

Aunque el código no está publicado, la imagen aún debe dibujarse.


Resumen

Se puede ver que tanto RocketMQ como Kafka adoptan el mecanismo de "sondeo largo". El método específico es esperar mensajes a través de los consumidores. Cuando hay un mensaje, el corredor lo devolverá directamente. Si no hay ningún mensaje, adoptará una estrategia de procesamiento de demora y Para garantizar la puntualidad del mensaje, cuando llegue un mensaje nuevo a la cola o partición correspondiente, le recordará que debe venir y devolver el mensaje a tiempo.

En una palabra, el consumidor y el corredor cooperan entre sí para esperar cuando la solicitud del mensaje de extracción no cumple con las condiciones, evitando múltiples acciones de extracción frecuentes y recordando que deben regresar tan pronto como llegue el mensaje.

 

Al final

En términos generales, el modo push-pull tiene sus propias ventajas y desventajas, y personalmente creo que el modo desplegable es más adecuado para las colas de mensajes en general.

No hay manera, pero la técnica se puede lograr; si no hay manera, termina con la técnica.

Bienvenidos a todos a seguir la cuenta pública de Java Way

Buen artículo, estoy leyendo ❤️

Supongo que te gusta

Origin blog.csdn.net/hollis_chuang/article/details/108480421
Recomendado
Clasificación