Modelo de mensaje compatible con RabbitMQ

Modelo de mensaje compatible con RabbitMQ

Inserte la descripción de la imagen aquí
Inserte la descripción de la imagen aquí
Inserte la descripción de la imagen aquí
Introducir dependencias

<dependency>
    <groupId>com.rabbitmq</groupId>
    <artifactId>amqp-client</artifactId>
    <version>5.7.2</version>
</dependency>

1. El primer modelo (conexión directa)

Inserte la descripción de la imagen aquí
En el modelo anterior, existen los siguientes conceptos:

  • P: Productor, es decir, el programa que quiere enviar el mensaje
  • C: Consumidor: el destinatario del mensaje siempre esperará a que llegue.
  • cola: cola de mensajes, la parte roja de la figura. Al igual que en un buzón de correo, los mensajes se pueden almacenar en caché; los productores les envían mensajes y los consumidores sacan mensajes de ellos.

Desarrollador

  //创建连接工厂
  ConnectionFactory connectionFactory = new ConnectionFactory();

        connectionFactory.setHost("xxx");
        connectionFactory.setPort(5672);
        connectionFactory.setUsername("admin");
        connectionFactory.setPassword("admin");
        connectionFactory.setVirtualHost("/");
        Connection connection = connectionFactory.newConnection();

        Channel channel = connection.createChannel();

        channel.queueDeclare("query3",true,false,false,null);
        for (int i = 0; i < 20; i++) {
    
    
            channel.basicPublish("", "query3", null, (i+"====>:我是消息").getBytes());
        }
        //channel.basicPublish("","",null,"hello latte rabbitmq".getBytes());
        channel.close();
        connection.close();

Desarrollar consumidores

  //创建连接工厂
 connectionFactory.setHost("xxx");
 connectionFactory.setPort(5672);
 connectionFactory.setUsername("admin");
 connectionFactory.setPassword("admin");
 connectionFactory.setVirtualHost("/");
 Connection connection = connectionFactory.newConnection();
  Channel channel = connection.createChannel();
  channel.queueDeclare("hello", true, false, false, null);
  channel.basicConsume("hello",true,new DefaultConsumer(channel){
    
    
    @Override
    public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
    
    
      System.out.println(new String(body));
    }
  });

Descripción de los parámetros

  channel.queueDeclare("hello",true,false,false,null);
  '参数1':用来声明通道对应的队列
  '参数2':用来指定是否持久化队列
  '参数3':用来指定是否独占队列
  '参数4':用来指定是否自动删除队列
  '参数5':对队列的额外配置

2. El segundo modelo (cola de trabajo)

Work queues, También conocido como (Task queues)modelo de tareas. Cuando el procesamiento de mensajes requiere mucho tiempo, la tasa de producción de mensajes puede ser mucho mayor que la tasa de consumo de mensajes. Si las cosas siguen así, se acumularán más y más mensajes y no se podrán procesar a tiempo. En este punto, puede usar el modelo de trabajo: permita que varios consumidores se unan a una cola y consuman los mensajes en la cola juntos. Una vez que se consume el mensaje en la cola, desaparecerá, por lo que la tarea no se repetirá.

Inserte la descripción de la imagen aquí
Personaje:

  • P: Productor: El editor de la tarea.
  • C1: Consumidor -1, recibe la tarea y completa la tarea, asumiendo que la velocidad de finalización es lenta
  • C2: Consumer-2: Reciba la tarea y complete la tarea, asumiendo que la velocidad de finalización es rápida

Desarrollador

channel.queueDeclare("hello", true, false, false, null);
for (int i = 0; i < 10; i++) {
    
    
  channel.basicPublish("", "hello", null, (i+"====>:我是消息").getBytes());
}

Consumidor de desarrollo-1

channel.queueDeclare("hello",true,false,false,null);
channel.basicConsume("hello",true,new DefaultConsumer(channel){
    
    
  @Override
  public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
    
    
    System.out.println("消费者1: "+new String(body));
  }
});

Development Consumer-2

