热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

浅谈对RabbitMQ的认识

一.什么是消息队列?什么时候使用它?在传统的web架构中(此处特指JavaSSM架构),用户在web中进行了某项需要和后台产生交互的操作后,一般都要开启一个session,从view层开

一.什么是消息队列?什么时候使用它


  在传统的web架构中(此处特指Java SSM架构),用户在web中进行了某项需要和后台产生交互的操作后,一般都要开启一个session,从view层开始,由controller层寻找相应的模型构件,找到相应的model后,生成相应的Java bean,再由Spring将bean映射到逻辑层,找到相关业务逻辑后,调用持久层框架,由数据库进行数据操作。可以看出,实际的业务逻辑十分复杂,在业务逻辑不多时尚可接受,但由于大多数数据库更新采用的是串行的方式,所有操作都需要在上一个操作完成后才能开始,就拿最常见的注册账号操作来说,常规操作下,用户输入基本信息以后,服务器响应时间我们假设为50ms,验证验证码的正确也需要50ms,验证手机号或者邮箱同样需要50ms,那么加起来就需要150ms。可以看出,在数据库操作数量增大后,即使是一个非常简单的select操作,也需要产生不小的服务器负担,一旦业务量也同时增大,很可能会造成服务器卡顿甚至宕机,给用户带来极差的体验。而之前的解决方法,是使用COOKIE技术,即将数据存放到客户端的浏览器上,但COOKIE技术虽然简化了业务流程,随之而来的是安全性的降低。某些居心不良的用户可能会修改本地COOKIE,具有很大的安全隐患。(补充一句,也可以通过对SQL本身的优化,通过调整行级锁来达到最佳的锁粒性,具体可以参考《高性能mySQL》一书,本文不做赘述。)

  因此,我们引入了消息中间件(Message-oriented middleware,MOM)技术。消息代理服务器通过将用户消息暂存到一个消息容器中,将一系列复杂的业务流程进行解耦,每个模块只需要完成它对应的功能,不需要关心别的模块。画一张图以便大家理解。

  可以看到,通过使用MOM技术,我们将原本可能需要150ms的业务流程缩短到了只需要70ms(实际上优化的时间会更多,因为RabbitMQ的特色正是响应时间极短,达到了微秒级)。同时,实现了业务的解耦,验证手机号时不需要关心用户此时有没有通过验证码。当然,如果并发量太大,我们可以在超过消息队列最大吞吐量后,选择抛弃用户请求,或者直接将用户重定向至报错页面。根据采用技术的不同,最大吞吐量也有所不同,本文介绍的RabbitMQ可达到万级,如果并发量大于万级,可以采用Kafka等技术。

  当然,一种技术不可能只有优点而没有缺点。我个人对MOM的理解是这样的,首先它确实对高并发场景有很大的帮助,比如双十一等访问量激增的时候,可以有效帮助服务器进行错峰。同时对各模块进行解耦,使系统各模块间的依赖度降低,不至于一个模块挂了整个系统全部瘫痪。最后,MOM是一种异步请求,无需服务器响应就可以发送下一个请求。但是,与之伴生的是,它对服务器压力的激增,和一系列的现实问题。我打个比方,就拿双十一抢购来说,假如采用了MOM技术,用户下的订单被存在消息队列服务器上,此时,如果后台的库存临时出现变化了,比如某个人下了很多订单突然退单了,由于数据尚未存入数据库,其可能会产生一些影响,又或者说在后续的某个部分, 比如你下了订单以后,后续的手机号填错了,此时你已经通过了下单模块,订单信息已经存入了消息队列服务器中,但后续本该异步的出现了错误,那可能就会出现脏读的情况。当然这些问题都是可以通过一 系列预案,用复杂的逻辑判断来规避的,但势必增加了系统出错的风险,因为系统的复杂性被大大地增加了。更需要注意的是,虽然系统各模块间的依赖度降低了,但这是建立在对消息队列服务器的依赖上的,如果消息队列服务器挂了呢?所以,每项技术都有其应用场景,我们应该根据实际使用情况,来具体分析要不要使用MOM技术。

 

二.AMQ协议


 

  RabbitMQ基于AMQP规范,AMQP规范不仅定义了一种网络协议,也定义了服务器端的服务和行为。这就是高级消息队列(Advanced Message Queuing,AMQ)模型,其在逻辑上定义了三种抽象组件用于指定消息的路由行为:

·交换器(Exchange),消息代理服务器中用于把消息路由到队列的组件。

·队列(Queue),用来存储消息的数据结构,位于硬盘或内存中。

