RabbitMQ
RabbitMQ是一个开源的AMQP实现,服务器端用Erlang语言编写,支持多种客户端,如:Python、Ruby、.NET、Java、JMS、C、PHP、ActionScript、XMPP、STOMP等,支持AJAX。用于在分布式系统中存储转发消息,在易用性、扩展性、高可用性等方面表现不俗。
AMQP(Advanced MessageQueuing Protocol):高级消息队列协议,应用层协议的一个开放标准,为面向消息的中间件设计。消息中间件主要用于组件之间的解耦,消息的发送者无需知道消息使用者的存在,反之亦然。AMQP的主要特征是面向消息、队列、路由(包括点对点和发布/订阅)、可靠性、安全。
Erlang:一种面向并发的编程语言。
RabbitMQ安装(windows环境):猛戳下一步
注意:安装时候报错如下图
原因:因为rabbitMQ服务端由Erlang语言编写,所以要在本机安装Erlang环境。
RabbitMQ视图工具
RabbitMQ 提供了视图工具,通过浏览器可访问操作,地址为RabbitMQ服务地址端口为15672
如果可视化软件无法正常使用可能是没有开启,开启命令rabbitmq-plugins enable rabbitmq_management
RabbitMQ基本概念
Producer:生产者,发送消息
Consumer:消费者,接受消息,处理
ConnectionFactory Connection Channle
channle:虚拟通道,rabbitMq大部分操作都是通过channle来完成,如:声明queue,
声明Exchange,绑定Queue与Exchange等等。使用channle的好处,提高项目效率。
Queue:队列,RabbitMQ存储消息的地方,Producer最终都是将消息发送到queue中。一个queue可以绑定多个消费者。
Message acknowledgment:类似回执,如果消费者进成功接受到消息之后给RabbitMQ返回一个回执,RabbitMQ接受到回执,讲该消息从queue中删除
Message durability:持久化
Prefetch count:当queue绑定多个消费者时,为避免分工不均匀情况,可以通过设置prefetch count 来设定queue发送给每个消费者的消息数量
Exchange :交换器。在RabbitMQ中生产者,产生消息之后并不是直接将消息推送到队列当中,而是先推送到指定的Exchange中,通过Exchange根据不同的
逻辑策略推送到一个或者多个queue中.
Routing Key:生产者将消息发送到Exchange时候,声明的一个key,Exchange通过这个routingKey来进行消息推送
Binding:用于Exchange与queue的绑定
BindingKey:exchange与queue绑定时的key ,在Exchange的Direct模式下,通过与Routing Key配合,讲Exchange中的消息推送到Queue中
Direct:
生产者生产消息之后,通过Exchange,讲消息发送到,routingkey与bindingkey相匹配的队列中。
Fanout:
生产者生产信息之后,通过Exchange,将消息发送到,所有与改Exchange绑定的Queue中,该模式忽略RoutingKey。
Topic:
Topic模式月direct模式类似,但是允许模糊推送,以“.”来进行分割,“*”代表一个,“#”代表多个。
Headers:
该模式不依赖于Routingkey和bindingkey匹配规则来路由消息,而是根据发送消息中的header属性来进行匹配。
RabbitMQ 支持RPC(远程调用协议)
RabbitMQ中实现RPC的机制是:客户端发送请求(消息)时,在消息的属性(MessageProperties,在AMQP协议中定义了14中properties,这些属性会随着消息一起
发送)中设置两个值replyTo(一个Queue名称,用于告诉服务器处理完成后将通知我的消息发送到这个Queue中)和correlationId(此次请求的标识号,服务器处理完成后
需要将此属性返还,客户端将根据这个id了解哪条请求被成功执行了或执行失败)。服务器端收到消息并处理,服务器端处理完消息后,将生成一条应答消息到replyTo指定
的Queue,同时带上correlationId属性。客户端之前已订阅replyTo指定的Queue,从中收到服务器的应答消息后,根据其中的correlationId属性分析哪条请求被执行了,根据执行
结果进行后续业务处理。
//常用API
//链接:
//创建工厂
ConnectionFactory connectionFactory = new ConnectionFactory();
//设置RabbitMQ服务地址
connectionFactory.setHost("localhost");
//设置RabbitMQ服务端口
connectionFactory.setPort(5672);
//RabbitMQ用户名
connectionFactory.setUsername("root");
//RabbitMQ密码
connectionFactory.setPassword("root");
/**
* 创建店址数组,在构造方法中加入地址数组,如果第一个链接失败,则使用第二个,connectionFactory.newConnection()
* 方法自动判断
Address[] addrArr = new Address[]{
new Address("hostname1",5672),
new Address("hostname2", 5672)};
Connection conn = connectionFactory.newConnection(addrArr);
*/
/**
* 通过Executors.newFixedThreadPool(20); 穿件连接池,创建连接时候从连接池冲获取
ExecutorService es = Executors.newFixedThreadPool(20);
Connection connection = connectionFactory.newConnection(es);
*/
//获取链接
Connection connection = connectionFactory.newConnection();
//获取通道
Channel channel =connection.createChannel();
/**
* 声明交换机
* exchange:名称
* type:类型
* durable:是否持久化,默认false
*/
channel.exchangeDeclare("exchangeName","exchangeType",false);
/**
* 声明队列queue
* queue:队列名称
* durable:是否持久化
* exclusive:是否仅供此链接使用
* autoDelete:不适用时是否自动删除
* arguments:其它参数
*/
channel.queueDeclare("queueName ",false,false,false,null);
/**
* 绑定Exchange和Queue
* queue:队列名称
* exchange:交换机名称
* routingKey:路由关键字
*/
channel.queueBind("queueName","exchagenName","");
/**
* 推送消息
* exchange:交换机名称
* routingKey:路由关键字
* props:其他属性
* body:消息主体
*/
channel.basicPublish("RabbitMQTopic","topic.key.*",null,message.getBytes());
//使用Direct Exchange的消息生产/消费
// 与Default Exchang 类似
//Producer代码
public class RabbitMqProducerDirect {
public static void main(String args[]) throws IOException, TimeoutException {
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("localhost");
connectionFactory.setPort(5672);
connectionFactory.setUsername("root");
connectionFactory.setPassword("root");
Connection connection = connectionFactory.newConnection();
Channel channel = connection.createChannel();
channel.exchangeDeclare("directExchange","direct");
channel.queueDeclare("RabbitDemo",false,false,false,null);
channel.queueBind("RabbitDemo","directExchange","rabbitMessage");
String message = "The message of RabbitMQ test";
channel.basicPublish("directExchange","rabbitMessage",null,message.getBytes());
}
}
//Consumer代码
public class RabbitMqConsumer {
public static void main(String args[]) throws IOException, TimeoutException {
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("localhost");
connectionFactory.setPort(5672);
connectionFactory.setUsername("root");
connectionFactory.setPassword("root");
Connection connection = connectionFactory.newConnection();
Channel channel = connection.createChannel();
//声明一个directExchange
channel.exchangeDeclare("directExchange","direct");
//声明一个queue
channel.queueDeclare("RabbitDemo", false, false, false, null);
//将queue与exchange 通过routingkey绑定
channel.queueBind("RabbitDemo","directExchange","rabbitMessage");
Consumer consumer = new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body)
throws UnsupportedEncodingException {
System.out.println(new String(body,"utf-8"));
}
};
channel.basicConsume("RabbitDemo", true, consumer);
}
}
//使用Fanout Exchange的消息消费/生产
//Producer代码
ublic class RabbitMqProducerFanout1 {
public static void main(String args[]) throws IOException, TimeoutException {
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("localhost");
connectionFactory.setPort(5672);
connectionFactory.setUsername("root");
connectionFactory.setPassword("root");
Connection connection = connectionFactory.newConnection();
Channel channel = connection.createChannel();
channel.exchangeDeclare("fanoutExchange","fanout");
// channel.queueDeclare("fanoutQueue",false,false,false,null);
String message = "The message of RabbitMq Fanout Exchange1";
channel.basicPublish("fanoutExchange","",null, message.getBytes());
}
}
public class RabbitMqProducerFanout2 {
public static void main(String args[]) throws IOException, TimeoutException {
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("localhost");
connectionFactory.setPort(5672);
connectionFactory.setUsername("root");
connectionFactory.setPassword("root");
Connection connection = connectionFactory.newConnection();
Channel channel = connection.createChannel();
channel.exchangeDeclare("fanoutExchange1","fanout");
// channel.queueDeclare("fanoutQueue",false,false,false,null);
String message = "The message of RabbitMq Fanout Exchange2";
channel.basicPublish("fanoutExchange1","",null, message.getBytes());
}
}
//Consumer代码
public class RabbitMqConsumerFanout1 {
public static void main(String args[]) throws IOException, TimeoutException {
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("localhost");
connectionFactory.setPort(5672);
connectionFactory.setUsername("root");
connectionFactory.setPassword("root");
Connection connection = connectionFactory.newConnection();
Channel channel = connection.createChannel();
channel.exchangeDeclare("fanoutExchange","fanout");
channel.queueDeclare("fanoutQueue1",false,false,false,null);
channel.queueBind("fanoutQueue1","fanoutExchange","");
channel.queueBind("fanoutQueue1","fanoutExchange1","");
Consumer consumer = new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body)
throws UnsupportedEncodingException {
System.out.println(new String(body,"utf-8"));
}
};
channel.basicConsume("fanoutQueue1", true, consumer);
}
}
public class RabbitMqConsumerFanout2 {
public static void main(String args[])throws Exception{
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("localhost");
connectionFactory.setPort(5672);
connectionFactory.setUsername("root");
connectionFactory.setPassword("root");
Connection connection = connectionFactory.newConnection();
Channel channel = connection.createChannel();
channel.exchangeDeclare("fanoutExchange","fanout");
channel.queueDeclare("fanoutQueue2",false,false,false,null);
channel.queueBind("fanoutQueue2","fanoutExchange","");
Consumer consumer = new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body)
throws UnsupportedEncodingException {
System.out.println(new String(body,"utf-8"));
}
};
channel.basicConsume("fanoutQueue2", true, consumer);
}
}
//使用Topic模式生产/消费
//Producer代码
public class RabbitMQProducerTopic {
public static void main(String[] args) throws IOException, TimeoutException {
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("localhost");
connectionFactory.setPort(5672);
connectionFactory.setUsername("root");
connectionFactory.setPassword("root");
Connection connection = connectionFactory.newConnection();
Channel channel = connection.createChannel();
channel.exchangeDeclare("RabbitMQTopic","topic",false);
String message = "The message of RabbitMq Topic Exchange1";
channel.basicPublish("RabbitMQTopic","topic.key.*",null,message.getBytes());
}
}
//Consumer1代码
public class RabbitMQConsumerTopic1 {
public static void main(String[] args) throws IOException, TimeoutException {
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("localhost");
connectionFactory.setPort(5672);
connectionFactory.setUsername("root");
connectionFactory.setPassword("root");
Connection connection = connectionFactory.newConnection();
Channel channel =connection.createChannel();
channel.queueDeclare("topicQueue1",false,false,false,null);
channel.queueBind("topicQueue1","RabbitMQTopic","topic.key.*");
DefaultConsumer consumer = new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body)
throws UnsupportedEncodingException {
System.out.println(new String(body,"utf-8"));
}
};
channel.basicConsume("topicQueue1",consumer);
}
}
//Consumer2代码
public class RabbitMQConsumerTopic2 {
public static void main(String[] args) throws Exception{
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("localhost");
connectionFactory.setPort(5672);
connectionFactory.setUsername("root");
connectionFactory.setPassword("root");
Connection connection = connectionFactory.newConnection();
Channel channel =connection.createChannel();
channel.queueDeclare("topicQueue2",false,false,false,null);
channel.queueBind("topicQueue2","RabbitMQTopic","topic.#");
DefaultConsumer consumer = new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body)
throws UnsupportedEncodingException {
System.out.println(new String(body,"utf-8"));
}
};
channel.basicConsume("topicQueue2",consumer);
}
}
//RabbitMQ与Spring整合
//spring.xml配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:rabbit="http://www.springframework.org/schema/rabbit"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/rabbit
http://www.springframework.org/schema/rabbit/spring-rabbit-1.4.xsd">
<rabbit:connection-factory id="connectionFactory"
host="localhost" port="5672" username="root" password="root"
/>
<rabbit:admin connection-factory="connectionFactory"/>
<!--direct模式-->
<rabbit:queue id="directQueue" auto-delete="false" durable="false" name="directQueue" exclusive="false"/>
<rabbit:direct-exchange name="directExchange" durable="false" auto-delete="false" id="directExchange">
<rabbit:bindings>
<rabbit:binding queue="directQueue" key="directExchangeTest"></rabbit:binding>
</rabbit:bindings>
</rabbit:direct-exchange>
<rabbit:template connection-factory="connectionFactory" exchange="directExchange" id="rabbitTemplate"/>
<bean id="messageProducer" class="com.yu.maven_demo.service.RmqSpringProducer"/>
<!-- <bean id="messageConsumer" class="com.yu.maven_demo.service.RmqSpringConsumer"/>
<rabbit:listener-container connection-factory="connectionFactory">
<rabbit:listener ref="messageConsumer" queues="directQueue"/>
</rabbit:listener-container>-->
</beans>
//Producer代码
public class RmqSpringProducer {
@Resource
private AmqpTemplate rabbitTemplate;
public boolean sendMessage(String message){
try {
rabbitTemplate.convertAndSend("directExchangeTest",message);
return true;
}catch (Exception e){
e.printStackTrace();
return false;
}
}
}
//Consumer代码
public class RmqSpringConsumer implements MessageListener{
public void onMessage(Message message) {
try {
System.out.println(new String(message.getBody(),"utf-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
}