RabbitMQ入门_02_HelloWorld
A. AMQP基础
RabbitMQ 并不是基于 Java 开发人员熟悉的 JMS 规范设计开发的,而是基于一个比 JMS 更新更合理的 AMQP (Advanced Message Queuing Protocol) 协议。所以,在开始 RabbitMQ 之旅前,需要先对 AMQP 有一定的了解。毕竟,RabbitMQ 就是 AMQP 协议的第一个开源实现。
a. AMQP messaging 中的基本概念
以下内容来自 http://www.cnblogs.com/frankyou/p/5283539.html
- Broker:接收和分发消息的应用,RabbitMQ Server 就是 Message Broker
- Virtual host:出于多租户和安全因素设计的,把 AMQP 的基本组件划分到一个虚拟的分组中,类似于网络中的 namespace 概念。当多个不同的用户使用同一个RabbitMQ server 提供的服务时,可以划分出多个 vhost,每个用户在自己的 vhost 创建 exchange/queue 等
- Connection:publisher/consumer 和 broker 之间的TCP连接。断开连接的操作只会在 client 端进行,broker不会断开连接,除非出现网络故障或 broker 服务出现问题
- Channel:如果每一次访问 RabbitMQ 都建立一个Connection,在消息量大的时候建立 TCP Connection 的开销将是巨大的,效率也较低。Channel 是在 connection 内部建立的逻辑连接,如果应用程序支持多线程,通常每个 thread 创建单独的 channel 进行通讯,AMQP method 包含了 channel id 帮助客户端和 message broker 识别 channel,所以 channel 之间是完全隔离的。Channel 作为轻量级的 Connection 极大减少了操作系统建立 TCP connection 的开销
- Exchange:message 到达 broker 的第一站,根据分发规则,匹配查询表中的 routing key,分发消息到 queue 中去。常用的类型有:direct (point-to-point), topic (publish-subscribe) and fanout (multicast)
- Queue:消息最终被送到这里等待 consumer 取走。一个 message 可以被同时拷贝到多个 queue 中
- Binding:exchange 和 queue 之间的虚拟连接,binding 中可以包含 routing key。Binding 信息被保存到 exchange 中的查询表中,用于 message 的分发依据
简而言之,Publisher 发送的消息通过 Connection 中的 Channel 到达 Broker 的某个 Virtual Host,消息经过指定的 Exchange,根据 Binding 提供的分发依据,分发到 0~n 个 Queue 中;Queue 中的消息等待 Consumer 消费。
b. AMQP 模型解释
官网有一篇更详尽的模型解释:https://www.rabbitmq.com/tutorials/amqp-concepts.html
这篇文章一看就知道是好东西,可惜读起来太累了,以后再来回顾。
c. AMQP 规范
官网有 AMQP 规范的快速参考:https://www.rabbitmq.com/amqp-0-9-1-quickref.html
AMQP 规范全部内容可在 AMQP 官网查阅:http://www.amqp.org/
这些内容短期不会接触,留个脚印以后有机会再研究。
B. 你好,世界
参考资料:https://www.rabbitmq.com/tutorials/tutorial-one-java.html
示例代码:https://github.com/gordonklg/study,rabbitmq module
gordon.study.rabbitmq.helloworld.Sender.java
import java.util.concurrent.TimeUnit;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
public class Sender {
private static final String QUEUE_NAME = "hello";
public static void main(String[] argv) throws Exception {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
for (int i = 0; i < 10;) {
String message = "NO. " + ++i;
TimeUnit.MILLISECONDS.sleep(1000);
channel.basicPublish("", QUEUE_NAME, null, message.getBytes("UTF-8"));
System.out.printf("(%1$s)[===>%2$s ] %3$s\n", "Sender", ":" + QUEUE_NAME, message);
}
channel.close();
connection.close();
}
}
代码第12-14行通过 ConnectionFactory 创建了一个 Connection。Broker Host 地址为 localhost,端口是默认的 5672,用户密码是默认的 guest,VHOST 是默认的 "/"。(实际上默认的 Host 就是 localhost,第13行可以省略)
第15行在 Connection 中创建了一个虚拟的 Channel。
第17行申明了一个名字为 hello 的 Queue。不同于 JMS,AMQP 协议允许通过编程方式创建绝大多数的模型,例如 Exchange、Queue 等等。之所以是申明,是因为该方法会先判断当前 VHOST 中是否已存在一个同名的 Queue,如果不存在,则创建 Queue;如果存在,可能会直接使用已存在的 Queue,也可能返回异常(例如申明的 Queue 的属性与已存在的 Queue 的属性不一致时)。
queueDeclare 方法中三个 boolean 型参数指定了 Queue 的属性:
- durable:队列本身是否需要持久化。如果为 false,则 RabbitMQ 重启后该 Queue 消失。
- exclusive:排他性队列确保该队列只对申明它的连接可见,注意是连接而不是 Channel。当相应连接关闭时,该队列自动删除。
- autoDelete:设置为 true 的队列会在所有 Consumer 都断开连接时自动删除(不管是否是 durable)。队列被第一个 Consumer 连接前不会被删除。
第22行发布一个消息。basicPublish 方法第一个参数指定发布该消息所使用的 Exchange 名称,空字符串为系统预先定义的默认 Exchange,类型为 direct。第二个参数指定路由键,对于 direct 类型的 Exchange,会将该消息发送到所有绑定到该 Exchange 并且也设定了相同的路由键的 Queue 中。
gordon.study.rabbitmq.helloworld.Receiver.java
public class Receiver {
private final static String QUEUE_NAME = "hello";
public static void main(String[] argv) throws Exception {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
Consumer consumer = new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body)
throws IOException {
String message = new String(body, "UTF-8");
System.out.printf(" [ %2$s<===](%1$s) %3$s\n", "Receiver", QUEUE_NAME, message);
try {
TimeUnit.MILLISECONDS.sleep(500);
} catch (InterruptedException e) {
}
}
};
channel.basicConsume(QUEUE_NAME, true, consumer);
}
}
代码从第13行开始定义一个 Consumer,通过 handleDelivery 回调接口,我们可以处理从队列中获取的消息。
第25行启动一个 Consumer,basicConsume 方法第一个参数指定 Consumer 消费的队列,即 hello 队列;第二个参数 autoAck 指定消息确认模式,true 表示消息确认是自动完成的(至少在进入 handleDelivery 方法前就已经自动确认了),false 表示必须由 Consumer 自己确认;第三个参数指定 Consumer
现在,可以花式运行两个类,看看发生了什么了。
RabbitMQ入门_02_HelloWorld的更多相关文章
- 2.RABBITMQ 入门 - WINDOWS - 生产和消费消息 一个完整案例
关于安装和配置,见上一篇 1.RABBITMQ 入门 - WINDOWS - 获取,安装,配置 公司有需求,要求使用winform开发这个东西(消息中间件),另外还要求开发一个日志中间件,但是也是要求 ...
- RabbitMQ入门-从HelloWorld开始
从读者的反馈谈RabbitMQ 昨天发完<RabbitMQ入门-初识RabbitMQ>,我陆陆续续收到一些反馈.鉴于部分读者希望结合实例来讲 期待下篇详细,最好结合案例.谢谢! 哪都好,唯 ...
- RabbitMQ入门-高效的Work模式
扛不住的Hello World模式 上篇<RabbitMQ入门-从HelloWorld开始>介绍了RabbitMQ中最基本的Hello World模型.正如其名,Hello World模型 ...
- RabbitMQ入门-消息订阅模式
消息派发 上篇<RabbitMQ入门-消息派发那些事儿>发布之后,收了不少反馈,其中问的最多的还是有关消息确认以及超时等场景的处理. 楼主,有遇到消费者后台进程不在,但consumer连接 ...
- RabbitMQ入门-Topic模式
上篇<RabbitMQ入门-Routing直连模式>我们介绍了可以定向发送消息,并可以根据自定义规则派发消息.看起来,这个Routing模式已经算灵活的了,但是,这还不够,我们还有更加多样 ...
- RabbitMQ入门与使用篇
介绍 RabbitMQ是一个由erlang开发的基于AMQP(Advanced Message Queue)协议的开源实现.用于在分布式系统中存储转发消息,在易用性.扩展性.高可用性等方面都非常的优秀 ...
- [转]RabbitMQ入门教程(概念,应用场景,安装,使用)
原文地址:https://www.jianshu.com/p/dae5bbed39b1 RabbitMQ 简介 RabbitMQ是一个在AMQP(Advanced Message Queuing Pr ...
- RabbitMQ 入门指南——安装
RabbitMQ好文 Rabbitmq Java Client Api详解 tohxyblog-博客园-rabbitMQ教程系列 robertohuang-CSDN-rabbitMQ教程系列 Rabb ...
- RabbitMQ入门:总结
随着上一篇博文的发布,RabbitMQ的基础内容我也学习完了,RabbitMQ入门系列的博客跟着收官了,以后有机会的话再写一些在实战中的应用分享,多谢大家一直以来的支持和认可. RabbitMQ入门系 ...
随机推荐
- 从零打造在线网盘系统之Hibernate框架起步
欢迎浏览Java工程师SSH教程从零打造在线网盘系统系列教程,本系列教程将会使用SSH(Struts2+Spring+Hibernate)打造一个在线网盘系统,本系列教程是从零开始,所以会详细以及着重 ...
- Web安全开发建议
版权声明:原创作品,如需转载,请与作者联系.否则将追究法律责任. Web安全问题,很多时候会被人所忽略,安全漏洞造成了很多不必要的维护和开发任务,产生的问题有时候更是致命的. 实际上,只要我们养成一些 ...
- Jenkins构建时提示maven版本问题
在使用Jenkins进行项目构建的时候出现下面问题 [INFO] Scanning for projects... [WARNING] [WARNING] Some problems were enc ...
- Feature Toggle JUnit
Feature Toggle,简单来说,就是一个开关,将未完成功能的代码屏蔽后发布到生产环境,从而避免多分支的情况.之所以有本文的产生,就是源于此情景.在引入Feature Toggle的同时,我们发 ...
- UA-* headers
HTTP The Definitive Guide Request headers are headers that make sense only in a request message. The ...
- 服务器为什么这么慢?耗尽了CPU、RAM和磁盘I/O资源
机器运行缓慢通常是由于消耗了太多系统特定的资源.系统的主要资源包括CPU.RAM.磁盘I/O以及网络.过度使用这些资源的任何一种都会让系统陷入困境.不过,如果能登录到系统之中,可以借助大量工具确定问题 ...
- 点击劫持漏洞解决( Clickjacking: X-Frame-Options header missing)
点击劫持漏洞 X-Frame-Options HTTP 响应头, 可以指示浏览器是否应该加载一个 iframe 中的页面. 网站可以通过设置 X-Frame-Options 阻止站点内的页面被其他页面 ...
- Python开发【整理笔记】
回顾笔记 学python半年,新知识不断填充,之前学的东西也忘的差不多,整理下笔记,把重点再加深下印象,算是读书拾遗吧.... 1.类继承.新式类.经典类 首先,新式类.经典类的概念只存在于Pytho ...
- Web开发:URL编码与解码(转)
原文:http://www.cnblogs.com/greatverve/archive/2011/12/12/URL-Encoding-Decoding.html 通常如果一样东西需要编码,说明这样 ...
- java 反射 (一)
原文地址https://www.zhihu.com/question/24304289 首先我们了解一下JVM,什么是JVM,Java的虚拟机,java之所以能跨平台就是因为这个东西,你可以理解成 ...