RabbitMQ
Contents
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.
Problem & Solution
ERROR: node with name "rabbit" already running on "localhost"
Solution : The rabbitmq server was running somewhere but it just couldn't be connected to.
One of the following will mention something about rabbits:
$: ps aux | grep epmd
$: ps aux | grep erl
lsof -i :<portNumber> | grep LISTEN #port search
Kill the process with kill -9 {pid of rabbitmq process}
start rabbitmq:
/usr/local/sbin/rabbitmqctl start
#or first time
$ /usr/local/sbin/rabbitmq-server
source: https://www.rabbitmq.com/install-standalone-mac.html