Un inicio rápido a RabbitMQ para Java avanzado (1)

Inicio rápido de RabbitMQ para Java avanzado

Conceptos relacionados

¿Qué es MQ?

MQ (cola de mensajes) es una cola de mensajes. Primero debemos saber que la naturaleza básica de la cola es primero en entrar, primero en salir, y la cola de mensajes usa la estructura de datos de la cola para almacenar mensajes. . En la arquitectura de Internet, MQ es un servicio de comunicación de mensajes de "desacoplamiento lógico + desacoplamiento físico" ascendente y descendente muy común. Después de usar MQ, el flujo ascendente del envío del mensaje solo necesita confiar en MQ y no necesita depender de otros servicios. Los llamados flujo ascendente y descendente significan que el flujo ascendente es responsable de enviar mensajes, y el flujo descendente es responsable de recibiendo mensajes.

Comprenda qué es MQ, entonces, ¿por qué usamos MQ, es decir, los beneficios de usar MQ?

  1. El primero es la reducción de los picos de tráfico. Tome el Doble 11 de Taobao como ejemplo. Todos sabemos que hay muchos usuarios que quieren comprar productos en el Doble 11 de Taobao. El número de pedidos procesados ​​por el servidor es limitado. Si este número excede este número, el servidor se bloqueará, es decir, el tráfico es particularmente grande.Si usa MQ, puede almacenar algunos mensajes procesados ​​en la cola de mensajes MQ.Aunque habrá un retraso, al menos el servidor no se bloqueará Este es el pico de tráfico.
  2. El segundo escenario de aplicación es el desacoplamiento de aplicaciones. Las llamadas entre módulos son muy complicadas. Para reducir las dependencias de llamadas entre módulos, se utiliza MQ para separar los dos sistemas y no se llama directamente a la interfaz del sistema. Para reducir la dependencia entre los dos sistemas es el desacoplamiento de aplicaciones. ¿No es esto lo que siempre hemos dicho de que un buen proyecto parte de "alta cohesión, bajo acoplamiento",
  3. Procesamiento asíncrono. Por ejemplo, después de que el usuario se registra, necesita enviar correos electrónicos de registro y SMS de registro. Hay dos métodos tradicionales: 1. Método en serie 2. Método paralelo. Si usa el método en serie, debe esperar a que se devuelva resultado antes de que pueda procesar el registro Después del código, en paralelo, es similar a abrir otro hilo para procesar la operación de registro por separado.

MQ común

ActiveMQ

Ventajas: rendimiento independiente de 10 000, puntualidad de ms, alta disponibilidad, alta disponibilidad basada en arquitectura maestro-esclavo, baja probabilidad de pérdida de datos debido a la confiabilidad del mensaje

Desventajas: la comunidad oficial ahora mantiene cada vez menos ActiveMQ 5.x, y se usa menos en escenarios de alto rendimiento.

Kafka

Kafka, la característica principal de los grandes datos, cuando se trata de la transmisión de mensajes en el campo de los grandes datos, no se puede evitar. Este middleware de mensajes nacido para los grandes datos es famoso por su rendimiento TPS de un millón de niveles y se ha convertido rápidamente en una plataforma de grandes datos. El mimado del campo, juega un papel fundamental en el proceso de recopilación, transmisión y almacenamiento de datos. Ha sido adoptado por grandes empresas como LinkedIn, Uber, Twitter, Netflix, etc.

Ventajas : excelente rendimiento, el TPS de una sola computadora es de aproximadamente un millón de piezas por segundo, y la mayor ventaja es el alto rendimiento . Puntualidad La disponibilidad a nivel de ms es muy alta, kafka se distribuye, múltiples copias de un dato, algunas máquinas se interrumpen, no hay pérdida de datos, no hay falta de disponibilidad, los consumidores usan Pull para obtener mensajes, los mensajes están en orden, a través del control Puede garantizar que todos los mensajes se consumen y solo se consumen una vez; existe una excelente interfaz de administración web Kafka de terceros, Kafka-Manager; es relativamente maduro en el campo de registro y es utilizado por muchas empresas y múltiples proyectos de código abierto; soporte de funciones: la función es relativamente simple, principalmente admite funciones MQ simples, la computación en tiempo real y la recopilación de registros en el campo de los grandes datos se utilizan a gran escala