channel.queueDeclare("hello",true,false,false,null);
channel.basicConsume("hello",true,new DefaultConsumer(channel){
    
    
  @Override
  public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
    
    
    try {
    
    
      Thread.sleep(1000);   //处理消息比较慢 一秒处理一个消息
    } catch (InterruptedException e) {
    
    
      e.printStackTrace();
    }
    System.out.println("消费者2: "+new String(body));  
  }
});

总结: De forma predeterminada, RabbitMQ enviará cada mensaje al siguiente usuario en orden. En promedio, todos los consumidores recibirán la misma cantidad de mensajes. Esta forma de distribuir mensajes se llama bucle.

Mecanismo de confirmación automática de mensajes

Realizar una tarea puede tardar unos segundos. Es posible que se pregunte qué sucede si uno de los consumidores comienza una tarea larga y muere con ella solo en parte. Con nuestro código actual, una vez que RabbitMQ envía un mensaje al consumidor, lo marca inmediatamente para su eliminación. En este caso, si mata a un trabajador, perderemos el mensaje que estaba procesando. También perderemos todos los mensajes que se enviaron a este trabajador en particular pero que aún no se manejaron.
Pero no queremos perder ninguna tarea. Si un trabajador muere, nos gustaría que la tarea se le entregara a otro trabajador.

channel.basicQos(1);//一次只接受一条未确认的消息
//参数2:关闭自动确认消息
channel.basicConsume("hello",false,new DefaultConsumer(channel){
    
    
  @Override
  public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
    
    
    System.out.println("消费者1: "+new String(body));
    channel.basicAck(envelope.getDeliveryTag(),false);//手动确认消息
  }
});
  • Configure el canal para consumir solo un mensaje a la vez
  • Desactive la confirmación automática de mensajes y active la confirmación manual de mensajes

En tercer lugar, el tercer modelo (fanout)

fanout también se llama transmisión

Inserte la descripción de la imagen aquí
En el modo de transmisión, el proceso de envío de mensajes es el siguiente:

  • Puede haber varios consumidores
  • Cada consumidor tiene su propia cola (cola)
  • Cada cola debe estar vinculada a Exchange (intercambio)
  • El mensaje enviado por el productor sólo se puede enviar al intercambio, el intercambio decide a qué cola enviar, y el productor no puede decidir.
  • El intercambio envía el mensaje a todas las colas vinculadas
  • Los consumidores de la cola pueden recibir el mensaje. Darse cuenta de que un mensaje es consumido por varios consumidores.

Desarrollador

//声明交换机
String exchange="latte2.faout";
channel.exchangeDeclare(exchange, BuiltinExchangeType.FANOUT);//广播 一条消息多个消费者同时消费
channel.queueBind("query4",exchange,"");//绑定交换机
//发布消息
channel.basicPublish(exchange,"",null,"hello faout".getBytes());

Consumidor de desarrollo-1

//处理消息
channel.basicConsume(queue,true,new DefaultConsumer(channel){
    
    
  @Override
  public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
    
    
    System.out.println("消费者1: "+new String(body));
  }
});

Development Consumer-2

//处理消息
channel.basicConsume(queue,true,new DefaultConsumer(channel){
    
    
  @Override
  public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
    
    
    System.out.println("消费者2: "+new String(body));
  }
});

Development Consumer-3

//处理消息
channel.basicConsume(queue,true,new DefaultConsumer(channel){
    
    
  @Override
  public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
    
    
    System.out.println("消费者3: "+new String(body));
  }
});

Cuarto, el cuarto modelo (enrutamiento)

1. Modelo de suscripción de enrutamiento: directo (conexión directa)

En el modo Fanout, todas las colas suscritas consumirán un mensaje. Sin embargo, en algunos escenarios, queremos que diferentes colas consuman diferentes mensajes. En este momento, se utilizará el tipo de intercambio directo.

Bajo el modelo Direct:

  • El enlace entre la cola y el conmutador no se puede enlazar arbitrariamente, pero se debe especificar una RoutingKey (clave de enrutamiento)
  • Al enviar un mensaje a Exchange, el remitente de un mensaje también debe especificar la clave de ruta del mensaje.
  • Exchange ya no entrega el mensaje a cada cola enlazada, pero juzga según la clave de enrutamiento del mensaje. Solo cuando la
    clave de enrutamiento de la cola es exactamente la misma que la clave de enrutamiento del mensaje , se recibirá el mensaje
    Inserte la descripción de la imagen aquí