·绑定(Binding),一套规则,用于告诉交换器消息应该被存储到哪个队列。

  一个AMQP可以有多个信道,允许服务器和客户端之间进行多次通信,这就是多路复用。需要注意的是,在尝试声明一个与现有队列同名的信道时,如果新队列的属性与现有队列不一样,那么RabbitMQ将关闭RPC请求的信道。 要正确处理错误,你的客户端应用程序应该监听来自RabbitMQ的Channel.Close命令,以便能够正确响应。有的客户端可能会通过在Channel.Close命令注册一个回调方法来自动触发。

  低层AMQP帧是由五个不同的组件构成的,其分别是:

 ·   帧类型
 ·   信道编号
 ·   以字节为单位的帧大小
 ·   帧有效载荷
 ·   结束字节标记(ASCII值206)
  低层AMQP帧的头部是三个字段,这三个字段组合起来被称为帧头。第一个字段是指示帧类型的单个字节,第二个字段指定帧的信道,第三个字段携带帧有效载荷的字节大小。
 
  在帧内部,位于头部之后和结束字节标记之前的内容就是帧的有效载荷。帧的设计是为了保护其携带内容的完整性。 
 
  AMQP的帧类型同样分为五种:协议头帧,方法帧,内容头帧,消息体帧,心跳帧。其中协议头帧用于连接到RabbitMQ,仅使用一次。方法帧携带发送给RabbitMQ或从RabbitMQ接收到的RPC请求或响应。内容头帧包含一条信息的大小和属性。消息体帧包含消息的内容。心跳帧在客户端与RabbitMQ之间进行传递,作为一种校验机制确保连接的两端都可用,且均在正常工作。 

三.RabbitMQ集群
  消息队列中间件技术是分布式系统中的重要组件,因此,我们需要对RabbitMQ集群有一定的认识。维护集群所需的工作和开销与集群中节点的数量多少有关,通俗一点来说,也就是越大的系统,就需要占用越多的额外资源对其进行管理,其遵循木桶原理,与集群中最慢的那个节点的响应速度有关。一般来说,RabbitMQ集群至少需要两个节点,至多在32-64个之间,因为其系统的复杂度是非线性上升的,系统中的每一个节点都需要了解其他节点的情况,这导致了你每添加一个新的节点,复杂性就会成指数化上升。不过,官方提供了一个工具,RabbitMQ UI,来解决这一问题,其可以很好地管理大型RabbitMQ集群。
  此外,向RabbitMQ添加的节点必须是磁盘节点或者内存节点。如果集群拥有大量的运行时状态时,相比内存节点,磁盘节点更容易收到磁盘I/O的影响。
内存节点仅将运行时状态信息存储在内存数据库中。可以说两种存储方式各有优劣,需要开发人员根据实际需求去进行判断。需要注意的是,集群里至少应当存在一个磁盘节点,因为一旦集群出现问题崩溃,崩溃的内存节点再次加入集群时,不会包含任何之前存储的信息,换而言之,这就是一个全新加入的节点,因此,需要磁盘节点将配置信息发送给它,如果有多个磁盘节点,那么应该把整个集群都关闭,再按照顺序重启节点,优先启动拥有最多正确状态的那个节点。
  有两种方式向集群中添加节点,其一是修改rabbitmq.cfg文件,来定义集群中的每个节点。因为有很多自动配置管理工具,比如Chef,Puppet等,这种方式更简单且不容易出错。第二种方式是通过使用cmd或者shell命令行来添加节点,这种方法工作量大,且相对来说不严格,但更有助于操作人员了解集群降级问题的排查,有兴趣的朋友可以自行了解一下erlang COOKIE及其对RabbitMQ集群的应用。
 
结束语
  本人的第一篇技术博客就暂时到此为止,本文仅涉及到原理和应用部分,希望自己以后有空详细讲一下RabbitMQ如何实际开发(希望懒癌以后每周都能更新一篇博客啦)另外有不正之处也望各位大神能多多指教,毕竟这是我的一家之言,其肯定有不足之处。 本文系我原创,如需转载,请联系我本人,并注明出处,如有侵权,必追究其法律责任。
 
参考书目:
Gavin M.Roy.RabbitMQ in Depth[M],2018.6,21-24.
 
 
 

