preface

This article is mainly a primer on RabbitMQ, you can learn the following:

  • History of MQ
  • Closer agreement
  • Rabbit MQ installation
  • Use of Rabbit MQ in the Java API
  • RabbitMQ integration with SpringBoot

MQ’s birth history

Most technologies start out with a specific scope of applicability. For example, with the emergence of the Internet, the communication protocol that emerged at the beginning was incompatible with each manufacturer. With the development of history, TCP/IP protocol, the communication standard in the industry, came into being, and MQ is the same. The first MQ software was created by A company called Teknekron, founded by Vivek Ranadive, an Indian in The United States, and implemented The world’s first messaging middleware, The Information Bus(TIB).

With the birth of the first MQ software TIB, major manufacturers immediately followed up, flowers argued, a number of MQ software emerged, such as IBM Wesphere developed by IBM, MSMQ developed by Microsoft and so on, but because the standard is not unified, it brings great inconvenience to our users. Each time you switch MQ, you need to implement a different protocol and a different API call repeatedly.

In 2001, The old owner of the Java language, Sun, released a JMS specification that encapsulated MQ across major manufacturers so that users could use different MQ drivers (just as we use database drivers). JMS specification although unified standards, but JMS specification has a big flaw is that it is bound to the Java language, so it still does not fundamentally solve the problem.

The golden age of MQ came in 2004 when the AMQP specification emerged, making it truly cross-lingual and cross-platform.

In 2007, Rabbit developed a message queue, RabbmitMQ, based on the AMQP specification. RabbitMQ soon became popular and widely used.

What is the MQ

MQ is Message Queue, called Message Queue or Message middleware. The essence of MQ is the use of efficient and reliable messaging mechanisms for platform-independent data delivery and the integration of distributed systems based on data communication. In other words, MQ is mainly used to solve the communication problem of messages. It has the following three characteristics:

  • 1.MQIs a standalone service. Producers are used to send messages and consumers are used to receive consumption.
  • 2, the internal use of queue for message storage, generally adopted are first in first out (FIFO) queue.
  • 3. With a publish and subscribe model, consumers can get the messages they want according to their needs.

Why MQ is needed

In the Java language, for example, the JDK itself provides many different types of queues, so why use MQ? This is because:

  • 1. Cross language. Queues implemented internally by major programming languages are language-bound and stand-alone and do not work well in a distributed environment, so we need one that can be deployed independently of the languageMQ.
  • 2. Asynchronous decoupling. Message queue can realize asynchronous communication, so that the sender only needs to care about whether the message is sent successfully, and the receiver only needs to care about how to process the message in the queue, which realizes the decoupling of consumption and producer.
  • 3, flow peak cutting. Because message queue is first in, first out, so if you put the messages that need to be consumed into the queue, then consumers can avoid being overwhelmed by the instantaneous heavy traffic, but can leisurely according to their own ability to take messages out of the queue for consumption.

RabbitMQ

The Rabbit in RabbitMQ means to run as fast as a Rabbit. It is a lightweight, highly available message queue that supports multiple messaging protocols. RabbitMQ is written in The Erlang language, which is naturally suited to high concurrency.

Advantages and features of RabbitMQ

RabbitMQ is a very popular messaging middleware with a wealth of features and advantages:

  • High reliability:RabbitMQIt provides persistence, send reply, release confirmation and other functions to ensure its reliability.
  • Flexible routing: Messages can be flexibly routed through different exchanges.
  • Clustering and scalability: Multiple nodes can form a logical server to support load.
  • High availability: Data in the queue is replicated through mirroring queues, ensuring that some nodes appear in extreme casescrashThe entire cluster is still available.
  • Supports multiple protocols:RabbitMQOriginally it was for supportAMQPIt was developed by protocol, soAMQPIs its core protocol, but it also supports others such as:STOMP.MOTT.HTTPSuch agreement.
  • Support for multiple clients:RabbitMQAlmost all common language clients are supported, such as:Java.Python.Ruby.GoAnd so on.
  • Rich plug-in system: support a variety of rich plug-in extensions, as well as support for custom plug-ins. Like the most commonRabbitMQBackground management system is implemented in the form of plug-ins.