Ilustración:

  • P: Productor, envía un mensaje a Exchange, al enviar un mensaje, se especificará una clave de enrutamiento.
  • X: Exchange (intercambio), recibe el mensaje del productor y luego entrega el mensaje a la cola que coincide exactamente con la clave de enrutamiento
  • C1: consumidor, cuya cola especifica un mensaje que requiere una clave de enrutamiento como error
  • C2: consumidores, cuyas colas especifican mensajes que requieren claves de enrutamiento de información, error y advertencia

Desarrollador

//声明交换机  参数1:交换机名称 参数2:交换机类型 基于指令的Routing key转发
channel.exchangeDeclare("logs_direct","direct");
String key = "";
//发布消息
channel.basicPublish("logs_direct",key,null,("指定的route key"+key+"的消息").getBytes());

Consumidor de desarrollo-1

 //声明交换机
channel.exchangeDeclare("logs_direct","direct");
//创建临时队列
String queue = channel.queueDeclare().getQueue();
//绑定队列和交换机
channel.queueBind(queue,"logs_direct","error");
channel.queueBind(queue,"logs_direct","info");
channel.queueBind(queue,"logs_direct","warn");
//消费消息
channel.basicConsume(queue,true,new DefaultConsumer(channel){
    
    
  @Override
  public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
    
    
    System.out.println("消费者1: "+new String(body));
  }
});

Development Consumer-2

//声明交换机
channel.exchangeDeclare("logs_direct","direct");
//创建临时队列
String queue = channel.queueDeclare().getQueue();
//绑定队列和交换机
channel.queueBind(queue,"logs_direct","error");
//消费消息
channel.basicConsume(queue,true,new DefaultConsumer(channel){
    
    
  @Override
  public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
    
    
    System.out.println("消费者2: "+new String(body));
  }
});

2. Modelo de suscripción de enrutamiento: tema

Topic类型De Exchangela Directcomparación, ambos según RoutingKeylas diferentes rutas de la cola de mensajes. ¡Solo el tipo de tema Exchangepermite que la cola Routing keyuse comodines al enlazar ! Este modelo Routingkeygeneralmente se compone de una o más palabras, separadas por "." Entre varias palabras, por ejemplo: com.latte

Inserte la descripción de la imagen aquí

# 统配符
        * (star) can substitute for exactly one word.    匹配不多不少恰好1个词
        # (hash) can substitute for zero or more words.  匹配一个或0个或多个词

Desarrollador

//生命交换机和交换机类型 topic 使用动态路由(通配符方式)
channel.exchangeDeclare("topics","topic");
String routekey = "user.save";//动态路由key
//发布消息
channel.basicPublish("topics",routekey,null,("这是路由中的动态订阅模型,route key: ["+routekey+"]").getBytes());

Consumidor de desarrollo-1

Utilice * comodín en la clave de enrutamiento

 //声明交换机
channel.exchangeDeclare("topics","topic");
//创建临时队列
String queue = channel.queueDeclare().getQueue();
//绑定队列与交换机并设置获取交换机中动态路由
channel.queueBind(queue,"topics","user.*");
//消费消息
channel.basicConsume(queue,true,new DefaultConsumer(channel){
    
    
  @Override
  public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
    
    
    System.out.println("消费者1: "+new String(body));
  }
});

Development Consumer-2

Utilice #wildcard en la clave de enrutamiento

//声明交换机
channel.exchangeDeclare("topics","topic");
//创建临时队列
String queue = channel.queueDeclare().getQueue();
//绑定队列与交换机并设置获取交换机中动态路由
channel.queueBind(queue,"topics","user.#");
//消费消息
channel.basicConsume(queue,true,new DefaultConsumer(channel){
    
    
  @Override
  public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
    
    
    System.out.println("消费者2: "+new String(body));
  }
});

Inserte la descripción de la imagen aquí

Supongo que te gusta

Origin blog.csdn.net/qq_43803285/article/details/115033363
Recomendado
Clasificación