1.引入——传统的Http请求的缺点
Http请求是同步的,也就是说必须和服务端建立连接,当服务端接收的请求过大时,给客户端的响应就不够及时如下图所示
每当客户端向tomcat服务器发送一个请求,tomcat服务器当中就会创建一个线程,而且这个线程不是无限的,有一个最大线程数。当我的请求数量大于这个最大线程数的时候,多余的请求就要缓存到队列里。这就有可能导致客户端长时间得不到响应。客户体验非常差。如果客户端一直等着没有收到服务端的响应的话那么可能引起超时重传,同一个请求传好几遍,有可能引发幂等性问题。
2.MQ应用场景有哪些
在一些耗时操作都可以使用到MQ,比如下面这个例子。
2.1 http同步方案的缺点
如下图所示
这是一个会员注册业务逻辑,客户端向服务段发送了一个请求Request,然后在服务端需要做如下操作,首先我插入一条会员数据1s,然后向用户发送登录短信提醒3s,然后发送新人优惠劵3s。也就是说假如我是用户我从发送请求到接收一共需要7s,搁我我是受不了。
2.2 多线程实现异步解耦的优缺点
为了优化这个接口响应时间,提高用户的满意度我们可以通过多线程的方式实现异步解耦,从而降低响应时间,如下图所示
- 优点
我单独开启一个线程去处理发送短信和发送新人优惠劵,这样的话我只需要在插入会员数据1s之后就可以返回OK,至于说剩下的发短信和发优惠券我可以在这个线程中慢慢处理。就算我发短信和发优惠券出现什么意外,我也可以一直重试。 - 缺点
我新开的这个线程会和Tomcat中的处理请求的线程发生竞争,他们存在着上下文切换对CPU资源消耗比较大。
2.3 MQ实现异步解耦
如图所示,客户端会向服务端发送请求,然后服务端会立刻插入会员服务向客户端反馈响应成功。然后服务端会打包一个msg报文,发送给消息队列通过消息队列传输到发送登录短信提醒和发送新人优惠券的活动。
这个就相当于消费者通过消息中间件调用生产者的模型,图中插入会员服务属于消费者服务,他发送一个msg给队列,然后通过消息队列传输到生产者服务,从而调用生产者。
2.4 MQ消息中间件常用名词
Producer 生产者:投递消息到MQ服务器端
Consumer 消费者:从MQ服务端获取消息处理业务逻辑
Broker:MQ服务器端
Topic:主题:分类业务逻辑发送短信主题
Queue:存放消息模型,队列,先进后出,后进后出原则,数组/链表。
Message:生产者投递消息报文:json
3. MQ是如何实现抗高并发的
假如说这时候有10万个请求,如果这10万个请求都打给服务器,服务器端又有很耗时的操作那么整个服务器估计就崩了。通过MQ我们可以把10万条消息都放到消息队列中,让消费者一点一点从里面拿,这样就可以有效地保证高并发环境下的可用性。但是这个也有缺点就是存在延迟的问题。
当MQ里面的消息多到一定程度,而我的消费者要处理完这些消息需要很长时间的时候就容易出现延迟问题,要解决这个问题我们可以让生产者变成一个集群这样的话就可以加快消息的处理速度,就可以避免延迟的发生。
4.主流MQ的对比
ActiveMQ | RabbitMQ | RocketMQ | Kafka | |
开发语言 | Java | erlang | Java | scala |
单机吞吐量 | 万级 | 万级 | 10万级 | 10万级 |
时效性 | ms级 | us级 | ms级 | ms级以内 |
可用性 | 高(主从架构) | 高(主从架构) | 非常高(分布式架构) | 非常高(分布式架构) |
功能特性 | 成熟的产品,在很多公司得到应用;有较多的文档;各种协议支持较好 | 基于erlang开发所以并发能力很轻,性能机器号,延时很低管理界面 丰富 | MQ功能比较完备,扩展性佳 | 只支持主要的MQ功能,像一些消息查询,消息回溯等功能没有提供,在大数据领域应用广。 |