轻松搞定RabbitMQ(一)——RabbitMQ基础知识+HelloWorld

       本文是简单介绍一下RabbitMQ,参考官网上的教程。同时加入了一些自己的理解。官网教程详见:"Hello World!"

引言



       你是否遇到过多个系统间需要通过定时任务来同步某些数据?

       你是否在为异构系统的不同进程间相互调用、通讯的问题而苦恼、挣扎?

       如果是,那么恭喜你,消息服务让你可以很轻松地解决这些问题。消息服务擅长于解决多系统、异构系统间的数据交换(消息通知/通讯)问题。

       本文将要介绍的RabbitMQ就是当前最主流的消息中间件之一。

RabbitMQ简介


       MQ(Message Queue,消息队列)是一种应用系统之间的通信方法。是通过读写出入队列的消息来通信(RPC则是通过直接调用彼此来通信的)。

       AMQP,即Advanced Message Queuing Protocol,高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计。消息中间件主要用于组件之间的解耦,消息的发送者无需知道消息使用者的存在,反之亦然。
AMQP的主要特征是面向消息、队列、路由(包括点对点和发布/订阅)、可靠性、安全。

       RabbitMQ是一个开源的AMQP实现,服务器端用Erlang语言编写,支持多种客户端,如:Python、Ruby、.NET、Java、JMS、C、PHP、ActionScript、XMPP、STOMP等,支持AJAX。用于在分布式系统中存储转发消息,在易用性、扩展性、高可用性等方面表现不俗。

       下面通过生产者代码来解释一下RabbitMQ中涉及到的概念。

public class MsgSender {
	private final static String QUEUE_NAME = "hello";

	public static void main(String[] args) throws IOException {
		/**
		 * 创建连接连接到MabbitMQ
		 */
		ConnectionFactory factory = new ConnectionFactory();
		// 设置MabbitMQ所在主机ip或者主机名
		factory.setHost("127.0.0.1");
		// 创建一个连接
		Connection connection = factory.newConnection();
		// 创建一个频道
		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();
	}
}

ConnectionFactory、Connection、Channel

       ConnectionFactory、Connection、Channel,这三个都是RabbitMQ对外提供的API中最基本的对象。不管是服务器端还是客户端都会首先创建这三类对象。
       ConnectionFactory为Connection的制造工厂。

       Connection是与RabbitMQ服务器的socket链接,它封装了socket协议及身份验证相关部分逻辑。

       Channel是我们与RabbitMQ打交道的最重要的一个接口,大部分的业务操作是在Channel这个接口中完成的,包括定义Queue、定义Exchange、绑定Queue与Exchange、发布消息等。

Queue

       Queue(队列)是RabbitMQ的内部对象,用于存储消息,用下图表示。

       RabbitMQ中的消息都只能存储在Queue中,生产者(下图中的P)生产消息并最终投递到Queue中,消费者(下图中的C)可以从Queue中获取消息并消费。

       队列是有Channel声明的,而且这个操作是幂等的。同名的队列多次声明也只会创建一次。我们发送消息就是想这个声明的队列里发送消息。

       看一下消费者的代码:

public class MsgReceiver {
	private final static String QUEUE_NAME = "hello";

	public static void main(String[] argv) throws IOException, InterruptedException {
		ConnectionFactory factory = new ConnectionFactory();
		factory.setHost("127.0.0.1");
		// 打开连接和创建频道,与发送端一样
		Connection connection = factory.newConnection();
		Channel channel = connection.createChannel();

		// 声明队列,主要为了防止消息接收者先运行此程序,队列还不存在时创建队列。
		channel.queueDeclare(QUEUE_NAME, false, false, false, null);
		// 创建队列消费者
		QueueingConsumer consumer = new QueueingConsumer(channel);
		System.out.println(" [*] Waiting for messages. To exit press CTRL+C");
		// 指定消费队列
		channel.basicConsume(QUEUE_NAME, true, consumer);
		while (true) {
			// nextDelivery是一个阻塞方法(内部实现其实是阻塞队列的take方法)
			QueueingConsumer.Delivery delivery = consumer.nextDelivery();
			String message = new String(delivery.getBody());
			System.out.println(" [x] Received '" + message + "'");
		}
	}
}

       从上述代码中,我们可以看到ConnectionFactory、Connection、Channel这三个对象都还是会创建。而队列在消费者这里又声明了一遍。这是为了防止先启动消费者,当为消费者指定队列时,如果RabbitMQ服务器上未声明过队列,就会抛出IO异常。

QueueingConsumer

       队列消费者,用于监听队列中的消息。调用nextDelivery方法时,内部实现就是调用队列的take方法。该方法的作用:获取并移除此队列的头部,在元素变得可用之前一直等待(如果有必要)。说白了就是如果没有消息,就处于阻塞状态。

       运行结果如下:(生产者、消费者谁先运行都可以)

时间: 2024-09-19 13:12:50

轻松搞定RabbitMQ(一)——RabbitMQ基础知识+HelloWorld的相关文章

轻松搞定RabbitMQ(六)——主题

       翻译地址:http://www.rabbitmq.com/tutorials/tutorial-five-java.html        在上一篇博文中,我们进一步改良了日志系统.使用Direct类型的转换器,使得接收者有能力进行选择性的接收日志,,而非fanout那样,只能够无脑的转发,如果你还不了解,请阅读:轻松搞定RabbitMQ(四)--发布/订阅.        虽然使用Direct类型的转换器改进了日志系统.但它仍然有一定的局限性--不能根据多重条件进行路由选择.  

