消息代理
在保证消息传输过程安全的前提下,为应用提供通用的消息发送和接收平台。
专有名词
生产(Producing),即发送
发送消息的程序就是开发者(producer),用“P”表示
队列(queue),邮箱的名称
无限缓冲,可接受多个生产者(producers)的消息,也可以给多个消费者(consumers)提供数据
消费(consuming),获取消息
等待获取消息的程序,用“C”表示
队列
Hello World(简单队列)
仅发送一个消息,获取它并输出到屏幕
生产者(producer)把消息发送给名为“hello”的队列,消费者从此队列中获取消息
工作队列(Work Queue)
又称任务队列
与简单队列不同的是,工作队列会发送一些耗时的任务给多个工作者(Worker)
为了避免等待一些占用大量资源、时间的操作,生产者将消息发送到队列中后,多个工作者对任务共享。
发布/订阅
与前两种队列不同的是,前两种队列每一条消息都只能被一个消费者所获取,但在发布/订阅队列中,一个消息可以给多个消费者。
此队列引入了交换机(Exchanges),它可以将同一条消息推送给多个队列
发布者(producer)把消息发送给一个交换机,交换机收到消息后,将一条消息推送到队列,交换机知道如何处理接收到的消息,应该推送给哪些队列或者直接忽略消息,由交换机类型定义。
路由(Routing)
同发布/订阅队列相似的,路由队列也是用交换机发布消息,其新增了一个功能——队列可以只订阅消息的一个子集。
路由算法:交换机会对绑定建(binding key)和路由键(routing key)进行精确匹配,以确定消息要分发到那个队列。
下图无疑是一个很好的场景描述:
通配符队列
模式同路由队列几乎相同,差别在于交换机发布消息到队列的过滤条件
发送到交换机的消息的路由键是一个由.分隔开的词语列表,词语的个数随意,不超过255字节
绑定键拥有同样的格式,交换机会将携带者特定路由键的消息发送给绑定键与之匹配的队列
* 用来表示一个单词
# 用来表示任意数量单词
代码实践
此处只列举简单队列的代码
发送者Send.java
public class Send {
private final static String QUEUE_NAME = "test_queue";
public static void main(String[] argv) throws Exception {
// 获取到连接以及mq通道
Connection connection = ConnectionUtil.getConnection();
// 从连接中创建通道
Channel channel = connection.createChannel();
// 声明(创建)队列
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
// 消息内容
String message = "Hello World!";
channel.basicPublish("", QUEUE_NAME, null, message.getBytes());
System.out.println(" [x] Sent '" + message + "'");
//关闭通道和连接
channel.close();
connection.close();
}
}
消费者Recv.java
public class Recv {
private final static String QUEUE_NAME = "test_queue";
public static void main(String[] argv) throws Exception {
// 获取到连接以及mq通道
Connection connection = ConnectionUtil.getConnection();
Channel channel = connection.createChannel();
// 声明队列
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
// 定义队列的消费者
QueueingConsumer consumer = new QueueingConsumer(channel);
// 监听队列
channel.basicConsume(QUEUE_NAME, true, consumer);
// 获取消息
while (true) {
QueueingConsumer.Delivery delivery = consumer.nextDelivery();
String message = new String(delivery.getBody());
System.out.println(" [x] Received '" + message + "'");
}
}
}