https://www.bilibili.com/video/av59630756?p=4
一、使用消息队列的好处
1、通过异步处理,提高系统性能(削峰,提高响应速度)
不使用消息队列时,用户数据直接写入数据库,在高并发情况下数据压力剧增,响应速度变慢;
使用消息队列后,用户将数据发送给消息队列后会立即返回,再由消费队列的消费者进程从队列中获取数据,异步写入数据库。
消息队列的服务器处理速度快于数据库,所以可以改善响应速度,提高系统性能。
2、系统解耦
模块之间不直接调用,新增或修改模块后对其他模块影响小,可扩展性好。
生产者成功发送到消息队列的消息会存储在生产者服务器上,直到消息被消费者处理后才删除消息,避免消息队列服务器、或者消费者服务器宕机后造成消息丢失(消费者无法读取数据)。
3、流量削峰(秒杀)
针对高并发情况 ,在消息队列中先对大量请求进行筛选,剩下的请求应用到接下来的业务中,实现流量削峰。
二、使用消息队列的问题
- 系统可用性降低:要考虑消息丢失和队列宕机的情况
- 系统复杂性提高:需要处理重复消费、消息丢失等情况
- 数据一致性问题:生产者生产的信息,消费者没有正确消费导致信息不一致
三、安装rabbitmq
1、官网下载版本匹配的rabbitmq-server-3.8.2.exe和Erlang 22.2
https://www.rabbitmq.com/
2、全部默认安装好后,打开RabbitMQ command prompt,输入rabbitmq-plugins enable rabbitmq_management
3、打开浏览器,输入http://localhost:15672/
默认账号密码都是:guest
四、添加用户
1、打开网址进入guest:http://localhost:15672/#/
2、在admin中添加用户
其中virtual hosts相当于mysql中的数据库db,授权后才能访问
3、添加数据库
命名一般以“/”开头
4、对用户进行授权
点击数据库名称,并设置允许
user_tyh就可以访问vhost_tyh的数据库了
五、配置MAVEN
maven是一个方便我们管理jar包的工具
1、官网下载:http://maven.apache.org/download.cgi
2、解压
3、添加环境变量:
用户变量中添加
MAVEN_HOME,地址为解压后的绝对地址
4、path中添加
%MAVEN_HOME%\bin
5、命令行中输入:mvn -version ,显示
6、配置eclipse+maven:
https://www.jianshu.com/p/03576e15035d
7、新建maven project,在pom.xml中添加:
<dependencies>
<!-- https://mvnrepository.com/artifact/com.rabbitmq/amqp-client -->
<dependency>
<groupId>com.rabbitmq</groupId>
<artifactId>amqp-client</artifactId>
<version>5.8.0</version>
</dependency>
</dependencies>
保存后会自动从上面的网址下载并添加依赖
MAVEN依赖下载网址:
https://mvnrepository.com/
六、简单队列(第一种队列)
1、模型:
生产者将消息发送到队列,消费者从队列中获取消息
对象:生产者、消息队列、消费者
2、获取MQ连接
package rabbitmq;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
public class ConnectionUtils {
/**
* 获取mq的连接
* 本类为工具类
* @return
* @throws TimeoutException
* @throws IOException
*/
public static Connection getConnection() throws IOException, TimeoutException {
//定义一个连接工厂
ConnectionFactory factory=new ConnectionFactory();
//设置服务地址
factory.setHost("127.0.0.1");
//设置端口(amqp为5672)
factory.setPort(5672);
//设置数据库vhost
factory.setVirtualHost("/vhost_tyh");
//用户名
factory.setUsername("user_tyh");
//密码
factory.setPassword("123");
return factory.newConnection();
}
}
3、生产者
package rabbitmqSimple;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import rabbitmq.ConnectionUtils;
/**
* 简单队列的生产者
* @param args
* @throws TimeoutException
* @throws IOException
*/
public class Producer {
private static final String QUEUE_NAME="simple_queue";
public static void main(String[] args) throws IOException, TimeoutException {
// TODO Auto-generated method stub
//获得连接
Connection connection=ConnectionUtils.getConnection();
//从连接中获取一个通道
Channel channel=connection.createChannel();
//创建队列声明
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
String msg="hello";
//发布
channel.basicPublish("", QUEUE_NAME, null, msg.getBytes());
System.out.println("send msg:"+msg);
channel.close();
connection.close();
}
}
4、消费者
package rabbitmqSimple;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.Envelope;
import rabbitmq.ConnectionUtils;
/**
* 消费者获取消息
* @author DELL
* */
public class Consumer {
private static final String QUEUE_NAME="simple_queue";
public static void main(String[] args) throws IOException, TimeoutException {
//1、获取连接
Connection connection=ConnectionUtils.getConnection();
//2、创建通道
Channel channel=connection.createChannel();
//队列声明
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
DefaultConsumer defaultConsumer = new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body)
throws IOException {
//重写方法,一旦有消息进入队列就会触发该方法
Stri