Desventajas : si Kafka tiene más de 64 colas/particiones en una sola máquina, la carga aumentará significativamente. Cuantas más colas, mayor será la carga y mayor será el tiempo de respuesta para enviar mensajes. Usando el método de sondeo corto, la real- el rendimiento del tiempo depende del intervalo de sondeo. La falla de consumo no admite el reintento; el orden de los mensajes es compatible, pero cuando un agente deja de funcionar, los mensajes estarán desordenados y las actualizaciones de la comunidad serán lentas .

RocketMQ

RocketMQ es un producto de código abierto de Alibaba, implementado en el lenguaje Java, que hace referencia a Kafka durante el diseño y realiza algunas mejoras propias. Es ampliamente utilizado por Alibaba en escenarios como pedidos, transacciones, recargas, computación de flujo, envío de mensajes, procesamiento de flujo de registro y distribución de Binglog.

Ventajas: rendimiento independiente de 100 000 niveles , muy alta disponibilidad, arquitectura distribuida, pérdida cero de mensajes , función MQ relativamente completa, distribuida, buena escalabilidad, soporte para la acumulación de mensajes de mil millones de niveles , y no se perderá debido a los clientes potenciales de acumulación a la degradación del rendimiento. El código fuente es java. Podemos leer el código fuente por nosotros mismos y personalizar el MQ de nuestra empresa.

Desventajas: No hay muchos lenguajes de cliente soportados , actualmente java y c++, entre los cuales c++ es inmaduro; la comunidad es generalmente activa, y las interfaces como JMS no han sido implementadas en el núcleo de MQ, y algunos sistemas necesitan modificar un mucho código para migrar.

ConejoMQ

Lanzado en 2007, es un sistema de mensajería empresarial reutilizable basado en AMQP (Advanced Message Queuing Protocol) y es uno de los middleware de mensajería más importantes en la actualidad.

Ventajas: debido a la función de alta concurrencia del lenguaje erlang, el rendimiento es mejor; el rendimiento alcanza los 10 000 niveles y la función MQ es relativamente completa, robusta, estable, fácil de usar, multiplataforma y admite varios idiomas tales como: Python, Ruby, .NET, Java, JMS, C, PHP, ActionScript, XMPP, STOMP, etc., admite AJAX y documentación completa, la interfaz de administración proporcionada por el código abierto es muy buena, fácil de usar y la la comunidad es muy activa; la frecuencia de actualización es bastante alta

Actualización del sitio web oficial: https://www.rabbitmq.com/news.html(se abre en una ventana nueva)

Desventajas: la versión comercial debe cargarse y el costo de aprendizaje es alto

ConejoMQ

RabbitMQ es un middleware de mensajería: acepta y reenvía mensajes.

Puede considerarlo como un sitio de mensajería. Cuando desea enviar un paquete, coloca su paquete en la estación de mensajería y el servicio de mensajería finalmente entregará su servicio de mensajería al destinatario. De acuerdo con esta lógica, RabbitMQ es una estación de mensajería, un mensajero le entregará el expreso.

La principal diferencia entre RabbitMQ y la estación express es que no procesa el correo express pero recibe, almacena y reenvía datos de mensajes.

Sitio web oficial: https://www.rabbitmq.com/#features(se abre en una ventana nueva)

