RabbitMQ使用
安装
使用docker一步到位
Java客户端使用
首先导入依赖:amqp-client-5.7.1.jar
连接工具类
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
/*
*@Info :
*@Author:ZuoBro
*@FileName:
*@Date: 2020/12/6
*/
public class RabbitMqConnectionUtil {
/**
* 获取RabbitMQ连接
* @return
* @throws TimeoutException
* @throws IOException
*/
public static Connection getConnection() throws TimeoutException, IOException {
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("localhost");
connectionFactory.setUsername("user");
connectionFactory.setPassword("password");
return connectionFactory.newConnection();
}
}
-
Channels(信道)
链接中的信道信息:Channel是在连接中存在的,一个Connection中可以有多个Channel。在Java代码中 通过连接来创建信道。 -
Exchanges(交换机)
Exchange作为消费的生产者和消息队列的一个中介,其将Producer生产的消息进行分发给消息队列。在没有使用交换机的简单模式中,实际上则使用的是默认的交换机(AMQP-Default) -
Queues(消息队列)
消息队列,在控制台页面中我们在queues页签中我们可以看到服务器端当前的消息队列信息。在java代码中我们需要先对消息队列进行声明后才可以使用。点击某一队列,在队列中我们也可以查看当前队列的消息信息。
6种队列模式
- 简单模式
- 工作队列模式Work Queue
- 发布/订阅模式Publish/Subscribe
- 路由模式Routing
- 通配符模式Topics
简单模式模式
Send.java
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import utils.RabbitMqConnectionUtil;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
public class Send {
private static final String QUEUE_NAME = "hello";
public static void main(String[] args) {
try {
Connection connection = RabbitMqConnectionUtil.getConnection();
Channel channel = connection.createChannel();
channel.queueDeclare(QUEUE_NAME,false,false,false,null);
int time = 1;
while (true) {
String message = String.format("Hello World%s!",time);
channel.basicPublish("", QUEUE_NAME, null, message.getBytes());
System.out.println(" [x] Sent '" + message + "'");
time ++;
if (time > 10) {
break;
}
Thread.sleep(2000);
}
System.out.println("结束发送");
channel.close();
connection.close();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
}
}
}
Reveiver.java
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.DeliverCallback;
import utils.RabbitMqConnectionUtil;
/**
* RabbitMQ简单模式 生产者-消费者
*/
public class Receiver {
private final static String QUEUE_NAME = "hello";
public static void main(String[] args) throws Exception {
Connection connection = RabbitMqConnectionUtil.getConnection();
Channel channel = connection.createChannel();
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
System.out.println(" [*] Waiting for messages. To exit press CTRL+C");
DeliverCallback deliverCallback = (consumerTag, delivery) -> {
String message = new String(delivery.getBody(), "UTF-8");
System.out.println(" [x] Received '" + message + "'");
};
// autoAck = true,会阻塞线程
channel.basicConsume(QUEUE_NAME, true, deliverCallback, consumerTag -> {});
}
}
在简单模式下,生产者发送消息到hello队列,消费者消费消息后从队列删除。
[x] Sent 'Hello World1!'
[x] Sent 'Hello World2!'
[x] Sent 'Hello World3!'
[x] Sent 'Hello World4!'
[x] Sent 'Hello World5!'
[x] Sent 'Hello World6!'
[x] Sent 'Hello World7!'
[x] Sent 'Hello World8!'
[x] Sent 'Hello World9!'
[x] Sent 'Hello World10!'
结束发送
[*] Waiting for messages. To exit press CTRL+C
[x] Received 'Hello World1!'
[x] Received 'Hello World2!'
[x] Received 'Hello World3!'
[x] Received 'Hello World4!'
[x] Received 'Hello World5!'
[x] Received 'Hello World6!'
[x] Received 'Hello World7!'
[x] Received 'Hello World8!'
[x] Received 'Hello World9!'
[x] Received 'Hello World10!'
路由模式
日志信息有这样的简单分类:error,warning,info
我们可能想将error单独处理,其他统一由另一个队列处理,此时我们就可以使用路由模式。
Send.java
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import utils.RabbitMqConnectionUtil;
/*
*@Info : 路由模式-直接交换
*@Author:ZuoBro
*@FileName:
*@Date: 2020/12/5
*/
public class Send {
private static final String EXCHANGE_NAME = "direct_logs";
public static void main(String[] args) throws Exception {
Connection connection = RabbitMqConnectionUtil.getConnection();
Channel channel = connection.createChannel();
// 声明交换机
channel.exchangeDeclare(EXCHANGE_NAME,"direct");
String[] routingKeys = new String[]{
"info",
"warning",
"error"
};
String[] messages = new String[]{
"This is an information!",
"This is a warning!",
"This is an error!"
};
for( int i = 0; i < 3; i++) {
channel.basicPublish(EXCHANGE_NAME,routingKeys[i],null,messages[i].getBytes());
System.out.println(String.format("[x] Sent: {type=%s} => { %s }",routingKeys[i],messages[i]));
}
}
}
Receiver1.java
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.DeliverCallback;
import utils.RabbitMqConnectionUtil;
public class Receiver1 {
/**
* 接收error
*/
private static final String EXCHANGE_NAME = "direct_logs";
public static void main(String[] args) throws Exception {
Connection connection = RabbitMqConnectionUtil.getConnection();
Channel channel = connection.createChannel();
// 声明交换机
channel.exchangeDeclare(EXCHANGE_NAME,"direct");
// 获取随机队列,非持久,排他,自动删除
String queueName = channel.queueDeclare().getQueue();
// 绑定交换机
channel.queueBind(queueName,EXCHANGE_NAME,"error");
DeliverCallback deliverCallback = (consumerTag, delivery) -> {
String message = new String(delivery.getBody());
System.out.println(String.format("[x-receiver-1] Received: {RoutingKey=%s} => { %s }",delivery.getEnvelope().getRoutingKey(),message));
};
channel.basicConsume(queueName,true,deliverCallback,consumerTag -> {});
}
}
Receiver2.java
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.DeliverCallback;
import utils.RabbitMqConnectionUtil;
public class Receiver2 {
/**
* 接收info/warning/error
*/
private static final String EXCHANGE_NAME = "direct_logs";
public static void main(String[] args) throws Exception {
Connection connection = RabbitMqConnectionUtil.getConnection();
Channel channel = connection.createChannel();
// 声明交换机
channel.exchangeDeclare(EXCHANGE_NAME,"direct");
// 获取随机队列,非持久,排他,自动删除
String queueName = channel.queueDeclare().getQueue();
// 绑定交换机
channel.queueBind(queueName,EXCHANGE_NAME,"info");
channel.queueBind(queueName,EXCHANGE_NAME,"warning");
channel.queueBind(queueName,EXCHANGE_NAME,"error");
DeliverCallback deliverCallback = (consumerTag, delivery) -> {
String message = new String(delivery.getBody());
System.out.println(String.format("[x-receiver-2] Received: {RoutingKey=%s} => { %s }",delivery.getEnvelope().getRoutingKey(),message));
};
channel.basicConsume(queueName,true,deliverCallback,consumerTag -> {});
}
}
结果:
********* Send **************
[x] Sent: {type=info} => { This is an information! }
[x] Sent: {type=warning} => { This is a warning! }
[x] Sent: {type=error} => { This is an error! }
********Receiver1*************
[x-receiver-1] Received: {RoutingKey=error} => { This is an error! }
********Receiver2*************
[x-receiver-2] Received: {RoutingKey=info} => { This is an information! }
[x-receiver-2] Received: {RoutingKey=warning} => { This is a warning! }
[x-receiver-2] Received: {RoutingKey=error} => { This is an error! }