080:消息中间件设计思想与RabbitMQ环境搭建
1 第六期消息中间件课程内容安排
RabbitMq,Kafka,RocketMq
课题内容
1.传统Http协议调用接口存在的缺陷
2.消息中间件产生的背景
3.市面主流的MQ对比分析
4.RabbitMq设计的思想与理念
2 传统Http协议调用接口存在的缺陷
传统Http协议调用接口存在缺陷
传统方式 采用同步的形式调用接口,如果调用的过程非常耗时间,客户需要等待非常久的时间才会响应,这样对客户端体验非常不好。
比如用户注册 调用数据库新增插入会员信息需要3s、调用优惠券接口需要3s、调用第三方短信接口需要3s 一共需要9s的时间才会返回信息,这样用户的体验是非常不好。
采用多线程异步的形式实现操作
缺点:
1 对cpu性能不是很好,因为频繁创建线程;就算使用线程池,在高并发情况下,如果请求数量超出了线程池核心数还是会等待;
2 开启了线程默认情况下是没有返回结果;
3 为什么要使用消息中间件
生产者(producer):向消息中间件投递消息
消费者(consumer):向消息中间件获取消息
服务端(broker):消息中间件Server端,主要负责存储和转发消息
Message:发送消息的内容,就是发送的参数信息
MessageId:消息全局唯一id,解决消息幂等性(重复消费)问题
4 消息中间件异步、流量削峰、解耦问题
消息中间件核心思想:异步通讯、系统解耦、自动补偿与重试、流量削峰、解决分布式事务问题。
消费者宕机,生产者投递消息到mq,mq缓存消息到内存中,等消费者重新启动以后继续消费;如果消费者消费失败,mq自动重试。
削峰:解决高并发。
传统形式大量请求造成服务堆积可能导致服务崩溃。
消息中间件broker可以提前设置阈值存放消息,超过阈值拒绝接收;消息中间件不会将所有消息一次性给消费者进行消费,队列存储消息;
5 市面主流消息中间件对比分析
市面主流的MQ对比分析
ActiveMQ
历史悠久的开源项目,是Apache下的一个子项目。实现了多种协议,不够轻巧(源代码比RocketMQ多),支持持久化到数据库,对队列数较多的情况支持不好。(过时)
RabbitMQ
结合erlang语言本身的并发优势,支持很多的协议:AMQP,XMPP, SMTP, STOMP,非常重量级,更适合于企业级的开发。(万级)
Kafka
Apache下的一个子项目,使用scala实现的一个高性能分布式Publish/Subscribe消息队列系统。(十万级)
RocketMQ
阿里系下开源的一款分布式、队列模型的消息中间件,是阿里参照kafka设计思想使用java实现的一套mq,目前主要多用于订单交易系统。(十万级)
6 windows版本安装Rabbitmq
RabbitMQ的基本介绍
RabbitMQ是实现了高级消息队列协议(AMQP)的开源消息代理软件(亦称面向消息的中间件),RabbitMQ服务器是用Erlang语言编写的。
RabitMQ官方网站:https://www.rabbitmq.com/
支持的消息模型:
1.点对点(简单)的队列
2.工作(公平性)队列模式
3.发布订阅模式
4.路由模式Routing
5.通配符模式Topics
RabitMQ环境的基本安装
1.下载并安装erlang,下载地址:http://www.erlang.org/download
2.配置erlang环境变量信息
新增环境变量ERLANG_HOME=erlang的安装地址
将%ERLANG_HOME%\bin加入到path中
3.下载并安装RabbitMQ,下载地址:http://www.rabbitmq.com/download.html
注意: RabbitMQ 它依赖于Erlang,需要先安装Erlang。
启动:RabbitMq Service start,如果报错“发生系统错误1067”,更换erlang或者rabbitmq对应版本。
7 rabbitmq管理平台端口号介绍
访问RabbitMQ 管理平台地址 http://127.0.0.1:15672
默认账号:guest/guest 用户可以自己创建新的账号
注:第一次访问http://127.0.0.1:15672失败。
解决方案:
打开cmd进入RabbitMQ Server的开始菜单安装目录\sbin
输入rabbitmq-plugins enable rabbitmq_management
再启动sever 尝试访问,问题解决
默认的端口15672:rabbitmq管理平台端口号
默认的端口5672:rabbitmq消息中间内部通讯的端口
默认的端口号25672:rabbitmq集群的端口号
8 VirtualHosts的核心作用
像mysql有数据库的概念并且可以指定用户对库和表等操作的权限,RabbitMQ也有类似的权限管理。
在RabbitMQ中可以使用虚拟消息服务器VirtualHost,每个VirtualHost相当于一个相对独立的RabbitMQ服务器,每个VirtualHost之间是相互隔离的,exchange、queue、message不能互通。
9 rabbitmq创建Virtual Hosts
10 简单工作队列之生产者投递消息
快速入门RabbitMQ简单队列
Maven依赖
<dependencies>
<dependency>
<groupId>com.rabbitmq</groupId>
<artifactId>amqp-client</artifactId>
<version>3.6.5 </version>
</dependency>
</dependencies>
建立连接
public class RabitMQConnection {
public static Connection getConnection() throws IOException, TimeoutException {
// 1.创建连接
ConnectionFactory connectionFactory = new ConnectionFactory();
// 2.设置连接地址
connectionFactory.setHost("127.0.0.1");
// 3.设置端口号
connectionFactory.setPort(5672);
// 4.设置账号和密码
connectionFactory.setUsername("mayikt");
connectionFactory.setPassword("123456");
// 5.设置VirtualHost
connectionFactory.setVirtualHost("/mayikt_rabbitmq");
return connectionFactory.newConnection();
}
}
生产者
public class Producer {
private static final String QUEUE_NAME = "mayikt";
public static void main(String[] args) throws IOException, TimeoutException {
System.out.println("生产者启动成功..");
// 1.创建连接
Connection connection = RabitMQConnection.getConnection();
// 2.创建通道
Channel channel = connection.createChannel();
for (int i = 0; i < 10; i++) {
String msg = "每特教育第六期突破3万月薪" + i;
channel.basicPublish("", QUEUE_NAME, null, msg.getBytes());
System.out.println("生产者发送消息成功:" + msg);
}
channel.close();
connection.close();
}
}
运行结果:
11 简单工作队列之消费者消费消息
消费者
public class Consumer {
private static final String QUEUE_NAME = "mayikt";
public static void main(String[] args) throws IOException, TimeoutException {
// 1.创建连接
Connection connection = RabitMQConnection.getConnection();
// 2.创建通道
Channel channel = connection.createChannel();
DefaultConsumer defaultConsumer = new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
String msg = new String(body, "UTF-8");
System.out.println("消费消息msg:" + msg);
}
};
// 3.创建监听的消息
channel.basicConsume(QUEUE_NAME, true, defaultConsumer);
}
}
运行结果: