Difference between revisions of "RabbitMQ"

(Create New RabbitMQ User)
Line 95: Line 95:
  
 
**Note: You can also create new user from RabbitMQ management webpage
 
**Note: You can also create new user from RabbitMQ management webpage
 +
 +
 +
=Tutorial=
 +
==Messaging with RabbitMQ(SpringBoot + Gradle)==
 +
===Create a RabbitMQ message receiver===
 +
With any messaging-based application, you need to create a receiver that will respond to published messages.
 +
 +
'''src/main/java/hello/Receiver.java'''
 +
<source>
 +
package hello;
 +
 +
import java.util.concurrent.CountDownLatch;
 +
import org.springframework.stereotype.Component;
 +
 +
@Component
 +
public class Receiver {
 +
 +
    private CountDownLatch latch = new CountDownLatch(1);
 +
 +
    public void receiveMessage(String message) {
 +
        System.out.println("Received <" + message + ">");
 +
        latch.countDown();
 +
    }
 +
 +
    public CountDownLatch getLatch() {
 +
        return latch;
 +
    }
 +
 +
}
 +
</source>
 +
 +
The Receiver is a simple POJO that defines a method for receiving messages. When you register it to receive messages, you can name it anything you want.
 +
 +
'''Note:''' For convenience, this POJO also has a CountDownLatch. This allows it to signal that the message is received. This is something you are not likely to implement in a production application.
 +
 +
===Register the listener and send a message===
 +
Spring AMQP’s RabbitTemplate provides everything you need to send and receive messages with RabbitMQ. Specifically, you need to configure:
 +
 +
*A message listener container
 +
*Declare the queue, the exchange, and the binding between them
 +
*A component to send some messages to test the listener
 +
 +
'''Note:''' Spring Boot automatically creates a connection factory and a RabbitTemplate, reducing the amount of code you have to write.
 +
 +
You’ll use RabbitTemplate to send messages, and you will register a Receiver with the message listener container to receive messages. The connection factory drives both, allowing them to connect to the RabbitMQ server.
 +
 +
src/main/java/hello/Application.java
 +
<source>
 +
package hello;
 +
 +
import org.springframework.amqp.core.Binding;
 +
import org.springframework.amqp.core.BindingBuilder;
 +
import org.springframework.amqp.core.Queue;
 +
import org.springframework.amqp.core.TopicExchange;
 +
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
 +
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
 +
import org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter;
 +
import org.springframework.boot.SpringApplication;
 +
import org.springframework.boot.autoconfigure.SpringBootApplication;
 +
import org.springframework.context.annotation.Bean;
 +
 +
@SpringBootApplication
 +
public class Application {
 +
 +
    static final String topicExchangeName = "spring-boot-exchange";
 +
 +
    static final String queueName = "spring-boot";
 +
 +
    @Bean
 +
    Queue queue() {
 +
        return new Queue(queueName, false);
 +
    }
 +
 +
    @Bean
 +
    TopicExchange exchange() {
 +
        return new TopicExchange(topicExchangeName);
 +
    }
 +
 +
    @Bean
 +
    Binding binding(Queue queue, TopicExchange exchange) {
 +
        return BindingBuilder.bind(queue).to(exchange).with("foo.bar.#");
 +
    }
 +
 +
    @Bean
 +
    SimpleMessageListenerContainer container(ConnectionFactory connectionFactory,
 +
            MessageListenerAdapter listenerAdapter) {
 +
        SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
 +
        container.setConnectionFactory(connectionFactory);
 +
        container.setQueueNames(queueName);
 +
        container.setMessageListener(listenerAdapter);
 +
        return container;
 +
    }
 +
 +
    @Bean
 +
    MessageListenerAdapter listenerAdapter(Receiver receiver) {
 +
        return new MessageListenerAdapter(receiver, "receiveMessage");
 +
    }
 +
 +
    public static void main(String[] args) throws InterruptedException {
 +
        SpringApplication.run(Application.class, args).close();
 +
    }
 +
 +
}
 +
</source>
 +
 +
@SpringBootApplication is a convenience annotation that adds all of the following:
 +
 +
*@Configuration tags the class as a source of bean definitions for the application context.
 +
 +
*@EnableAutoConfiguration tells Spring Boot to start adding beans based on classpath settings, other beans, and various property settings.
 +
 +
*Normally you would add @EnableWebMvc for a Spring MVC app, but Spring Boot adds it automatically when it sees spring-webmvc on the classpath. This flags the application as a web application and activates key behaviors such as setting up a DispatcherServlet.
 +
 +
*@ComponentScan tells Spring to look for other components, configurations, and services in the hello package, allowing it to find the controllers.
 +
 +
The main() method uses Spring Boot’s SpringApplication.run() method to launch an application. Did you notice that there wasn’t a single line of XML? No web.xml file either. This web application is 100% pure Java and you didn’t have to deal with configuring any plumbing or infrastructure.
 +
 +
The bean defined in the listenerAdapter() method is registered as a message listener in the container defined in container(). It will listen for messages on the "spring-boot" queue. Because the Receiver class is a POJO, it needs to be wrapped in the MessageListenerAdapter, where you specify it to invoke receiveMessage.
 +
 +
 +
Note: JMS queues and AMQP queues have different semantics. For example, JMS sends queued messages to only one consumer. While AMQP queues do the same thing, AMQP producers don’t send messages directly to queues. Instead, a message is sent to an exchange, which can go to a single queue, or fanout to multiple queues, emulating the concept of JMS topics. For more, see [https://spring.io/understanding/AMQP Understanding AMQP].
 +
 +
 +
The message listener container and receiver beans are all you need to listen for messages. To send a message, you also need a Rabbit template.
 +
 +
The '''queue()''' method creates an AMQP queue. The '''exchange()''' method creates a topic exchange. The '''binding()''' method binds these two together, defining the behavior that occurs when RabbitTemplate publishes to an exchange.
 +
 +
'''Note:''' Spring AMQP requires that the Queue, the TopicExchange, and the Binding be declared as top level Spring beans in order to be set up properly.
 +
 +
In this case, we use a topic exchange and the queue is bound with routing key foo.bar.# which means any message sent with a routing key beginning with foo.bar. will be routed to the queue.
 +
 +
===Send a Test Message===
 +
Test messages are sent by a CommandLineRunner, which also waits for the latch in the receiver and closes the application context:
 +
 +
src/main/java/hello/Runner.java
 +
 +
<source>
 +
package hello;
 +
 +
import java.util.concurrent.TimeUnit;
 +
 +
import org.springframework.amqp.rabbit.core.RabbitTemplate;
 +
import org.springframework.boot.CommandLineRunner;
 +
import org.springframework.stereotype.Component;
 +
 +
@Component
 +
public class Runner implements CommandLineRunner {
 +
 +
    private final RabbitTemplate rabbitTemplate;
 +
    private final Receiver receiver;
 +
 +
    public Runner(Receiver receiver, RabbitTemplate rabbitTemplate) {
 +
        this.receiver = receiver;
 +
        this.rabbitTemplate = rabbitTemplate;
 +
    }
 +
 +
    @Override
 +
    public void run(String... args) throws Exception {
 +
        System.out.println("Sending message...");
 +
        rabbitTemplate.convertAndSend(Application.topicExchangeName, "foo.bar.baz", "Hello from RabbitMQ!");
 +
        receiver.getLatch().await(10000, TimeUnit.MILLISECONDS);
 +
    }
 +
 +
}
 +
 +
</source>
 +
 +
Notice that the template routes the message to the exchange, with a routing key of foo.bar.baz which matches the binding.
 +
 +
The runner can be mocked out in tests, so that the receiver can be tested in isolation.
 +
 +
source: https://spring.io/guides/gs/messaging-rabbitmq/
 +
 +
===Run the Application===
 +
The main() method starts that process by creating a Spring application context. This starts the message listener container, which will start listening for messages. There is a Runner bean which is then automatically executed: it retrieves the RabbitTemplate from the application context and sends a "Hello from RabbitMQ!" message on the "spring-boot" queue. Finally, it closes the Spring application context and the application ends.
 +
  
 
source: https://www.rabbitmq.com/install-standalone-mac.html
 
source: https://www.rabbitmq.com/install-standalone-mac.html

Revision as of 06:03, 28 August 2018

Installing on Mac

Dependencies

This package requires OpenSSL 1.0.x installed. We strongly recommend doing this via Homebrew to avoid possible issues with dynamic library paths.

Installation with Homebrew

Possibly the easiest way to use this package is via Homebrew. It will automatically install the OpenSSL formula mentioned above:

brew install rabbitmq

Run RabbitMQ Server

Overview

Unlike some other installation methods, namely the Debian and RPM packages, RabbitMQ generic UNIX binary build does not require sudo. It can be uncompressed into any location and started and managed using the tools under sbin. Default data directory location will be under ./var, that is, in the installation directory.

Start the Server

To start the server, run the sbin/rabbitmq-server script. This displays a short banner message, concluding with the message "completed with [n] plugins.", indicating that the RabbitMQ broker has been started successfully.

$ /usr/local/sbin/rabbitmq-server

To start the server in "detached" mode, use rabbitmq-server -detached. This will run the node process in the background.

Configure the Server

It is possible to customise the RabbitMQ environment by setting environment variables in $RABBITMQ_HOME/etc/rabbitmq/rabbitmq-env.conf. Server components may be configured, too, in the RabbitMQ configuration file located at $RABBITMQ_HOME/etc/rabbitmq/rabbitmq.config. Neither of these files exist after installation.

File Locations

The Generic Unix tarball is designed as far as possible to run without requiring configuration changes or special permissions. The directories and files used by default are all held under the installation directory rabbitmq_server-3.7.7 which is in the $RABBITMQ_HOME variable in the scripts.

Should you wish to install RabbitMQ Server such that it uses the conventional system directories for configuration, database, log files, plugins etc, it is possible to do this.

Find the line:

SYS_PREFIX=${RABBITMQ_HOME}

in the sbin/rabbitmq-defaults script and change this line to:

SYS_PREFIX=

but do not modify any other line in this script.

Note: After this modification the default directory locations may require different permissions. In particular RABBITMQ_MNESIA_BASE and RABBITMQ_LOG_BASE may need to be created (the server will attempt to create them at startup), and the RABBITMQ_ENABLED_PLUGINS_FILE will need to be writable (for rabbitmq-plugins). The configuration files will be looked for in /etc/rabbitmq/.

Default user access

The broker creates a user guest with password guest. Unconfigured clients will in general use these credentials. By default, these credentials can only be used when connecting to the broker as localhost so you will need to take action before connecting from any other machine.

See the documentation on access control for information on how to create more users, delete the guest user, or allow remote access to the guest user.

Managing the Broker

To stop the server or check its status, etc., you can invoke sbin/rabbitmqctl (as the user running rabbitmq-server). All rabbitmqctl commands will report the node absence if no broker is running.

to start server:

sbin/rabbitmq-server

Invoke rabbitmqctl stop to stop the server.

rabbitmqctl stop

Invoke rabbitmqctl status to check whether it is running.

rabbitmqctl status

The RabbitMQ Management's Web Page

http://localhost:15672

Create New RabbitMQ User

Mac/Linux Terminal

rabbitmqctl add_user test test
rabbitmqctl set_user_tags test administrator
rabbitmqctl set_permissions -p / test ".*" ".*" ".*"

Test New User

curl -i -u test:test http://localhost:15672/api/whoami

Note: for the above one to work we need to enable the management plugin

rabbitmq-plugins enable rabbitmq_management


    • Note: You can also create new user from RabbitMQ management webpage


Tutorial

Messaging with RabbitMQ(SpringBoot + Gradle)

Create a RabbitMQ message receiver

With any messaging-based application, you need to create a receiver that will respond to published messages.

src/main/java/hello/Receiver.java

package hello;

import java.util.concurrent.CountDownLatch;
import org.springframework.stereotype.Component;

@Component
public class Receiver {

    private CountDownLatch latch = new CountDownLatch(1);

    public void receiveMessage(String message) {
        System.out.println("Received <" + message + ">");
        latch.countDown();
    }

    public CountDownLatch getLatch() {
        return latch;
    }

}

The Receiver is a simple POJO that defines a method for receiving messages. When you register it to receive messages, you can name it anything you want.

Note: For convenience, this POJO also has a CountDownLatch. This allows it to signal that the message is received. This is something you are not likely to implement in a production application.

Register the listener and send a message

Spring AMQP’s RabbitTemplate provides everything you need to send and receive messages with RabbitMQ. Specifically, you need to configure:

  • A message listener container
  • Declare the queue, the exchange, and the binding between them
  • A component to send some messages to test the listener

Note: Spring Boot automatically creates a connection factory and a RabbitTemplate, reducing the amount of code you have to write.

You’ll use RabbitTemplate to send messages, and you will register a Receiver with the message listener container to receive messages. The connection factory drives both, allowing them to connect to the RabbitMQ server.

src/main/java/hello/Application.java

package hello;

import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
public class Application {

    static final String topicExchangeName = "spring-boot-exchange";

    static final String queueName = "spring-boot";

    @Bean
    Queue queue() {
        return new Queue(queueName, false);
    }

    @Bean
    TopicExchange exchange() {
        return new TopicExchange(topicExchangeName);
    }

    @Bean
    Binding binding(Queue queue, TopicExchange exchange) {
        return BindingBuilder.bind(queue).to(exchange).with("foo.bar.#");
    }

    @Bean
    SimpleMessageListenerContainer container(ConnectionFactory connectionFactory,
            MessageListenerAdapter listenerAdapter) {
        SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
        container.setConnectionFactory(connectionFactory);
        container.setQueueNames(queueName);
        container.setMessageListener(listenerAdapter);
        return container;
    }

    @Bean
    MessageListenerAdapter listenerAdapter(Receiver receiver) {
        return new MessageListenerAdapter(receiver, "receiveMessage");
    }

    public static void main(String[] args) throws InterruptedException {
        SpringApplication.run(Application.class, args).close();
    }

}

@SpringBootApplication is a convenience annotation that adds all of the following:

  • @Configuration tags the class as a source of bean definitions for the application context.
  • @EnableAutoConfiguration tells Spring Boot to start adding beans based on classpath settings, other beans, and various property settings.
  • Normally you would add @EnableWebMvc for a Spring MVC app, but Spring Boot adds it automatically when it sees spring-webmvc on the classpath. This flags the application as a web application and activates key behaviors such as setting up a DispatcherServlet.
  • @ComponentScan tells Spring to look for other components, configurations, and services in the hello package, allowing it to find the controllers.

The main() method uses Spring Boot’s SpringApplication.run() method to launch an application. Did you notice that there wasn’t a single line of XML? No web.xml file either. This web application is 100% pure Java and you didn’t have to deal with configuring any plumbing or infrastructure.

The bean defined in the listenerAdapter() method is registered as a message listener in the container defined in container(). It will listen for messages on the "spring-boot" queue. Because the Receiver class is a POJO, it needs to be wrapped in the MessageListenerAdapter, where you specify it to invoke receiveMessage.


Note: JMS queues and AMQP queues have different semantics. For example, JMS sends queued messages to only one consumer. While AMQP queues do the same thing, AMQP producers don’t send messages directly to queues. Instead, a message is sent to an exchange, which can go to a single queue, or fanout to multiple queues, emulating the concept of JMS topics. For more, see Understanding AMQP.


The message listener container and receiver beans are all you need to listen for messages. To send a message, you also need a Rabbit template.

The queue() method creates an AMQP queue. The exchange() method creates a topic exchange. The binding() method binds these two together, defining the behavior that occurs when RabbitTemplate publishes to an exchange.

Note: Spring AMQP requires that the Queue, the TopicExchange, and the Binding be declared as top level Spring beans in order to be set up properly.

In this case, we use a topic exchange and the queue is bound with routing key foo.bar.# which means any message sent with a routing key beginning with foo.bar. will be routed to the queue.

Send a Test Message

Test messages are sent by a CommandLineRunner, which also waits for the latch in the receiver and closes the application context:

src/main/java/hello/Runner.java

package hello;

import java.util.concurrent.TimeUnit;

import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

@Component
public class Runner implements CommandLineRunner {

    private final RabbitTemplate rabbitTemplate;
    private final Receiver receiver;

    public Runner(Receiver receiver, RabbitTemplate rabbitTemplate) {
        this.receiver = receiver;
        this.rabbitTemplate = rabbitTemplate;
    }

    @Override
    public void run(String... args) throws Exception {
        System.out.println("Sending message...");
        rabbitTemplate.convertAndSend(Application.topicExchangeName, "foo.bar.baz", "Hello from RabbitMQ!");
        receiver.getLatch().await(10000, TimeUnit.MILLISECONDS);
    }

}

Notice that the template routes the message to the exchange, with a routing key of foo.bar.baz which matches the binding.

The runner can be mocked out in tests, so that the receiver can be tested in isolation.

source: https://spring.io/guides/gs/messaging-rabbitmq/

Run the Application

The main() method starts that process by creating a Spring application context. This starts the message listener container, which will start listening for messages. There is a Runner bean which is then automatically executed: it retrieves the RabbitTemplate from the application context and sends a "Hello from RabbitMQ!" message on the "spring-boot" queue. Finally, it closes the Spring application context and the application ends.


source: https://www.rabbitmq.com/install-standalone-mac.html