It models

AMQP stands for Advanced Message Queuing Protocol. The core protocol of RabitMQ is the AMQP protocol based on the AMQP model. The latest version of THE AMQP model is version 1.0, but the best version officially recommended for users is still based on the AMQP model of version 0.9.1. Version 0.9.1 is also called the AMQP 0-9-1 model in RabbitMQ.

AMQP 0-9-1 (Advanced Message Queue Protocol) is a messaging protocol that allows standards-compliant client applications to communicate with standards-compliant messaging middleware brokers. The messaging Broker receives messages from the Publisher (the application that publishes the message, also known as producer: Producter) and routes them to the Consumer (Consumer, the application that processes the message).

The core idea of the AMQP 0-9-1 model is that messages are posted to an exchange, which is often compared to a post office or mailbox. The switch then distributes the copy of the message to the queue using a rule called binding. The broker then passes the message to the consumer that subscribes to the queue, or the consumer retrieves/extracts the message from the queue as needed.

Here’s oneAMQPThe model diagram, if you understand this diagram, you basically understand itRabbitMQWorking mode.

A Producer, usually an application client, produces messages that are sent to RabbitMQ for processing by the consumer.

A Consumer is a Consumer that takes a message from a particular queue and consumes it. When a message is delivered to a consumer, the consumer notifies the Broker automatically, and the Broker removes the message completely from the queue only when it is notified about it.

Connection: I am a TCP long Connection

A producer must establish a TCP long connection with the Broker before sending a message and a consumer must establish a TCP long connection before receiving a message.

Channel: I’m made up

One of the role of the message queue is used to do the peak clipping, so the message queue in high concurrency scenario may have a large number of producers and consumers, as if every producer when sending a message or a consumer in the consumer message needs to be continuously created and destroyed the TCP connection, so the Broker can be a great consumption, To reduce the frequency at which this TCP connection is created, the AMQP model introduces channels (channels or channels).

A Channel is a virtual connection that can be considered a “lightweight connection that shares the same TCP connection.” You can create and destroy different channels in the same TCP long connection to reduce the frequency of creating and destroying TCP connections, which greatly reduces the consumption of resources.

Every protocol operation performed by the client (producer/consumer) takes place on the channel. Communication on a particular Channel is completely independent of communication on another Channel, so each protocol method also carries a Channel ID (also known as a Channel number).

A Channel exists only in the context of a connection and does not exist independently, so when a TCP connection is closed, all channels are closed as well.

Channels are thread-unsafe, so for applications that use multiple threads/processes for processing, you need to create a Channel for each thread/process rather than sharing the same Channel.

Broker: I’m just an ordinary Broker

The RabbitMQ server is a RabbitMQ server. The RabbitMQ server is a RabbitMQ server.

Exchange: I’m just doing a message mapping

Echange is a switch. Because of the many-to-many relationship between producers and consumers, one queue is not sufficient. So if there are multiple queues, where should we store the messages we send each time? Switches is the middle of the played a role, we send a message to the switch, and then sent via the switch to the corresponding queue, switches and need early binding good corresponding relation between the queue, this message got to within their specified queue, and then consumers can directly from their respective responsible for remove the message queue for consumption.

Queue: I’m where the messages are actually stored

After messages are sent to the Broker, they are mapped to the switch and stored in the specified Queue.

VHost: I’m just a namespace

A VHost is similar to a namespace and is used to isolate data. For example, RabbitMQ is used by many business systems. If a single server is sufficient, there is no need to install multiple RabbitMQ hosts. Different Vhosts can realize data isolation between various business systems.

The installation of the RabbitMQ

RabbitMQ is developed in The Erlang language, so you will need to install Erlang before installing RabbitMQ. There is a version relationship between RabbitMQ and Erlang. This article uses Erlang 21.3 and RabbitMQ3.8.4 as examples.

  1. The installationErlang
