一,RabbitMQ的简单了解
RabbitMQ是目前非常热门的一款消息中间件,经常使用于并发量比较高的场景。用电商下单过程作为一个简单列子,按照传统的方式,下单过程要等到调用完毕之后才能返回下单成功,如果网络产生波动等原因使得商品服务扣库存延迟或者失败,这样就会导致较差的用户体验。
消息队列提供一个异步通信机制,消息的发送者不必一直等待到消息被成功处理才返回,而是立即返回。消息中间件负责处理网络通信,如果网络连接不可用,消息被暂存于队列当中,当网络畅通的时候在将消息转发给相应的应用程序或者服务,当然前提是这些服务订阅了该队列。
二,RabbitMQ简单队列
接下来我们用代码简单模拟 消息生产者P 发送一条信息到红色队列中,然后消费者C从队列中获取到消息首先我们要在RabbitMQ上建立一个virtual host
建立一个maven项目,对应的pom文件引入的依赖
<!-- 引入队列依赖 -->
<dependency>
<groupId>com.rabbitmq</groupId>
<artifactId>amqp-client</artifactId>
<version>4.0.2</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.10</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.5</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
对应的Java代码:
简单的包结构
这是util包下的ConnectionUtils
package com.liao.rabbitmq.util;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
public class ConnectionUtils {
/**
* 获取MQ链接
*/
public static Connection getConnection() throws IOException, TimeoutException {
//定义一个链接工厂
ConnectionFactory factory = new ConnectionFactory();
//设置服务器地址
factory.setHost("127.0.0.1");
//设置AMQP端口号
factory.setPort(5672);
//设置vhost
factory.setVirtualHost("/vhost_mmr");
//用户名
factory.setUsername(" ");//自己登录RabbitMQ的用户名和密码
//密码
factory.setPassword(" ");//
return factory.newConnection();
}
}
消息生产者P
对应simple包下的Send类
package com.liao.rabbitmq.simple;
import com.liao.rabbitmq.util.ConnectionUtils;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
/**
* 生产者,发送消息
*/
public class Send {
private static final String QUEUE_NAME = "test_simple_queue";
public static void main(String[] args) throws IOException, TimeoutException {
//获取MQ链接
Connection connection = ConnectionUtils.getConnection();
//从链接中获取一个通道
Channel channel = connection.createChannel();
//创建队列声明
channel.queueDeclare(QUEUE_NAME,false,false,false,null);
//要发送的信息
String msg = "hello simple queue";
//进行发送
channel.basicPublish("",QUEUE_NAME,null,msg.getBytes());
System.out.println("发送信息:"+msg);
//关闭链接
channel.close();
connection.close();
}
}
消费者C
对应simple包下的Receive类
package com.liao.rabbitmq.simple;
import com.liao.rabbitmq.util.ConnectionUtils;
import com.rabbitmq.client.*;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
/**
* 消费者接受消息
*/
public class Receive {
private static final String QUEUE_NAME = "test_simple_queue";
public static void main(String[] args) throws IOException, TimeoutException {
//获取MQ链接
Connection connection = ConnectionUtils.getConnection();
//从链接中获取一个通道
Channel channel = connection.createChannel();
//创建队列声明
channel.queueDeclare(QUEUE_NAME,false,false,false,null);
//从消息队列中获取消息
DefaultConsumer consumer = new DefaultConsumer(channel){
//当消息队列中有消息时则会触发该方法
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties,
byte[] body) throws IOException {
super.handleDelivery(consumerTag, envelope, properties, body);
String msg = new String(body,"utf-8");
System.out.println("消费者接受到的消息: " + msg);
}
};
//监听队列
channel.basicConsume(QUEUE_NAME,true,consumer);
}
}
运行效果:
运行send时,当该消息被接受后,这里的1则就没了
三,简单队列存在的问题
生产者与消费者属于一一对应的问题,如果存在多个消费时则不行。而且在实际开发中,一般生产者发送消息的速度是比较快的,而消费者则需要和业务结合,所以一般速度是比较慢的,所以这时则就会出现积压很多队列消息,这时就需要工作队列来实现。