21 利用分布式消息队列降低系统耦合性
Posted water___Wang
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了21 利用分布式消息队列降低系统耦合性相关的知识,希望对你有一定的参考价值。
国内某大型互联网企业经常因为对同行的产品进行微创新,然后推岀自己的产品而遭人诟病,不讨论这种做法是否合适,我们分析这些产品,发现大多数都比原创产品有 更好的用户体验。这些产品常常后来居上,更速度地推岀新功能,吸引用户注意,进而 占据市场。
微信从发布到拥有1亿用户,仅仅用了一年的时间。而据说摇一摇这个功能是两个 实习生用一个星期就开发完成上线的。
使用TOP( Taobao Open API ), 一个技术熟练的淘宝客网站开发工程师只需要用几个 晚上的业余时间就可以开发部署一个炫目的购物导购网站。
如此轻易地就可以开发一个新产品,如此快速地就可以实现一个新功能,他们是如 何做到的?
为什么有的网站必须规定系统发布日,一到发布日就如临大敌,整个技术部加班通 宵达旦;而有的网站就可以随时发布,新功能可以随时快速上线。
这些都有赖于网站的扩展性架构设计,就是在对现有系统影响最小的情况下,系统 功能可持续扩展及提升的能力。
经常听到各种场合中对扩展性和伸缩性的误用,包括许多资深网站架构师也常常混淆两者,用扩展性表示伸缩性。在此,我们澄清下这两个概念。
扩展性(Extensibility)
指对现有系统影响最小的情况下,系统功能可持续扩展或提升的能力。表现在系统 基础设施稳定不需要经常变更,应用之间较少依赖和耦合,对需求变更可以敏捷响应。 它是系统架构设计层面的开闭原则(对扩展开放,对修改关闭),架构设计考虑未来功能 扩展,当系统增加新功能时,不需要对现有系统的结构和代码进行修改。
伸缩性(Scalability)
指系统能够通过增加(减少)自身资源规模的方式增强(减少)自己计算处理事务的能力。如果这种增减是成比例的,就被称作线性伸缩性。在网站架构中,通常指利用 集群的方式增加服务器数量、提高系统的整体事务吞吐能力。
1 构建可扩展的网站架构
开发低耦合系统是软件设计的终极目标之一,这一目标驱动着软件开发技术的创新 与发展,从软件与硬件的第一次分离到操作系统的诞生;从汇编语言到面向过程的开发语言,再到面向对象的编程语言;从各种软件工具集到各种开发框架;无不体现着降低 软件系统耦合性这一终极目标。可以说,度量一个开发框架、设计模式、编程语言优劣 的重要尺度就是衡量它是不是让软件开发过程和软件产品更加低耦合。
显而易见,低耦合的系统更容易扩展,低耦合的模块更容易复用,一个低耦合的系
统设计也会让开发过程和维护变得更加轻松和容易管理。一个复杂度为100的系统,如 果能够分解成没有耦合的两个子系统,那么每个子系统的复杂度不是50,而可能是25。
当然,完全没有耦合就是没有关系,也就无法组合出一个强大的系统。那么如何分解系 统的各个模块、如何定义各个模块的接口、如何复用组合不同的模块构造成一个完整的 系统,这是软件设计中最有挑战的部分。
笔者认为,软件架构师最大的价值不在于掌握多少先进的技术,而在于具有将一个 大系统切分成N个低耦合的子模块的能力,这些子模块包含横向的业务模块,也包含纵 向的基础技术模块。这种能力一部分源自专业的技术和经验,还有一部分源自架构师对 业务场景的理解、对人性的把握、甚至对世界的认知。
大型网站也常常意味着功能复杂,产品众多。网站为了在市场竞争中胜岀,不断推 出各种新产品,为了把握市场机会,这些产品从策划到上线,时间非常短暂,技术团队 必须在产品设计和需求分析结束之后,快速地开发完成一个新产品。同时经过长期的演 化和发展,这些产品之间的关系错综复杂,维护也变得异常困难。这些问题对网站的可 扩展架构提岀了挑战和要求。
设计网站可扩展架构的核心思想是模块化,并在此基础之上,降低模块间的耦合性, 提高模块的复用性。
我们在本书第6章讨论过网站通过分层和分割的方式进行架构伸缩,分层和分割也 是模块化设计的重要手段,利用分层和分割的方式将软件分割为若干个低耦合的独立的 组件模块,这些组件模块以消息传递及依赖调用的方式聚合成一个完整的系统。
在大型网站中,这些模块通过分布式部署的方式,独立的模块部署在独立的服务器 (集群)上,从物理上分离模块之间的耦合关系,进一步降低耦合性提高复用性。
模块分布式部署以后具体聚合方式主要有分布式消息队列和分布式服务。
2 利用分布式消息队列降低系统耦合性
如果模块之间不存在直接调用,那么新增模块或者修改模块就对其他模块影响最小, 这样系统的可扩展性无疑更好一些。
2.1 事件驱动架构
事件驱动架构(Event Driven Architecture ):通过在低耦合的模块之间传输事件消息, 以保持模块的松散耦合,并借助事件消息的通信完成模块间合作,典型的EDA架构就是 操作系统中常见的生产者消费者模式。在大型网站架构中,具体实现手段有很多,最常 用的是分布式消息队列,如图7.1所示。
消息队列利用发布一订阅模式工作,消息发送者发布消息,一个或者多个消息接收 者订阅消息。消息发送者是消息源,在对消息进行处理后将消息发送至分布式消息队列, 消息接受者从分布式消息队列获取该消息后继续进行处理。可以看到,消息发送者和消 息接受者之间没有直接耦合,消息发送者将消息发送至分布式消息队列即结束对消息的处理,而消息接受者只需要从分布式消息队列获取消息后进行处理,不需要知道该消息 从何而来。对新增业务,只要对该类消息感兴趣,即可订阅该消息,对原有系统和业务 没有任何影响,从而实现网站业务的可扩展设计。
消息接受者在对消息进行过滤、处理、包装后,构造成一个新的消息类型,将消息 继续发送出去,等待其他消息接受者订阅处理该消息。因此基于事件(消息对象)驱动 的业务架构可以是一系列的流程。
由于消息发送者不需要等待消息接受者处理数据就可以返回,系统具有更好的响应 延迟;同时,在网站访问高峰,消息可以暂时存储在消息队列中等待消息接受者根据自 身负载处理能力控制消息处理速度,减轻数据库等后端存储的负载压力。
2.2 分布式消息队列
队列是一种先进先出的数据结构,分布式消息队列可以看作将这种数据结构部署到 独立的服务器上,应用程序可以通过远程访问接口使用分布式消息队列,进行消息存取 操作,进而实现分布式的异步调用,基本原理如图7.2所示。
消息生产者应用程序通过远程访问接口将消息推送给消息队列服务器,消息队列服 务器将消息写入本地内存队列后立即返回成功响应给消息生产者。消息队列服务器根据 消息订阅列表查找订阅该消息的消息消费者应用程序,将消息队列中的消息按照先进先出(FIFO )的原则将消息通过远程通信接口发送给消息消费者程序。
目前开源的和商业的分布式消息队列产品有很多,比较著名的如Apache ActiveMQ 等,这些产品除了实现分布式消息队列的一般功能,在可用性、伸缩性、数据一致性、性能和可管理性方面也做了很多改善。
在伸缩性方面,由于消息队列服务器上的数据可以看作是被即时处理的,因此类似 于无状态的服务器,伸缩性设计比较简单。将新服务器加入分布式消息队列集群中,通 知生产者服务器更改消息队列服务器列表即可。
在可用性方面,为了避免消费者进程处理缓慢,分布式消息队列服务器内存空间不 足造成的问题,如果内存队列已满,会将消息写入磁盘,消息推送模块在将内存队列消 息处理完以后,将磁盘内容加载到内存队列继续处理。
为了避免消息队列服务器宕机造成消息丢失,会将消息成功发送到消息队列的消息存储在消息生产者服务器,等消息真正被消息消费者服务器处理后才删除消息。在消息 队列服务器宕机后,生产者服务器会选择分布式消息队列服务器集群中其他的服务器发 布消息。
分布式消息队列可以很复杂,比如可以支持ESB(企业服务总线)、支持SOA(面向 服务的架构)等;也可以很简单,比如用mysql也可以当作分布式消息队列:消息生产 者程序将消息当作数据记录写入数据库,消息消费者程序查询数据库并按记录写入时间 戳排序,就实现了一个事实上的分布式消息队列,而且这个消息队列使用成熟的MySQL 运维手段,也可以达到较高的可用性和性能指标。
以上是关于21 利用分布式消息队列降低系统耦合性的主要内容,如果未能解决你的问题,请参考以下文章