推荐阅读
  • 总结:常见php页面漏洞分析及相关问题解决
    php教程|php手册PHP,phpBB,topic,Socket,SQLphp教程-php手册  从现在的网络安全来看,大家最关注和接触最多的WEB页面漏洞应该是ASP了,在这方 ... [详细]
  • 目录浏览漏洞与目录遍历漏洞的危害及修复方法
    本文讨论了目录浏览漏洞与目录遍历漏洞的危害,包括网站结构暴露、隐秘文件访问等。同时介绍了检测方法,如使用漏洞扫描器和搜索关键词。最后提供了针对常见中间件的修复方式,包括关闭目录浏览功能。对于保护网站安全具有一定的参考价值。 ... [详细]
  • 如何实现织梦DedeCms全站伪静态
    本文介绍了如何通过修改织梦DedeCms源代码来实现全站伪静态,以提高管理和SEO效果。全站伪静态可以避免重复URL的问题,同时通过使用mod_rewrite伪静态模块和.htaccess正则表达式,可以更好地适应搜索引擎的需求。文章还提到了一些相关的技术和工具,如Ubuntu、qt编程、tomcat端口、爬虫、php request根目录等。 ... [详细]
  • 本文详细介绍了SQL日志收缩的方法,包括截断日志和删除不需要的旧日志记录。通过备份日志和使用DBCC SHRINKFILE命令可以实现日志的收缩。同时,还介绍了截断日志的原理和注意事项,包括不能截断事务日志的活动部分和MinLSN的确定方法。通过本文的方法,可以有效减小逻辑日志的大小,提高数据库的性能。 ... [详细]
  • Linux如何安装Mongodb的详细步骤和注意事项
    本文介绍了Linux如何安装Mongodb的详细步骤和注意事项,同时介绍了Mongodb的特点和优势。Mongodb是一个开源的数据库,适用于各种规模的企业和各类应用程序。它具有灵活的数据模式和高性能的数据读写操作,能够提高企业的敏捷性和可扩展性。文章还提供了Mongodb的下载安装包地址。 ... [详细]
  • web.py开发web 第八章 Formalchemy 服务端验证方法
    本文介绍了在web.py开发中使用Formalchemy进行服务端表单数据验证的方法。以User表单为例,详细说明了对各字段的验证要求,包括必填、长度限制、唯一性等。同时介绍了如何自定义验证方法来实现验证唯一性和两个密码是否相等的功能。该文提供了相关代码示例。 ... [详细]
  • 本文介绍了Composer依赖管理的重要性及使用方法。对于现代语言而言,包管理器是标配,而Composer作为PHP的包管理器,解决了PEAR的问题,并且使用简单,方便提交自己的包。文章还提到了使用Composer能够避免各种include的问题,避免命名空间冲突,并且能够方便地安装升级扩展包。 ... [详细]
  • 本文介绍了一种轻巧方便的工具——集算器,通过使用集算器可以将文本日志变成结构化数据,然后可以使用SQL式查询。集算器利用集算语言的优点,将日志内容结构化为数据表结构,SPL支持直接对结构化的文件进行SQL查询,不再需要安装配置第三方数据库软件。本文还详细介绍了具体的实施过程。 ... [详细]
  • c语言 怎么访问64位地址_C语言调动硬件的原理是什么?
    大家都知道我们可以使用C语言写一段程序来控制硬件工作,但你知道其工作原理吗?1c语言在实际运行中,都是以汇编指令的方式运行的,由编译器把C ... [详细]
  • 一.常见基于身份识别进行反爬1通过headers字段来反爬headers中有很多字段,这些字段都有可能会被对方服务器拿过来进行判断是否为爬虫1.1通过headers中的User-A ... [详细]
  • mysql字符集和表字符集_Mysql数据库表引擎与字符集
    Mysql数据库表引擎与字符集1.服务器处理客户端请求其实不论客户端进程和服务器进程是采用哪种方式进行通信,最后实现的效果都是:客户端进程向服务器进程发送一段文本(MySQL语句) ... [详细]
  • 文件上传漏洞利用介绍
    目录文件上传漏洞利用介绍1.绕过js验证2.绕过MIME-TYPE验证3.绕过基于黑名单验证基于文件后缀名验证介绍基于文件后缀名验证方式的分类基于黑名单验证代码分析利 ... [详细]
  • 点此学习更多SQL相关函数与字符串处理函数mysql函数一、简明总结ASCII(char)        返回字符的ASCII码值BIT_LENGTH(str)      返回字 ... [详细]
  • 你知道Kafka和Redis的各自优缺点吗?一文带你优化选择,不走弯路 ... [详细]
  • 开发笔记:GD库的基本信息,图像的旋转水印缩略图验证码,以及图像类的封装
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了GD库的基本信息,图像的旋转水印缩略图验证码,以及图像类的封装相关的知识,希望对你有一定的参考价值。GD ... [详细]
author-avatar
太2真人05
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有