Rabbitmq的六种工作模式(附代码)
简单模式
pom依赖
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.tedu</groupId>
<artifactId>rabbitmq</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>com.rabbitmq</groupId>
<artifactId>amqp-client</artifactId>
<version>5.4.3</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.8.0-alpha2</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.8.0-alpha2</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
生产者发送消息
package rabbitmq.simple;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
public class Sender {
//生产者
public static void main(String[] args) throws IOException, TimeoutException {
//链接rabbitmq服务器
ConnectionFactory f =new ConnectionFactory();
f.setHost("192.168.64.140");
f.setPort(5672);
f.setUsername("admin");
f.setPassword("admin");
//创建连接
Connection con = f.newConnection();
//建立通道
Channel c= con.createChannel();
/*
* 声明队列,会在rabbitmq中创建一个队列
* 如果已经创建过该队列,就不能再使用其他参数来创建
*
* 参数含义:
* -queue: 队列名称
* -durable: 队列持久化,true表示RabbitMQ重启后队列仍存在
* -exclusive: 排他,true表示限制仅当前连接可用
* -autoDelete: 当最后一个消费者断开后,是否删除队列
* -arguments: 其他参数
*/
c.queueDeclare("hellworld", false, false, false, null);
/*
* 发布消息
* 这里把消息向默认交换机发送.
* 默认交换机隐含与所有队列绑定,routing key即为队列名称
*
* 参数含义:
* -exchange: 交换机名称,空串表示默认交换机"(AMQP default)",不能用 null
* -routingKey: 对于默认交换机,路由键就是目标队列名称
* -props: 其他参数,例如头信息
* -body: 消息内容byte[]数组
*/
c.basicPublish("", "hellworld", null,
("hellworld"+System.currentTimeMillis()).getBytes());
System.out.println("消息已发送");
//断开连接
c.close();
con.close();
}
}
消费者接受消息
package rabbitmq.simple;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
import com.rabbitmq.client.CancelCallback;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.DeliverCallback;
import com.rabbitmq.client.Delivery;
public class Receive {
//消费者
public static void main(String[] args) throws IOException, TimeoutException {
//连接rabbitmq服务器
ConnectionFactory f = new ConnectionFactory();
f.setHost("192.168.64.140");
f.setPort(5672);
f.setUsername("admin");
f.setPassword("admin");
//建立连接
Connection con = f.newConnection();
//建立连接通道
Channel c = con.createChannel();
//声明队列定义队列
c.queueDeclare("hellworld", false, false, false, null);
//收到消息后用来处理消息的回调
DeliverCallback deliverCallback =new DeliverCallback() {
@Override
public void handle(String consumerTag, Delivery message) throws IOException {
byte[] a = message.getBody();
String s = new String(a);
System.out.println("消息已收到:"+ s);
}
};
//消费者取消时的回调函数
CancelCallback cancelCallback = new CancelCallback() {
@Override
public void handle(String consumerTag) throws IOException {
}
};
//开始消费消息
c.basicConsume("hellworld",true , deliverCallback,cancelCallback);
}
}
工作模式
生产者发送消息
package rabbitmq.workqueue;
import java.io.IOException;
import java.util.Scanner;
import java.util.concurrent.TimeoutException;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.MessageProperties;
public class Sender {
//生产者
public static void main(String[] args) throws IOException, TimeoutException {
//链接rabbitmq服务器
ConnectionFactory f =new ConnectionFactory();
f.setHost("192.168.64.140");
f.setPort(5672);
f.setUsername("admin");
f.setPassword("admin");
//创建连接
Connection con = f.newConnection();
//建立通道
Channel c= con.createChannel();
//声明队列
c.queueDeclare("hellworld", false, false, false, null);
while (true) {
System.out.println("输入:");
String s = new Scanner(System.in).nextLine();
//发送消息
c.basicPublish("", "hellworld", MessageProperties.PERSISTENT_TEXT_PLAIN,s.getBytes());
}
}
}
消费者接受消息
package rabbitmq.workqueue;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
import com.rabbitmq.client.CancelCallback;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.DeliverCallback;
import com.rabbitmq.client.Delivery;
public class Receive {
//消费者
public static void main(String[] args) throws IOException, TimeoutException {
//连接rabbitmq服务器
ConnectionFactory f = new ConnectionFactory();
f.setHost("192.168.64.140");
f.setPort(5672);
f.setUsername("admin");
f.setPassword("admin");
//建立连接
Connection con = f.newConnection();
//建立连接通道
Channel c = con.createChannel();
//声明队列定义队列
c.queueDeclare("hellworld", true, false, false, null);
//收到消息后用来处理消息的回调
DeliverCallback deliverCallback =new DeliverCallback() {
@Override
public void handle(String consumerTag, Delivery message) throws IOException {
String s = new String(message.getBody());
System.out.println("消息已收到:"+ s);
for (int i = 0; i < s.length(); i++) {
//每遇到一个.字符暂停一秒
if (s.charAt(i)=='.') {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
//手动ack操作,手动向服务器发送回执 false表示是否确认多条消息(否)
c.basicAck(message.getEnvelope().getDeliveryTag(), false);
System.out.println("消息处理结束---------------------\n");
}
};
//消费者取消时的回调函数
CancelCallback cancelCallback = new CancelCallback() {
@Override
public void handle(String consumerTag) throws IOException {
}
};
//设置每次只接受一条数据
c.basicQos(1);
//开始消费消息
//第二个参数true 自动ack false 手动ack
c.basicConsume("hellworld",false , deliverCallback,cancelCallback);
}
}
合理分发
- 手动 ack
c.basicConsume(“队列”, false, …)
c.basicAck(消息标签, false)
qos=1, 每次只接收处理一条消息 - 一条消息处理完成之前,不接收下一条消息
c.basicQos(1) - 持久化
队列持久化: c.queueDeclare(“队列名”, true, …)
消息持久化: c.basicPublish("", “队列名”, MessageProperties.PERSISTENT_TEXT_PLAIN, 消息)
发布订阅模式
Exchanges 交换机
有几种可用的交换类型:direct、topic、header和fanout。我们将关注最后一个——fanout。让我们创建一个这种类型的交换机,并称之为 logs: ch.exchangeDeclare(“logs”, “fanout”);
fanout交换机非常简单。它只是将接收到的所有消息广播给它所知道的所有队列。这正是我们的日志系统所需要的。
fanout交换机
生产者
package rabbitmq.publishsubscribe;
import java.util.Scanner;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
public class Sender {
//fanout交换机
public static void main(String[] args) throws Exception {
//建立连接
ConnectionFactory f = new ConnectionFactory();
f.setHost("192.168.64.140");
f.setPort(5672);
f.setUsername("admin");
f.setPassword("admin");
//创建链接
Connection con = f.newConnection();
//建立通道
Channel c = con.createChannel();
//定义fanout类型的交换机,注意现在的生产者不定义队列
//rabbitmq服务器中,如果交换机不存在则新建 反之,空操作
c.exchangeDeclare("logs", "fanout");
//向交换机发送数据
while (true) {
System.out.println("输入:");
String msg = new Scanner(System.in).nextLine();
/**
* 参数:1.交换机 2.指定队列,指定任何对列名无效
* 3.其他参数 4.消息
*/
c.basicPublish("logs", "", null, msg.getBytes());
}
}
}
消费者
package rabbitmq.publishsubscribe;
import java.io.IOException;
import com.rabbitmq.client.CancelCallback;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.DeliverCallback;
import com.rabbitmq.client.Delivery;
public class Receive {
public static void main(String[] args) throws Exception{
//建立连接
ConnectionFactory f = new ConnectionFactory();
f.setHost("192.168.64.140");
f.setPort(5672);
f.setUsername("admin");
f.setPassword("admin");
//创建链接
Connection con = f.newConnection();
//建立通道
Channel c = con.createChannel();
//1.定义队列 fanout类型的队列 随机命名,非持久,独占,自动删除
String queue = c.queueDeclare().getQueue();
//2.定义交换机
c.exchangeDeclare("logs", "fanout");
//3.绑定
c.queueBind(queue, "logs", "");//发布订阅模式中第三个参数无效
DeliverCallback deliverCallback = new DeliverCallback() {
@Override
public void handle(String consumerTag, Delivery message) throws IOException {
String msg = new String(message.getBody());
System.out.println("收到:"+msg);
}
};
CancelCallback cancelCallback = new CancelCallback() {
@Override
public void handle(String consumerTag) throws IOException {
}
};
//消费数据
c.basicConsume(queue, true, deliverCallback, cancelCallback);
}
}
路由模式
直连交换机 Direct exchange
生产者
package rabbitmq.route;
import java.util.Scanner;
import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
public class Sender {
//路由模式
//直连交换机
public static void main(String[] args) throws Exception{
//建立连接
ConnectionFactory f = new ConnectionFactory();
f.setHost("192.168.64.140");
f.setPort(5672);
f.setUsername("admin");
f.setPassword("admin");
//创建链接
Connection con = f.newConnection();
//建立通道
Channel c = con.createChannel();
//定义交换机
c.exchangeDeclare("direct-logs", BuiltinExchangeType.DIRECT);
//发送消息
while (true) {
System.out.println("输入消息:");
String msg = new Scanner(System.in).nextLine();
System.out.println("输入key:");
String key = new Scanner(System.in).nextLine();
c.basicPublish("direct-logs", key, null, msg.getBytes());
}
}
}
消费者
package rabbitmq.route;
import java.io.IOException;
import java.util.Scanner;
import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.CancelCallback;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.DeliverCallback;
import com.rabbitmq.client.Delivery;
public class Receive {
public static void main(String[] args) throws Exception{
//建立连接
ConnectionFactory f = new ConnectionFactory();
f.setHost("192.168.64.140");
f.setPort(5672);
f.setUsername("admin");
f.setPassword("admin");
//创建链接
Connection con = f.newConnection();
//建立通道
Channel c = con.createChannel();
//定义队列
String queue = c.queueDeclare().getQueue();
//定义交换机
c.exchangeDeclare("direct-logs", BuiltinExchangeType.DIRECT);
//绑定
System.out.println("输入绑定建,用空格隔开: ");
String s = new Scanner(System.in).nextLine();
String[] b = s.split("\\s+");
for (String key : b) {
c.queueBind(queue, "direct-logs", key);
}
DeliverCallback deliverCallback = new DeliverCallback() {
@Override
public void handle(String consumerTag, Delivery message) throws IOException {
String msg = new String(message.getBody());
String key = message.getEnvelope().getRoutingKey();
System.out.println(key + "-" + msg);
}
};
CancelCallback cancelCallback = new CancelCallback() {
@Override
public void handle(String consumerTag) throws IOException {
}
};
c.basicConsume(queue, true, deliverCallback, cancelCallback);
}
}
主题模式
主题交换机 Topic exchange
- 使用* 可以通配单个单词。
- 使用# 可以通配零个或多个单词。
生产者
package rabbitmq.topic;
import java.util.Scanner;
import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
public class Sender {
//主题模式(topic)
public static void main(String[] args) throws Exception{
//建立连接
ConnectionFactory f = new ConnectionFactory();
f.setHost("192.168.64.140");
f.setPort(5672);
f.setUsername("admin");
f.setPassword("admin");
//创建链接
Connection con = f.newConnection();
//建立通道
Channel c = con.createChannel();
//定义交换机
c.exchangeDeclare("topic-logs", BuiltinExchangeType.TOPIC);
while (true) {
System.out.println("输入消息:");
String msg = new Scanner(System.in).next();
System.out.println("输入key:");
String key = new Scanner(System.in).next();
c.basicPublish("topic-logs", key, null, msg.getBytes());
}
}
}
消费者
package rabbitmq.topic;
import java.io.IOException;
import java.util.Scanner;
import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.CancelCallback;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.DeliverCallback;
import com.rabbitmq.client.Delivery;
public class Receive {
public static void main(String[] args) throws Exception{
//建立连接
ConnectionFactory f = new ConnectionFactory();
f.setHost("192.168.64.140");
f.setPort(5672);
f.setUsername("admin");
f.setPassword("admin");
//创建链接
Connection con = f.newConnection();
//建立通道
Channel c = con.createChannel();
//定义交换机
c.exchangeDeclare("topic-logs", BuiltinExchangeType.TOPIC);
//定义队列
String queue = c.queueDeclare().getQueue();
//绑定
System.out.println("获取绑定建,用空格隔开:");
String s = new Scanner(System.in).nextLine();
String[] b = s.split("\\s+");
for (String key : b) {
c.queueBind(queue, "topic-logs", key);
}
DeliverCallback deliverCallback = new DeliverCallback() {
@Override
public void handle(String consumerTag, Delivery message) throws IOException {
String msg = new String(message.getBody());
String key = message.getEnvelope().getRoutingKey();
System.out.println(key + "-" +msg);
}
};
CancelCallback cancelCallback = new CancelCallback() {
@Override
public void handle(String consumerTag) throws IOException {
// TODO Auto-generated method stub
}
};
c.basicConsume(queue, true, deliverCallback, cancelCallback);
}
}
RPC模式
RPC的工作方式:
- 对于RPC请求,客户端发送一条带有两个属性的消息:replyTo,设置为仅为请求创建的匿名独占队列,和correlationId,设置为每个请求的惟一id值。
- 请求被发送到rpc_queue队列
- RPC工作进程(即:服务器)在队列上等待请求。当一个请求出现时,它执行任务,并使用replyTo字段中的队列将结果发回客户机
- 客户机在回应消息队列上等待数据。当消息出现时,它检查correlationId属性。如果匹配请求中的值,则向程序返回该响应数据
服务端
package rabbitmq.rpc;
import java.io.IOException;
import com.rabbitmq.client.AMQP.BasicProperties;
import com.rabbitmq.client.CancelCallback;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.DeliverCallback;
import com.rabbitmq.client.Delivery;
public class RPCServer {
public static void main(String[] args) throws Exception{
//建立连接
ConnectionFactory f = new ConnectionFactory();
f.setHost("192.168.64.140");
f.setPort(5672);
f.setUsername("admin");
f.setPassword("admin");
//创建链接
Connection con = f.newConnection();
//建立通道
Channel c = con.createChannel();
//1.接收调用信息
//2.执行业务运算
//3.吧结果发回去
//定义队列
c.queueDeclare("rpc_queue", false, false, false, null);
DeliverCallback deliverCallback = new DeliverCallback() {
@Override
public void handle(String consumerTag, Delivery message) throws IOException {
String s = new String(message.getBody());
int n = Integer.parseInt(s);
//求第N个斐波那契数
long r =fbnq(n);
//去出返回队列名和关联id
//replyTo返回队列名
String replyTo = message.getProperties().getReplyTo();
String correlationId = message.getProperties().getCorrelationId();
//将correlationId放置BasicProperties属性
BasicProperties props = new BasicProperties().builder().correlationId(correlationId).build();
c.basicPublish("", replyTo, props, (""+r).getBytes());
}
};
CancelCallback cancelCallback = new CancelCallback() {
@Override
public void handle(String consumerTag) throws IOException {
}
};
c.basicConsume("rpc_queue", true, deliverCallback, cancelCallback);
}
//求第n个斐波那契数
//1,1,2,3,5,8.....
static long fbnq(int n) {
if (n == 1 || n == 2) {
return 1;
}
return fbnq(n-1)+fbnq(n-2);
}
}
客户端
package rabbitmq.rpc;
import java.io.IOException;
import java.util.Scanner;
import java.util.UUID;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeoutException;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.DeliverCallback;
import com.rabbitmq.client.Delivery;
import com.rabbitmq.client.AMQP.BasicProperties;
import com.rabbitmq.client.CancelCallback;
public class RPCClient {
public static BlockingQueue<Long> q =new ArrayBlockingQueue<>(10);
public static void main(String[] args) throws Exception{
System.out.println("求第几个斐波那契数:");
int n = new Scanner(System.in).nextInt();
long r = fbnq(n);
System.out.println(r);
}
public static long fbnq(int n) throws Exception {
//建立连接
ConnectionFactory f = new ConnectionFactory();
f.setHost("192.168.64.140");
f.setPort(5672);
f.setUsername("admin");
f.setPassword("admin");
//创建链接
Connection con = f.newConnection();
//建立通道
Channel c = con.createChannel();
//1.发送调用信息
c.queueDeclare("rpc_queue", false, false, false, null);
//返回队列名和关联id
String replyTo = c.queueDeclare().getQueue();
String correlationId = UUID.randomUUID().toString();
//将返回队列名和关联id放置属性里面
BasicProperties props =
new BasicProperties()
.builder()
.replyTo(replyTo)
.correlationId(correlationId)
.build();
c.basicPublish("", "rpc_queue", props, (""+n).getBytes());
//2.模拟继续执行主线程其他运算
System.out.println("其他运算.........");
//3.直到取到结果时,返回结果
DeliverCallback deliverCallback = new DeliverCallback() {
@Override
public void handle(String consumerTag, Delivery message) throws IOException {
//返回的斐波那契数结果与关联id
String msg = new String(message.getBody());
String cid = message.getProperties().getCorrelationId();
if (cid.equals(correlationId)) {
//消息处理线程放数据
q.offer(Long.parseLong(msg));
}
try {
c.close();
} catch (Exception e) {
e.printStackTrace();
}
con.close();
}
};
CancelCallback cancelCallback = new CancelCallback() {
@Override
public void handle(String consumerTag) throws IOException {
}
};
c.basicConsume(replyTo,true, deliverCallback, cancelCallback);
//主线程拿数据
return q.take();
}
}
virtual host
在RabbitMQ中叫做虚拟消息服务器VirtualHost,每个VirtualHost相当于一个相对独立的RabbitMQ服务器,每个VirtualHost之间是相互隔离的。exchange、queue、message不能互通
创建virtual host:
admin–virtual host:
Rabbmq(什么是RabbmitMQ,RabbmitMQ的六种工作模式)
RabbitMQ整合springboot(附代码)
最后
需要资料软件,解决问题可私信博主
更多参考精彩博文请看这里:RR-Shmily
喜欢博主的小伙伴可以加个关注、点个赞,欢迎评论哦,持续更新嘿嘿!