yum -y install gcc glibc-devel make ncurses-devel openssl-devel xmlto perl wget // Install some dependencies in advance. Depending on the PC's dependencies, you can select the uninstalled dependencies as required
wget http:/ / erlang.org/download/otp_src_21.3.tar.gz # download (also can be downloaded to the server)
tar -xvf otp_src_213..tar.gz / /
mkdir erlang // Create an Erlang directory in the specified directory, such as /usr/local
cd otp_src_213. // Switch to the decompressed directory
./configure --prefix=/usr/local/erlang // Compile (path based on actual situation)
make && make install / / installation
Copy the code
  1. configurationErlangEnvironment variables:
vim /etc/profile  // Edit environment variable files (default CentOS environment variable files, other systems may be different)
export PATH=$PATH:/usr/local/erlang/bin // Add environment variable configuration at the end (select path based on actual situation)
source /etc/profile // Take effect in real time
Copy the code
  1. The inputerlvalidationErlangCheck whether the installation is successful. If the following information is displayed, the installation is successful. (Enter the version numberhalt().Command to exit) :

  1. The installationRabbitMQ:
wget https:/ / dl.bintray.com/rabbitmq/all/rabbitmq-server/3.8.4/rabbitmq-server-generic-unix-3.8.4.tar.xz / / download RabbitMQ
xz -d rabbitmq-server-generic-unix-3.84..tar.xz / /
tar -xvf rabbitmq-server-generic-unix-3.84..tar / /
Copy the code
  1. Again, environment variables need to be configured here:
vim /etc/profile  // Edit environment variable files (default CentOS environment variable files, other systems may be different)
export PATH=$PATH:/usr/local/rabbitmq_server-3.84./sbin // Add environment variable configuration at the end (select path based on actual situation)
source /etc/profile // Take effect in real time
Copy the code
  1. Start theRabbitMQ, the default port is6752:
/usr/local/rabbitmq_server-3.84./sbin/./rabbitmq-server -detached  // Start in the background. Select the actual path or run the service or systemctl command to start the system
Copy the code
  1. If no error message is displayed, the startup is successful. After the startup, one is created by defaultguest/guestThe account can only be connected locally, so you need to create a new user, and give the new user authorization (of course, we can also give directlyguestUser authorization) :
./rabbitmqctl add_user admin 123456   // Create user admin
./rabbitmqctl set_user_tags admin administrator  // Add a label
./rabbitmqctl set_permissions -p / admin ". *" ". *" ". *"  / / authorization
Copy the code
  1. RabbitMQBy default, a visual management page is provided. You need to manually enable the page. The default port is15672:
./rabbitmq-plugins enable rabbitmq_management // Start the daemon plugin (disable if not)
Copy the code
  1. Once the plug-in is enabled, you can access:http://ip:15672/Access the background management system, and set some parameters, the account password is added aboveadmin/123456.

Common errors occur during installation

An error may occur during installation as shown in the following figure:

  1. Odbc :ODBC library-link check failed:

    Solution: Run the yum install unixodbc.x86_64 unixodbc-vel. X86_64 command to install unixodbc.x86_64.

  2. Wx :wxWidgets not found, wx will not be usable:

    Solution: This belongs to APPLOICATION INFORMATION and can not be processed.

  3. PDF files generated by placeholder PDF files, documentation: FOP is missing.

    Solution: Run the yum install fop.noarch command.

Implement a producer and consumer using the Java API

Next, implement a simple producer and consumer using Java native apis:

  1. pom.xmlThe file importRabbitMQClient dependencies:
 <dependency>
     <groupId>com.rabbitmq</groupId>
     <artifactId>amqp-client</artifactId>
     <version>5.6.0</version>
  </dependency>
Copy the code
  1. Create a new consumerTestRabbitConsumerClass:
package com.lonelyWolf.rabbitmq;

import com.rabbitmq.client.*;
import java.io.IOException;

