大型网站技术架构,7网站的可扩展架构之构建可扩展的网站和利用分布式消息队列降低系统耦合性
首先,澄清两个易混淆的概念:扩展性和伸缩性
扩展性(Extensibility)
指对现有系统影响最小的情况下,系统功能可持续扩展或提升的能力。表现在系统基础设施稳定不需要经常变更,应用之间较少依赖和耦合,对需求变更可以敏捷响应。
它是系统架构设计层面的开闭原则(对扩展开放,对修改关闭),架构设计考虑未来功能扩展,当系统增加新功能时,不需要对现有系统的结构和代码进行修改。
伸缩性(Scalability)
指系统能够通过增加(减少)自身资源规模的方式增强(减少)自己计算处理事务的能力。如果这种增减是成比例的,就被称作线下伸缩性。在网站架构中,通常指利用集群的方式增加服务器数量、提高系统的整体事务吞吐能力。
7.1 构建可扩展的网站
开发低耦合系统是软件设计的终极目标之一,这一目标驱动着软件开发技术的创新与发展,从软硬件分离到操作系统诞生从汇编语言到面向过程的开发语言,再到面向对象的编程语言;从各种软件工具集到各种开发框架;无不体现着降低软件系统耦合度的终极目标。
可以说,度量一个开发框架、设计模式、编程语言优劣的重要尺度就是衡量它是不是让软件开发过程和软件产品更加低耦合。
低耦合的系统更容易扩展,低耦合的模块更容易复用,一个低耦合的系统设计也会让开发过程和维护变得更加轻松和容易管理。
个人理解:对功能模块解耦、抽象出基础设施,进行低耦合的架构设计,是架构师乃至程序员最基本的素养。写代码不仅仅是写,也是设计,确保代码低耦合,可以复用,无状态,方法读写分离,方法本身幂等,类的单一职责等等。
当然,完全没有耦合就是没有关系,也就无法组合出一个强大的系统。
如何分解系统的各个模块、如何定义各个模块的接口、如何复用组合不同的模块构造成一个完整的系统,这时软件设计中最有挑战的部分。
个人理解:网站的架构目标是低耦合,可复用。所以先分割和分层,模块化,之后聚合,可以通过分布式消息队列和分布式服务(HTTP、RPC)。
软件架构师最大的价值不在于掌握多少先进的技术,而在于具有将一个大系统切分成N个低耦合的子模块的能力,这些子模块包含横向的业务模块,也包含纵向的基础技术模块。这种能力一部分源自专业的技术和经验,还有一部分源自架构师对业务场景的理解、对人性的把握、甚至对世界的认知。
个人理解:平时在业务评审,架构评审时,多关注别人是如何考虑拆分的,积极参与讨论和提问,从中深刻理解拆分的思路。
设计网站可扩展架构的核心思想是模块化,并在此基础之上,降低模块间的耦合性,提高模块的复用性。
网站通过分层和分割的方式进行架构伸缩,分层和分割也是模块化设计的重要手段,利用分层和分割的方式将软件分割为若干个低耦合的独立组件模块,这些组件模块以消息传递及依赖调用的方式聚合成一个完整的系统。
大型网站中,这些模块通过分布式部署的方式,独立的模块部署在独立的服务器(集群)上,从物理上分离模块之间的耦合关系,进一步降低耦合性提高复用性。
模块分布式部署以后,具体的聚合方式主要有分布式消息队列和分布式服务。
7.2 利用分布式消息队列降低系统耦合性
对于模块之间不存在直接调用的情况,新增模块或修改模块对其他模块影响最小,这样系统的可扩展性无疑更好一些。
7.2.1 事件驱动架构
事件驱动架构(Event Driven Architecture):通过在低耦合的模块之间传输事件消息,以保持模块的松散耦合,并借助事件消息的通信完成模块间的合作,典型的EDA架构就是操作系统中常见的生产者消费者模式。在大型网站架构中,具体实现手段有很多,最常用的是分布式消息队列,如下图所示:
对于架构里面的很多概念,如果因为经验而有自己的总结,但是又说不好关键的名词解释,就是缺少理论先行的学习。即平时都在用或者有架构上的思考,但是说不好理论的东西,这个对于非科班的我可能是一个痛点。
不过也容易解决,就是通过看书系统学习理论,比如这本书可以学到很多架构理论和常识。并且也和作者产生许多共鸣,所以更应该坚持把本书看完,加油自己!
消息队列利用发布-订阅模式工作,消息发送者发布消息,一个或多个消息消息接收者订阅消息。
消息发送者是消息源,在对消息进行处理后将消息发送至分布式消息队列,消息接收者从分布式消息队列获取该消息后继续进行处理。
消息发送者和消息接收者之间没有直接耦合,消息发送者将消息发送至分布式消息队列即结束对消息的处理,而消息接收者只需要从分布式消息队列获取消息后进行处理,不需要知道该消息从何而来。
对新增业务,只要对该类消息感兴趣,即可订阅该消息,对原有系统和业务没有任何影响,从而实现网站业务的可扩展设计。
消息接收者在对消息进行过滤、处理、包装后,构造成一个新的消息类型,将消息继续发送出去,等待其他消息接收者订阅处理该消息。因此基于事件(消息对象)驱动的业务架构可以是一系列的流程。
由于消息发送者不需要等待消息接收者处理数据就返回,系统具有更好的响应延迟;
同时,在网站访问高峰,消息可以暂时存储在消息队列中等待消息接收者根据自身负载处理能力控制消息处理速度,减轻数据库等后端存储的负载压力。
7.2.2 分布式消息队列
队列是一种先进先出的数据结构,分布式消息队列可以看作将这种数据结构部署到独立的服务器上,应用程序可以通过远程访问接口使用分布式消息队列,进行消息存取操作,进而实现分布式的异步调用,基本原理如下图所示:
消息生产者应用程序通过远程访问接口将消息推送给消息队列服务器,
消息队列服务器将消息写入本地内存队列后立即返回成功响应给消息生产者。
消息队列服务器根据消息订阅列表查找订阅该消息的消息消费者应用程序,将消息队列中的消息按照先进先出(FIFO)的原则将消息通过远程通信接口发送给消息消费者程序。
目前的分布式消息队列,在伸缩性方面,由于消息队列服务器上的数据可以看作是被即时处理的,因此类似于无状态的服务器,伸缩性设计比较简单。将新服务器加入分布式消息队列集群中,通知生产者服务器更改消息队列服务器列表即可。
在可用性方面,为了避免消费者进程处理缓慢,分布式消息队列服务器内存空间不足造成的问题,如果内存队列已满,会将消息写入磁盘,消息推送模块在内存队列消息完以后,将磁盘内容加载到内存队列继续处理。
为了避免消息队列服务器宕机造成消息丢失,会将消息成功发送到消息队列的消息存储在消息生产者服务器,等消息真正被消费者服务器处理后才删除消息。在消息队列服务器宕机后,生产者服务器会选择分布式消息队列服务器集群中其他的服务器发布消息。
分布式消息队列可以很复杂,比如可以支持ESB(企业服务总线)、支持SOA(面向服务的架构)等;
也可以很简单,比如用MySQL也可以当做分布式消息队列:
消息生产者程序将消息当做数据记录写入数据库,消息消费者程序查询数据库并按记录写入时间戳排序,就实现了一个事实上的分布式消息队列,而且这个消息队列使用成熟的MySQL运维手段,可以达到较高可用和性能指标。
目前牛逼的开源分布式消息中间件有Kafka、RocketMQ
作者: 元宝爸爸
出处:https://www.cnblogs.com/wozixiaoyao/p/11965398.html
版权:本文采用「署名-非商业性使用-相同方式共享 4.0 国际」知识共享许可协议进行许可。
觉得文章不错,点个关注呗!