Fork me on GitHub

架构学习笔记

模块和组件有什么区别?

模块和组件都是一个系统的组成部分,只是从不同的角度拆分系统而已.
从业务逻辑的角度来拆分系统,得到的单元是”模块”, 划分”模块”的目的是业务之间的解耦,职责分离.
从物理的角度来拆分系统后,得到的单元是”组件”,划分组件的目的是为了单元复用.

比如一个学生管理系统, 从业务逻辑上分为”登录模块”,”个人信息模块”,”选课模块”, 单纯从物理的角度来拆分,可以拆分为”Nginx 组件”,”MySQL”组件,”Web 服务器组件”.

架构和框架是什么关系?

什么是框架?
框架是组件规范,框架提供了基础功能的产品,比如 Spring 的注解, SpringJPA 等.

什么是架构?
架构是软件系统的基础结构,比如 MVC 的架构

二者区别
二者是从不同的角度来看待系统,不同的角度可以将系统划分为不同的结构

什么是架构?

综上所述, 架构师软件系统的顶层结构.

架构设计的历史背景

从一开始的模块,到后来的对象,再到现在的组件,本质上都是对一定规模的软件进行拆分,差别只是在于随着软件的复杂程度不断增加,拆分的粒度越来越粗,层次越来越高. 系统越庞大,越可能面临软件架构相关的问题,因为越庞大的系统内部耦合越严重,扩展更加困难,逻辑更加复杂.

架构设计的目的

通过回顾架构设计的历史背景, 我们可以得出结论,架构设计的目的就是为了解决软件系统复杂度带来的问题.

复杂度来源:高性能

单机复杂度

比如操作系统,线程,多线程,多进程,进程间通信,并发等问题.举个例子: Nginx 可以用多进程也可以用多线程, Redis 采用的是单进程, Memcache 采用的是多线程.

集群的复杂度

05 | 复杂度来源:高可用

高可用定义

系统无中断地执行其功能的能力,代表系统的可用性程度,系统的高可用方案五花八门,但万变不离其宗,本质上都是通过“冗余”来实现高可用.

计算高可用

这里的“计算”指的是业务的逻辑处理。你需要增加一个任务分配器,选择合适的任务分配器也是一件复杂的事情,需要综合考虑性能、成本、可维护性、可用性等各方面因素。

存储高可用

综合分析,无论是正常情况下的传输延迟,还是异常情况下的传输中断,都会导致系统的数据在某个时间点或者时间段是不一致的,而数据的不一致又会导致业务问题;但如果完全不做冗余,系统的整体高可用又无法保证,所以存储高可用的难点不在于如何备份数据,而在于如何减少或者规避数据不一致对业务造成的影响。

06 | 复杂度来源:可扩展性

可扩展性指系统为了应对将来需求变化而提供的一种扩展能力,当有新的需求出现时,系统不需要或者仅需要少量修改就可以支持,无须整个系统重构或者重建。

设计具备良好可扩展性的系统,有两个基本条件:正确预测变化、完美封装变化。但要达成这两个条件,本身也是一件复杂的事情,我来具体分析一下。

1 What:什么是架构的可扩展性?

业务需求、运行环境方面的变化都会导致软件系统发生变化,而这种软件系统对上述变化的适应能力就是可扩展性。

可扩展性可以理解为是一种从功能需求方面考虑的软件属性,属性就会存在好坏之分。

按照可扩展性的定义,一个具备良好可扩展性的架构设计应当符合开闭原则:对扩展开放,对修改关闭。衡量一个软件系统具备良好可扩展性主要表现但不限于:(1)软件自身内部方面。在软件系统实现新增的业务功能时,对现有系统功能影响较少,即不需要对现有功能作任何改动或者很少改动。(2)软件外部方面。软件系统本身与其他存在协同关系的外部系统之间存在松耦合关系,软件系统的变化对其他软件系统无影响,其他软件系统和功能不需要进行改动。反之,则是一个可扩展性不好的软件系统。

2 Why:为什么要求架构具备良好的可扩展性?

伴随业务的发展、创新,运行环境的变化,对技术也就提出了更多、更高的要求。能够快速响应上述变化,并最大程度降低对现有系统的影响,是设计可扩展性好的架构的主要目的。

3 How:如何设计可扩展性好的架构?

面向对象思想、设计模式都是为了解决可扩展性的而出现的方法与技术。

设计具备良好可扩展性的系统,有两个思考角度:(1)从业务维度。对业务深入理解,对可预计的业务变化进行预测。(2)从技术维度。利用扩展性好的技术,实现对变化的封装。

(1)在业务维度。对业务深入理解,对业务的发展方向进行预判,也就是不能完全不考虑可扩展性;但是,变化无处不在,在业务看得远一点的同时,需要注意:警惕过度设计;不能每个设计点都考虑可扩展性;所有的预测都存在不正确的可能性。

(2)在技术维度。预测变化是一回事,采取什么方案来应对变化,又是另外一个复杂的事情。即使预测很准确,如果方案不合适,则系统扩展一样很麻烦。第一种应对变化的常见方案是将“变化”封装在一个“变化层”,将不变的部分封装在一个独立的“稳定层”。第二种常见的应对变化的方案是提炼出一个“抽象层”和一个“实现层”。

4.在实际工作场景中的解决方案
在实际软件系统架构设计中,常通过以下技术手段实现良好的可扩展性:(1)使用分布式服务(框架)构建可复用的业务平台。(2)使用分布式消息队列降低业务模块间的耦合性。

(1)分布式服务框架
利用分布式服务框架(如Dubbo)可以将业务逻辑实现和可复用组件服务分离开,通过接口降低子系统或模块间的耦合性。新增功能时,可以通过调用可复用的组件实现自身的业务逻辑,而对现有系统没有任何影响。可复用组件升级变更的时候,可以提供多版本服务对应用实现透明升级,对现有应用不会造成影响。

(2) 分布式消息队列
基于生产者-消费者编程模式,利用分布式消息队列(如RabbitMQ)将用户请求、业务请求作为消息发布者将事件构造成消息发布到消息队列,消息的订阅者作为消费者从消息队列中获取消息进行处理。通过这种方式将消息生产和消息处理分离开来,可以透明地增加新的消息生产者任务或者新的消息消费者任务。

07 | 复杂度来源:低成本、安全、规模