rabbitmq是有erlang开发消息队列,支持很多客户端,例如java等等,就是解决生产者和消费者的问题,生产者和消费者可以部署在不同的服务器上,可以达到松耦合,容易扩展,并且异步的处理任务,可以降低密集型任务对服务器资源的消耗,针对大型系统来说,可以统一管理任务,rabbitmq可以实现以下功能:
1.简单的单发送单接收,这种情况使用比较少
2.生产者对应多个消费者,在使用多个消费者的时候可以有效率的避免消息流失的情况,通过设置消息应答(类似HTTP的握手机制)控制不流失消息;但是如果rabbit服务停了怎么办呢,可以通过设置消息持久化避免消息丢失。
3.rabbitmq支持公平转发,例如有两个任务,其中一个非常耗时,另外一个非常快的执行完成,那如果这两个任务都发送到一个rabbit服务上,那执行任务快的那个会经常出现等待执行任务慢的那个,那怎么办呢?
(1)我们可以使用basicQos方法,传递参数prefetchCount=1,这样可以告诉生产者不要在同一时间给一个消费者超过一个任务,也就是说在消费者空闲的时候发送消息。
4.rabbitmq的发布/订阅功能,日志信息,每一个消费者都需要得到日志信息,第一个消费者需要将日志信息记录下来,第二个消费者需要将日志输出到频幕上,怎么控制将所有的消息发到知道的消费者呢?
(1)此时用到Exchanges(转发器),就是说生产者通过转发器发送给消费者,而他不知道发送到哪个消费者,由转发器决定;可以首先定义转发器类型,fanout,例如chaneel.exchangeDeclare(EXCHAGE_NAME,"fanout"); (在生产者中声明)。
(2)其次在消费者中需要绑定转发器,channel.queueBind(queueName,EXCHANGE_NAME),此时消息就通过转发器发送到指定的消费者队列中。转发器属于rabbitmq的完整的消息模型。
5.路由选择(Routing),对于4中的日志信息,我们想把一些特别严重的消息写到日志文件中,所有的日志还是仍然输出到频幕上,这个时候就用到这个路由选择的功能了。
(1)绑定(bindings)在4中已经使用过了,但是绑定可以增加一个额外的参数routingKey,可以称之为绑定键。
(2)直接转发器类型(Direct exchange),在4中我们使用过fanout的转发器类型,此类型不是很灵活,使用direct转发器,可以在生产者中指定routing key,在消费者中指定binding key消息会被推送至routing key 与 routing key完全匹配的队列中去,可以实现多重绑定。
(3)使用方法,在生产者声明:
//首先声明转发器类型
channel.exchangeDeclare(EXCHAGNE_NAME,"direct")
//发送消息的时候,发送消息值转发器指定routing key
channel.basicPublish(EXCHANGE_NAME,routing key,null,message.getBytes())
在消费者中:
//首先声明转发器类型
channel.exchangeDeclare(EXCHAGNE_NAME,"direct")
//指定binding key,与上面的routing key对应
channel.queueBind(queueName,EXCHANGE_NAME,binding key)
6.主题(Topic),5中可以实现基于日志级别的发送,选择的接收,如果想实现根据日志的来源进行订阅,需要用到主题转发器。
(1)主题转发器(Topic Exchange),此类型转换器不能随意的设置选择键,必须由点隔开的标识符组成,合法的例子:“user.name.log”,标识符的上限为255个字节。关于绑定键(消费者定义的)有两种特殊的情况:*可以匹配一个标识符;#可以匹配0或多个标识符。
(2)使用方法与5类似,首先声明为topic 转发器类型,其次routing key与binding key增加了标识符。
注:介绍rabbitmq中的几个必须用到的东东,Connection(连接),Channel(通道,频道);
(1)Connection:就是一个TCP连接,生产者和消费者都是通过TCP连接到服务器上的,程序的起始处就是建立一个TCP连接。
(2)Channels:虚拟连接,他建立在上述的TCP连接中,数据流动都是在此中进行的。一般情况下,程序都是先建立TCP连接,然后建立这个虚拟连接。
(3)为什么使用Channels而不直接使用TCP连接呢?因为TCP的频繁的建立和连接都是很好CPU的,对系统的性能影响很大,而且TCP的连接数也是有限,因此也影响了系统处理高并发的能力,但是加你Channels是没有上述代价的。