This series is the summary note for RabbitMQ In Action: Deploying Distributed Message Queues efficiently.

The previous article covered AMQP message communication, including queues, switches, and bindings. Virtual hosts can also isolate data and permissions, and message persistence and sender confirmation patterns ensure that messages are not lost.

This article will show you how to run and manage RabbitMQ, with a DEMO showing how to send and receive messages to give you a better understanding of the elements of the AMQP and to use as a source of data for monitoring.

Through introduction, you will learn:

  • Message sending and receiving simple implementation
  • Server management – Start and stop nodes
  • Access configuration
  • The use of statistical

Welfare portal: Small love speaker F code

Message sending and receiving simple implementation

The Demo is designed to collect logs. The message sender is the application subsystem and the message receiver is the log collection service. This can be easily implemented using RabbitMQ.

Implemented based on the Spring Boot framework, the main functions of classes are as follows:

  • LogRabbitConfig: create queue, switch, bind and other initialization operations;
  • Sender: message Sender;
  • AllReceiver: indicates the receiver of logs of all levels.
  • ErrorReceiver indicates the receiver of logs of the error level. Only logs of the error level are received.
  • LogSenderTest: test case class;

The message model is as follows:

configuration

First, configure spring Boot and RabbitMQ dependencies:

<parent>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-parent</artifactId>
	<version>2.0.1. RELEASE</version>
	<relativePath/>
</parent>
<dependencies>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter</artifactId>
	</dependency>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-test</artifactId>
		<scope>test</scope>
	</dependency>
	<! - the rabbitmq dependence - >
	<dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-amqp</artifactId>
    </dependency>
</dependencies>
Copy the code

Then configure the RabbitMQ address in the application.properties file:

Spring. The rabbitmq. Host = 127.0.0.1 spring. The rabbitmq. Port = 5672 spring. The rabbitmq. Username = guest spring. The rabbitmq. Password = guest spring.rabbitmq.publisher-confirms=true spring.rabbitmq.virtual-host=/Copy the code
LogRabbitConfig implementation

Use Spring’s @Configuration to define a Configuration class that replaces an XML Configuration file. The annotated class contains one or more @Bean-annotated methods for building the Bean definition and initializing the Spring container.

@Configuration
public class LogRabbitConfig {
    final static String QUEUE_LOG_ERROR = "log.error";
    final static String QUEUE_LOG_ALL = "log.all";

    // Create log.error queue
    @Bean
    public Queue logError(a) {
        return new Queue(QUEUE_LOG_ERROR);
    }
    // Create log.all queue
    @Bean
    public Queue logAll(a) {
        return new Queue(QUEUE_LOG_ALL);
    }
    // Create exchange and name it log
    @Bean
    TopicExchange exchange(a) {
        return new TopicExchange("log");
    }
    // Bind the log.error queue to exchange, routingkey to log.error
    @Bean
    Binding bindingExchangeError(Queue logError, TopicExchange exchange) {
        return BindingBuilder.bind(logError).to(exchange).with("log.error");
    }
    // Bind log.all queue to exchange, routingkey to log.#
    @Bean
    Binding bindingExchangeAll(Queue logAll, TopicExchange exchange) {
        return BindingBuilder.bind(logAll).to(exchange).with("log.#"); }}Copy the code
Sender to realize

Each subsystem sends a message to the RabbitMQ server:

@Component
public class Sender {
    @Autowired
    private AmqpTemplate rabbitTemplate;
    
    public void send(a) {
        // Send a message to the MQ server, exchange as log, routingKey as log.error
        String context = "error log";
        this.rabbitTemplate.convertAndSend("log"."log.error", context);

        // Send a message to the MQ server, exchange as log, routingKey as log.info
        context = "info log";
        System.out.println("send msg : " + context);
        this.rabbitTemplate.convertAndSend("log"."log.info", context);

        // Send messages to the MQ server with Exchange as log and routingKey as log.warn
        context = "warn log";
        System.out.println("send msg : " + context);
        this.rabbitTemplate.convertAndSend("log"."log.warn", context); }}Copy the code
