本文章的内容是根据书籍《从零开始学架构》整理的资料,供作者以及读者查阅。
软件架构指软件系统的顶层架构。详细阐述如下:
a. “系统由一群关联个体组成”,个体分别是:系统、子系统、模块、组件等。架构需要明确系统包含哪些“个体”。
b. 系统中的个体需要“按照某种规则”运作,架构需要明确个体运作和协作的规则。
(1)机器语言:其是最早的开发语言,直接使用0和1来表示机器可以识别的指令和数据。主要问题:太难写、太难读、太难改。
(2)汇编语言:为了解决机器语言的问题,汇编语言应运而生。汇编语言虽然解决了机器语言读写复杂的问题,但本质还是面向机器的,因为需要我们精确了解计算底层的知识才可编写汇编语言。
(3)高级语言:为了解决汇编语言的问题,计算机前辈开始又设计了多个高级语言,其可以让程序员不需要关注机器底层的低级结构和逻辑,只需关注具体的问题和业务即可。优势:通过编译处理,高级语言可以被编译成适合不同CPU指令的机器语言。
(1)20世纪60年代第一次出现软件危机引入了“结构化编程”,创建了“模块”概念;
(2)20世纪80年代第二次软件危机引出了“面向对象编程”,创造了“对象”概念;
(3)20世纪90年代“软件架构”开始流行,创建了“组件”该鸟。
从软件开发历史可以看到,整个软件技术发展的历史,其实就是一部与“复杂度”斗争的历史,架构出现也不例外。架构设计主要目的就是为了解决复杂度带来的问题。
软件系统高性能带来的复杂度主要体现在:a. 单台计算机内部为了高性能带来的复杂度;b. 多台计算机集群为了高性能带来的复杂 度。
操作系统和性能相关的就是进程和线程,最早的计算机是没有操作系统的,只有输入、计算和输出功能,用户输入一指令,计算机完成操作。这样的处理性能是很低效的。
为了解决手工操作的低效性,批处理系统应运而生。批处理就是先把要执行的指令记下来(写在纸带、磁带、磁盘等),形成指令清单(任务),然后交给计算机执行。批处理操作系统负责读取任务进行处理,无需等待人工操作,这样性能就有了很大提升。但是具有明显缺点:计算机一次只能执行一个任务,例如现需从I/O设备读取大量数据,在进行I/O操作时,CPU其实是空闲的,而这个空闲时间是可以进行其他计算操作。
为了进一步提升性能,人们发明了“进程”,用进程对应一个任务,每个任务都有独立的内存空间,进程间互不相关,由操作系统进行调度。由于此时还没有多核和多线程的概念,为了达到多进程并行执行的目的,采取分时操作(即把CPU的时间分成很多片段,每片段只能执行某进程的指令)。
多进程虽然要求每个任务都有独立的空间,进程互不相关。但是在用户角度来看,如果进程在运行过程中可以进行通信会使任务设计更加灵活高效。例如现存在两个任务A和B,两任务不能相互通信,A只能将结果写入存储,B读取进行处理,这样不仅任务低效,而且任务设计更加复杂。为了解决此问题,进程间通信的各种方式被设计出来,如:管道、消息队列、信号量、共享存储等。
多进程可以使任务并行处理,但是进程内部只能串行处理,而进程内部之间的子任务有时也需要并行处理。为了解决此问题,人们又发明了线程(进程内部的子任务)。为了保证数据的完成性,又发明了互斥锁机制。有了多线程以后,操作系统的调度的最小单位是线程,资源分配的最小单位是进程。
操作系统发展到现在,如果我们需要完成一个高性能的软件系统,需考虑如下技术点:多进程、多线程、进程间通信、多线程并发等。
高可用是指“系统无中断的执行其功能”的能力,本质是通过“冗余”来实现高可用,即是通过增加更多机器来达到效果。
可扩展性是指系统为了应对将来需求变化而提供的一种扩展能力,当有新的需求出现时,系统无需或者少量修改就可以支持,无须整个系统重建或重构。