public class TestRabbitConsumer {
    public static void main(String[] args) throws Exception{
        ConnectionFactory factory = new ConnectionFactory();
        factory.setUri("amqp://admin:123456@ip:5672");
        Connection conn = factory.newConnection();// Establish a connection
       
        Channel channel = conn.createChannel(); // Create a message channel

        channel.queueDeclare("TEST_QUEUE".false.false.false.null);// Declare a queue
        System.out.println("Waiting to receive message...");

        Consumer consumer = new DefaultConsumer(channel) {// Create a consumer
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties,byte[] body) throws IOException {
                System.out.println("Received a message:" + new String(body, "UTF-8") + ", the current message ID is: + properties.getMessageId());
                System.out.println("Received custom attribute:"+ properties.getHeaders().get("name")); }}; channel.basicConsume("TEST_QUEUE".true, consumer);// After consumption, callback to consumer}}Copy the code
  1. Create a new producerTestRabbitProducterClass:
package com.lonelyWolf.rabbitmq;

import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

public class TestRabbitProducter {
    public static void main(String[] args) throws Exception {
        ConnectionFactory factory = new ConnectionFactory();
        factory.setUri("amqp://admin:123456@ip:5672");
        Connection conn = factory.newConnection();// Establish a connection
        
        Channel channel = conn.createChannel();// Create a message channel
        Map<String, Object> headers = new HashMap<String, Object>(1);
        headers.put("name".The Twin Lone Wolves.);// You can customize some custom parameters to be sent with the message

        AMQP.BasicProperties properties = new AMQP.BasicProperties.Builder()
                .contentEncoding("UTF-8") / / code
                .headers(headers) // Custom attributes
                .messageId(String.valueOf(UUID.randomUUID()))/ / message id
                .build();

        String msg = "Hello, RabbitMQ";// Message that needs to be sent
        channel.queueDeclare("TEST_QUEUE".false.false.false.null); // Declare a queue
        channel.basicPublish(""."TEST_QUEUE", properties, msg.getBytes());// Send a messagechannel.close(); conn.close(); }}Copy the code
  1. Start the consumer first, after start the consumer will stay togetherRabbitMQWaiting for a message; After the message is sent, the consumer can receive the message:

Implement a producer and consumer with SpringBoot

Let’s see how SpringBoot integrates with RabbitMQ and implements a simple producer and consumer:

  1. Introducing dependencies (on my sideSpringBootUsing a2.4.0Version, so this version number also needs to be changed if you use a lower version) :
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-amqp</artifactId>
    <version>2.4.0</version>
</dependency>
Copy the code
  1. Added the following configuration files:
spring:
    rabbitmq:
        host: ip
        port: 5672
        username: admin
        password: 123456
Copy the code
  1. Create a configuration fileRabbitConfigClass to create a queue:
package com.lonely.wolf.rabbit.config;

import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class RabbitConfig {
    
    @Bean("simpleRabbitQueue")
    public Queue getFirstQueue(a){
        Queue queue = new Queue("SIMPLE_QUEUE");
        returnqueue; }}Copy the code
  1. Create a new consumerSimpleConsumerClass (note that the listening name is the same as defined above) :
package com.lonely.wolf.rabbit.consumer;

import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

@RabbitListener(queues = "SIMPLE_QUEUE")
@Component
public class SimpleConsumer {
    @RabbitHandler
    public void process(String msg){
        System.out.println("Received a message:"+ msg); }}Copy the code
  1. Create a new message senderHelloRabbitControllerClass (the name of the queue that sends the message must be the same as the name of the queue that the consumer listens to, otherwise the message cannot be received), after running, the corresponding interface is called, the consumer classSimpleConsumerYou can receive a message:
package com.lonely.wolf.rabbit.controller;

import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/hello")
public class HelloRabbitController {
    @Autowired
    private RabbitTemplate rabbitTemplate;

    @GetMapping(value="/send")
    public String clearVipInfo(@RequestParam(value = "msg",defaultValue = "no message") String msg){
        rabbitTemplate.convertAndSend("SIMPLE_QUEUE",msg);
        return "succ"; }}Copy the code

conclusion

This article gives a brief history of MQ, explains why MQ is used and what it solves, followed by a brief introduction to the AMQP 0.9.1 model. The AMQP model gives you a basic understanding of how RabbitMQ works. Finally, we introduce how to use RabbitMQ using the JAVA API and SpringBoot examples.