AllReceiver and ErrorReceiver implementations

Receive messages from the RabbitMQ server.

AllReceiver gets messages from the log.all queue on the server and, since it is bound to a Routingkey of “log.#”, receives all levels of logs:

@Component
@RabbitListener(queues = "log.all")
public class AllReceiver {
    @RabbitHandler
    public void process(String context) {
        System.out.println("receive log : "+ context); }}Copy the code

ErrorReceiver gets messages from the log.error queue on the server and, since it is bound to a Routingkey of “log.error”, only error-level logs are received:

@Component
@RabbitListener(queues = "log.error")
public class ErrorReceiver {
    @RabbitHandler
    public void process(String context) {
        System.out.println("receive error : "+ context); }}Copy the code
LogSenderTest Test case

The test case is simple, just call the Sender to send the message and observe how the message is received.

@RunWith(SpringRunner.class)
@SpringBootTest
@SpringBootApplication
public class LogSenderTest {
    @Autowired
    Sender sender;

    @Test
    public void sendLog(a) { sender.send(); }}Copy the code

Run logs are as follows:

As you can see, error was received twice, indicating that exchange was sent to both log.all and log.error queues, and other levels of logs were sent to log.all queues.

Server management – Start and stop nodes

RabbitMQ is written in Erlang, which inherently allows applications to communicate with each other without knowing whether they are on the same machine, making clustering and reliable message routing easy.

Understand nodes and Erlang applications

Just as Java has JVM virtual machines, Erlang has virtual machines, and each instance of the virtual machine is called a “node.” The difference is that multiple Erlang applications can run on the same node, and if the application crashes, the Erlang node automatically tries to restart the application automatically.

Node operations:

Background start node:./ rabbitmq-server-detached Stop node:./rabbitmqctl stop Stop rabbit application only:./rabbitmqctl stop_appCopy the code
The configuration file

The format of the configuration file is essentially the original Erlang data structure, which is an array containing nested hash tables, as follows:

[[mnesia, [{dump_log_write_threshold, 1000}]], [Rabbit, [{vm_memory_high_wateremark, 0.4}]]]Copy the code

There are two applications configured above, each with its own hash table to configure options:

  • Mnesia: is used by RabbitMQ to store switch and queue metadata;
  • Rabbit: is a rabbitMq-specific configuration option.

If each application has multiple options, separate them with commas.

Access configuration

RabbitMQ permission system, a single user can be authorized across multiple vhosts, and can authorize read, write, and configuration separately.

First create a user named dongqingqing with the password 123456:

./rabbitmqctl add_user dongqingqing 123456
Copy the code

Grant dongqingqing user permission to read all queues and switches, write only log.* queues and switches, cannot create or delete queues and switches

./rabbitmqctl set_permissions  dongqingqing ".*" "log.*" "" 
Copy the code

The parameters after set_permissions are user name, read permission, write permission, and configuration permission respectively.

See the documentation for other detailed uses.

The use of statistical

Viewing statistics

You can use the rabbitmqctl command to view data statistics, such as the number of queues and messages, switches and bindings.

Check all queues, including log.all and log.error as defined by the demo above:

View all switches, including the logs defined by the demo above

In addition, RabbitMQ provides a management interface plug-in to make it easier to view statistics. This can be enabled by using the following command:

sudo ./rabbitmq-plugins enable rabbitmq_management
Copy the code

See the log

You can view the logs on the file system, and when rabbitMQ is started, the log path is displayed:

In addition, real-time log information can be obtained via AMQP, there is a topic switch to amq.rabbitmq.log, listening to the corresponding queue.

The next article will cover messaging communication patterns and best practices. Thank you for your continued attention.

Please scan the qr code below and follow my personal wechat official account ~