SQL Server数据汇总五招轻松搞定_MsSql

本文我们将讨论如何使用GROUPBY子句来汇总数据. 使用单独列分组 GROUP BY子句通过设置分组条件来汇总数据,在第一个例子中,我在数据库AdventureWork2012中的表 Sales.SalesOrderDetail.中的一列上进行数据分组操作.这个例子以及其他例子都使用数据库AdventureWorks2012,如果你想使用它运行我的代码,你可以点击下载. 下面是第一个示例的源码,在CarrierTrackingNumber列上使用group by子句进行数据分组操作 USE A

轻松搞定jQuery.noConflict()_jquery

jQuery是目前使用最广泛的前端框架之一,有大量的第三方库和插件基于它开发.为了避免全局命名空间污染,jQuery提供了jQuery.noConflict()方法解决变量冲突.这个方法,毫无疑问,非常有效.遗憾的是,jQuery的官方文档对该方法的描述不够清晰,许多开发者并不清楚当他们调用jQuery.noConflict()时,究竟发生了什么,从而导致在使用时出现了许多问题.尽管如此,jQuery.noConflict()背后实现原理依然值得Web开发者学习掌握,成为解决类似全局命名空间污染

轻松搞定js表单验证_javascript技巧

先看看效果图: html: 引入 <script src="/Scripts/jquery-1.10.2.js"></script> <script src="/Scripts/Validate-1.0.1.js"></script> <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head ru

两行代码轻松搞定JavaScript日期验证_javascript技巧

我们通常在 JavaScript 中验证日期,基本的思路大概是,先判断年月日是否有效,再判断当月是否有当日,比如一些月份没有 31 日,平年二月没有 29.30 日,闰年二月没有 30 日等等.  偶然间发现一个技巧,能判断以上所有的情况.除去赋值代码,实际代码仅两行.  其实这个技巧也很简单,通过实例化 Date 对象来生成一个合法的日期,再去对比年月日是否相等,以验证日期是否合法.  var originalYear = 2016; var originalMonth = 12; var o

JavaScript 一行代码,轻松搞定浮动快捷留言-V2升级版_javascript技巧

前天熬了大半宿发了一篇[一行代码轻松搞定快捷留言功能],同时发布了V1.0beta版的快捷留言功能和源代码,之所以是beta版,就是当时感觉虽然基本功能有了,但是还不够完善,特性也不一定合理,今天不知不觉又弄到了这个时候,这次对上一版做了很大改进: 首先,原来自动提交留言信息的同时会自动推荐,大量的推荐数,直接影响了博客园的推荐排名机制,所以后来在第一时间修改成了询问是否要推荐的交互模式! 其次,虽然快捷功能有了,并且很好用,但是满屏幕的"好贴!我顶你!"也确实有些审美疲劳了,并且没什

如何轻松搞定一个优质的域名?

中介交易 http://www.aliyun.com/zixun/aggregation/6858.html">SEO诊断 淘宝客 云主机 技术大厅 现在,很多朋友接触到了网赚,都想要建立一个自己的网站,做回站长获得收益.但是,大家在建站最为基础的部分并没有给予充分的重视,就比如说是对于域名的选择方面.所以,今天,time给大家讲解一下,如何轻松搞定一个优质的域名! 如何轻松搞定一个优质的域名? 域名和空间都是非常重要的,这个对于网站来说,属于硬件.但是在这个方面上,千万不要小气,想要找价

五步轻松搞定网站数据分析收集工作

中介交易 http://www.aliyun.com/zixun/aggregation/6858.html">SEO诊断 淘宝客 云主机 技术大厅 网站及产品运营不能凭空而谈,纸上谈兵,要用实实在在的数据说话.如果我们手里有一份针对我们需求的非常完美的数据的话,那对于我们在进行推广的时候,就会有目标,有针对性地去进行,节省了大量的工作量,也能让我们很好地了解竞争对手的情况,从而来达到一个知己知彼,掌控全局的目的.万丈高楼平地起,再完美的数据分析也是建立在数据的基础上的,只有在足够多的数据

几行代码轻松搞定网页的简繁转换

简繁转换|网页 对网页进行简繁字体转换的方法一般有两种:一是使用<简繁通>这样的专业软件,另外一种是制作两套版本的网页.显然,这两种方法都较为麻烦,而且专业软件一般不能用于免费的空间.笔者在这里给大家提供一个非常简单的方法,只须在页面上添加几行代码就可以轻松搞定网页的简繁转换了.首先在http://www.knowsky.com/download/transform.js处下载用于简繁转换的js文件transform.js,复制到网站目录下,然后使用网页制作工具打开需要进行简繁转换的网页,

一步一步轻松搞定您的个人数码免冠照

应用目标:制作证件照片 使用软件:Photoshop 7.0(其他版本操作类似) 实现难度:即学即会 相信许多朋友都有这样的经历:填写应聘表.考个驾照或是办个工作证经常会用到免冠照,可每次都想不起来上回留下的底(照)片放在哪里,回到家里翻天覆地地一阵好找,结果常常是无功而返,最后只好一边抱怨自己记性不好一边梳妆打扮走进照相馆,一番讨价还价之后,然后极不情愿地把银子数给照相馆老板,到了下回这样的情形依然会重现.要是我们做好一个无需底片的数码免冠照存在个人电脑或软盘里,随用随扩,岂不是要省掉许多麻烦