Cuatro conceptos básicos de RabbitMQ

  • productor

    El programa que genera el mensaje de envío de datos es el productor.

  • cambiar

    El conmutador es una parte muy importante de RabbitMQ: por un lado, recibe mensajes de los productores y, por otro lado, envía mensajes a la cola. El conmutador debe saber exactamente qué hacer con los mensajes que recibe, ya sea enviarlos a una cola específica o a varias colas, o descartar los mensajes, según el tipo de conmutador.

  • cola

    Las colas son una estructura de datos utilizada internamente por RabbitMQ y, aunque los mensajes fluyen a través de RabbitMQ y las aplicaciones, solo se pueden almacenar en colas. La cola está restringida únicamente por las limitaciones de memoria y disco del host y es esencialmente un gran búfer de mensajes. Muchos productores pueden enviar mensajes a una cola y muchos consumidores pueden intentar recibir datos de una cola. Así es como usamos la cola

  • consumidor

    Consumir tiene un significado similar a recibir. La mayoría de las veces, un consumidor es un programa que espera recibir mensajes. Tenga en cuenta que los productores, los consumidores y el middleware de mensajes a menudo no están en la misma máquina. La misma aplicación puede ser tanto un productor como un consumidor.

Introducción a varios términos en RabbitMQ

inserte la descripción de la imagen aquí

  • Corredor

    La aplicación para recibir y distribuir mensajes, RabbitMQ Server es Message Broker

  • Anfitrión virtual

    Los componentes básicos de AMQP, diseñados para múltiples inquilinos y factores de seguridad, se dividen en un grupo virtual, similar al concepto de espacio de nombres en la red. Cuando varios usuarios diferentes utilizan los servicios proporcionados por el mismo servidor RabbitMQ, se pueden dividir varios hosts virtuales y cada usuario crea un intercambio/cola en su propio host virtual, etc.

  • Conexión

    Conexión TCP entre editor/consumidor y corredor

  • Canal

    Si se establece una conexión cada vez que se accede a RabbitMQ, la sobrecarga de establecer una conexión TCP cuando el volumen de mensajes es grande será enorme y la eficiencia será baja. El canal es una conexión lógica establecida dentro de la conexión. Si la aplicación admite subprocesos múltiples, por lo general cada subproceso crea un canal independiente para la comunicación. El método AMQP incluye el ID del canal para ayudar al cliente y al intermediario de mensajes a identificar el canal, de modo que los canales estén completamente aislado de. Como una conexión liviana, Channel reduce en gran medida la sobrecarga del sistema operativo para establecer una conexión TCP

  • Intercambio

    Cuando el mensaje llega a la primera parada del intermediario, coincide con la clave de enrutamiento en la tabla de consulta de acuerdo con las reglas de distribución y distribuye el mensaje a la cola. Los tipos comúnmente utilizados son: directo (punto a punto), tema (publicación-suscripción) y fanout (multidifusión)

  • Cola

    El mensaje finalmente se envía aquí para que lo recoja el consumidor.

  • Vinculante

    La conexión virtual entre el intercambio y la cola, el enlace puede contener la clave de enrutamiento y la información de enlace se guarda en la tabla de consulta en el intercambio, que se utiliza como base de distribución del mensaje.

Instalación de RabbitMQ

En esta oportunidad solo explicaremos el método de instalación de rpm y la configuración de roles bajo el sistema Linux:

Dado que la capa inferior de RabbitMQ está escrita en lenguaje erlang, es necesario instalar el entorno de lenguaje erlang al instalar RabbitMQ. La siguiente es la dirección del sitio web oficial:

Dirección de descarga del sitio web oficial de RabbitMQ: https://www.rabbitmq.com/download.html

Dirección de descarga del sitio web oficial de Erlang: https://www.erlang-solutions.com/downloads/

Después de cargarlo en el sistema Linux, instálelo:

#  erlangxxxxx.rpm是erlang完整的名称
rpm -ivh erlangxxxxx.rpm
yum install socat -y
# rabbitmqxxxxx.rpm是rabbitMQ完整的名称
rpm -ivh rabbitmqxxxxx.rpm

Comandos comunes para RabbitMQ:

# 启动服务
systemctl start rabbitmq-server
# 查看服务状态
systemctl status rabbitmq-server 
# 开启自启动
systemctl enable rabbitmq-server
# 停止服务
systemctl stop rabbitmq-server 
# 重启服务
systemctl restart rabbitmq-server

Interfaz de administración web

RabbitMQ tiene su propia interfaz de administración web y el puerto predeterminado utilizado es 15672

La primera interfaz de administración web que usa RabbitMQ necesita instalar el complemento del cliente web:

rabbitmq-plugins enable rabbitmq_management

Una vez completada la instalación, reinicie el servicio RabbitMQ

systemctl restart rabbitmq-server

Ingrese a la interfaz de administración web de RabbitMQ, podemos ver que necesitamos iniciar sesión en la cuenta.

inserte la descripción de la imagen aquí

RabbitMQ viene con una cuenta de invitado, pero debe configurarse para iniciar sesión en la cuenta de invitado. Entonces necesitamos recrear nuestra propia cuenta, el comando es el siguiente:

# 创建账号
rabbitmqctl add_user admin 123
# 设置用户的角色
rabbitmqctl set_user_tags  admin administrator 
# 设置用户的权限
# set_permissions [-p <vhostpath>] <user> <conf> <write> <read>
rabbitmqctl set_permissions -p "/" admin ".*" ".*" ".*"

Los roles de usuario incluyen principalmente los siguientes cuatro tipos:

  1. administrador : puede iniciar sesión en la consola, ver toda la información y administrar rabbitmq
  2. monitoreo : el monitor inicia sesión en la consola para ver toda la información
  3. formulador de políticas : el creador de políticas inicia sesión en la consola y especifica la política
  4. administración : los administradores ordinarios inician sesión en la consola

Ábralo nuevamente, inicie sesión con el administrador de la cuenta y la contraseña 123, e ingrese a la interfaz de fondo de RabbitMQ después de iniciar sesión correctamente:
inserte la descripción de la imagen aquí

Empezando

Hola Mundo

En esta parte del tutorial, escribiremos dos programas en Java. Un productor que envía un solo mensaje y recibe un mensaje e imprime

consumidores fuera. Cubriremos algunos de los detalles en la API de Java.

En el siguiente diagrama, "P" es nuestro productor y "C" es nuestro consumidor. El cuadro del medio es una cola: generación RabbitMQ

El búfer de mensajes mantenido por el consumidor de la tabla.

inserte la descripción de la imagen aquí

Después de crear el proyecto en idea, importe las dependencias requeridas.

<!--指定 jdk 编译版本-->
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
                <source>8</source>
                <target>8</target>
            </configuration>
        </plugin>
    </plugins>
</build>
<dependencies>
    <!--rabbitmq 依赖客户端-->
    <dependency>
        <groupId>com.rabbitmq</groupId>
        <artifactId>amqp-client</artifactId>
        <version>5.8.0</version>
    </dependency>
    <!--操作文件流的一个依赖-->
    <dependency>
        <groupId>commons-io</groupId>
        <artifactId>commons-io</artifactId>
        <version>2.6</version>
    </dependency>
</dependencies>

código productor de mensaje

package com.it.rabbitmq;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.ConnectionFactory;

import java.nio.charset.StandardCharsets;

public class Producer {
    
    
    public static void main(String[] args) throws Exception{
    
    
        //创建一个连接工厂
        ConnectionFactory connectionFactory = new ConnectionFactory();
        //设置要连接RabbitMQ所在服务器的ip地址,这里要进行填写自己的
        connectionFactory.setHost("121.56.241.29");
        //设置账号
        connectionFactory.setUsername("admin");
        //设置密码
        connectionFactory.setPassword("123");
        //创建信道channel
        //channel实现了自动close接口,自动关闭
        Channel channel = connectionFactory.newConnection().createChannel();
        /**
         * 进行生成一个队列
         * 1. 队列名称
         * 2. 队列里面是否持久化
         * 3. 该队列是否只进行提供一个消费者进行(是否共享)
         * 4. 是否自动删除,即最后一个消费者断开连接之后,队列是否自动删除该消息
         * 5. 其他参数
         */
        //队列名称为test,不持久化,不共享,不自动删除,没有其他参数
        channel.queueDeclare("test",false,false,false,null);
        String msg = "Hello World";
        /**
         * 进行发送一个消息
         * 1. 发送到哪个交换机(目前没有交换机进行传空,代表的是默认交换机)
         * 2. 路由的key(当前的key没有声明,使用队列名称即可)
         * 3. 其他参数信息
         * 4. 发送消息的消息体
         */
        channel.basicPublish("","test",null,msg.getBytes(StandardCharsets.UTF_8));
        System.out.println("消息发送成功");
    }
}

mensaje de código de consumidor

package com.it.rabbitmq;

import com.rabbitmq.client.CancelCallback;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.DeliverCallback;

public class Consumer {
    
    
    public static void main(String[] args) throws Exception{
    
    
        //创建连接工厂
        ConnectionFactory connectionFactory = new ConnectionFactory();
        //设置ip地址
        connectionFactory.setHost("121.56.241.29");
        //设置账号
        connectionFactory.setUsername("admin");
        //设置密码
        connectionFactory.setPassword("123");
        //获取信道
        Channel channel = connectionFactory.newConnection().createChannel();
        //消息成功接受的回调方法,采用lambda表达式
        DeliverCallback deliverCallback = (tag,message)->{
    
    
            //将信道存储的信息转化为字符串类型
            String msg = new String(message.getBody());
            System.out.println(message);
        };
        //取消消费的回调接口
        CancelCallback cancelCallback = (tag)->{
    
    
            System.out.println("消息被取消");  
        };
        /**
         * 消费者消费消息
         * 1. 消费哪个队列
         * 2. 消费成功后是否自动应答
         * 3. 消费成功的回调接口
         * 4. 消费取消的回调接口
         */
        channel.basicConsume("test",true,deliverCallback,cancelCallback);
    }
}

Primero, se debe ejecutar el productor, crear una cola en RabbieMQ y luego ejecutar el productor. El efecto es el siguiente:

inserte la descripción de la imagen aquí

cola de trabajo

Colas de trabajo: la idea principal de las colas de trabajo (también conocidas como colas de tareas) es evitar la ejecución inmediata de tareas que consumen muchos recursos y tener que esperar a que se complete. En su lugar, programamos la tarea para que se ejecute más tarde. Encapsulamos la tarea como un mensaje y la enviamos a la cola. Un proceso de trabajo que se ejecuta en segundo plano mostrará las tareas y finalmente ejecutará el trabajo. Cuando hay varios subprocesos de trabajo, estos subprocesos de trabajo trabajarán juntos en estas tareas.

Sondeo para enviar mensajes

En este caso, comenzaremos dos subprocesos de trabajo, un subproceso de envío de mensajes, veamos cómo funcionan sus dos subprocesos de trabajo.

extraer clase de trabajo

package com.it.rabbitmq.util;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.ConnectionFactory;

public class RabbitMQUtil {
    
    
    //进行获取信道channel
    public static Channel getChannel() throws Exception{
    
    
        //创建连接工厂
        ConnectionFactory connectionFactory = new ConnectionFactory();
        //设置ip地址
        connectionFactory.setHost("121.56.241.29");
        //设置账号
        connectionFactory.setUsername("admin");
        //设置密码
        connectionFactory.setPassword("123");
        //获取信道
        Channel channel = connectionFactory.newConnection().createChannel();
        return channel;
    }
}

Iniciar un hilo de envío

package com.it.rabbitmq;

import com.it.rabbitmq.util.RabbitMQUtil;
import com.rabbitmq.client.Channel;

import java.nio.charset.StandardCharsets;

//发送线程,生产者
public class Producer {
    
    
    public static void main(String[] args) throws Exception{
    
    
        Channel channel = RabbitMQUtil.getChannel();
        /**
         * 进行生成一个队列
         * 1. 队列名称
         * 2. 队列里面是否持久化
         * 3. 该队列是否只进行提供一个消费者进行(是否共享)
         * 4. 是否自动删除,即最后一个消费者断开连接之后,队列是否自动删除该消息
         * 5. 其他参数
         */
        //队列名称为test,不持久化,不共享,不自动删除,没有其他参数
        channel.queueDeclare("test",false,false,false,null);
        String msg = "Hello World";
        /**
         * 进行发送一个消息
         * 1. 发送到哪个交换机(目前没有交换机进行传空,代表的是默认交换机)
         * 2. 路由的key(当前的key没有声明,使用队列名称即可)
         * 3. 其他参数信息
         * 4. 发送消息的消息体
         */
        channel.basicPublish("","test",null,msg.getBytes(StandardCharsets.UTF_8));
        System.out.println("消息发送成功");
    }
}

Iniciar un hilo de consumidor

package com.it.rabbitmq;

import com.it.rabbitmq.util.RabbitMQUtil;
import com.rabbitmq.client.CancelCallback;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.DeliverCallback;

//接受线程消费者
public class Consumer {
    
    
    public static void main(String[] args) throws Exception{
    
    
        Channel channel = RabbitMQUtil.getChannel();
        //消息成功接受的回调方法,采用lambda表达式
        DeliverCallback deliverCallback = (tag,message)->{
    
    
            //将信道存储的信息转化为字符串类型
            String msg = new String(message.getBody());
            System.out.println("接收到的消息:"+msg);
        };
        //取消消费的回调接口
        CancelCallback cancelCallback = (tag)->{
    
    
            System.out.println("消息被取消");
        };
        /**
         * 消费者消费消息
         * 1. 消费哪个队列
         * 2. 消费成功后是否自动应答
         * 3. 消费成功的回调接口
         * 4. 消费取消的回调接口
         */
        channel.basicConsume("test",true,deliverCallback,cancelCallback);
    }
}

El resultado de la operación es el siguiente:

inserte la descripción de la imagen aquí

mensaje de respuesta

Los consumidores pueden tardar un tiempo en completar una tarea, qué sucede si uno de los consumidores procesa una tarea larga y solo completa una parte de ella y de repente muere. RabbitMQ marca un mensaje para su eliminación tan pronto como lo entrega a un consumidor. En este caso, de repente muere un consumidor y perdemos los mensajes que estábamos procesando. y mensajes posteriores enviados al consumidor porque no pudo recibirlos.

Para garantizar que el mensaje no se pierda durante el proceso de envío, se introduce un mecanismo de respuesta de mensaje. La respuesta del mensaje es: después de que el consumidor recibe el mensaje y lo procesa, le dice a rabbitmq que ha sido procesado, y rabbitmq puede borrar el mensaje.

respuesta automática

Inmediatamente después de que se envía el mensaje, se considera que se ha transmitido con éxito. Este modo requiere un equilibrio entre el alto rendimiento y la seguridad de la transmisión de datos , porque en este modo, si el mensaje se recibe antes de que se reciba el mensaje, hay un conexión en el lado del consumidor o el canal se cierra, entonces el mensaje Se pierde. Por supuesto, por otro lado, los consumidores en este modo pueden transmitir mensajes sobrecargados sin limitar la cantidad de mensajes transmitidos . Por supuesto, esto puede hacer que los consumidores recibe demasiados mensajes que son demasiado tarde para procesar, lo que resulta en La acumulación de estos mensajes eventualmente hará que se agote la memoria y, finalmente, el sistema operativo eliminará estos subprocesos del consumidor, por lo que este patrón solo es adecuado si el consumidor puede procesar estos mensajes de manera eficiente y a cierta velocidad.

Método de respuesta manual

  • Channel.basicAck (para confirmación positiva)

    RabbitMQ ya conoce el mensaje y lo procesó con éxito, por lo que puede descartarse

  • Channel.basicNack (para reconocimiento negativo)

  • Channel.basicReject (para confirmación negativa)

    En comparación con Channel.basicNack, hay un parámetro menos, si el mensaje no se procesa, se rechazará directamente y se puede descartar.

La ventaja de la respuesta manual es que se puede responder por lotes y reducir la congestión de la red.

El contenido posterior continuará actualizándose, haga clic en seguir gratis para no perderse.

Supongo que te gusta

Origin blog.csdn.net/weixin_45927121/article/details/121864203
Recomendado
Clasificación