1. 原始分布式时代
这个时代(20世纪70年代末期到80年代初)的计算机计算能力非常有限(内存只有几百K),所以科学家就寻求通过多台计算机来完成一个功能,这个时代被称为原始分布式时代。
但是这个时代对分布式系统的尝试并没有取得太大的成绩。但也不是一无所成,这个时代的探索,出现了远程调用,分布式文件系统的雏型,为后续计算机学科的发展奠定了基础。
IBM院士Kyle Brown事后曾评价道,“这次尝试最大的收获就是对RPC、DFS等概念的开创,以及得到了一个价值千金的教训:某个功能能够进行分布式,并不意味着它就应该进行分布式,强行追求透明的分布式操作,只会自寻苦果。”
无论是DCE还是稍后出现的CORBA,从结果来看,都不能称得上成功,因为将一个系统拆分到不同的机器中运行,为解决这样做带来的服务发现、跟踪、通信、容错、隔离、配置、传输、数据一致性和编码复杂度等方面的问题所付出的代价已远远超过了分布式所取得的收益。
关于DCE的一点介绍
DCE是当时业界主流的计算机厂商一起参与,共同制订了名为“分布式运算环境[2]”(Distributed Computing Environment,DCE)的分布式技术体系。
DCE包含一套相对完整的分布式服务组件规范与参考实现,譬如源自NCA(惠普公司)的远程服务调用规范(Remote Procedure Call,RPC),当时被称为DCE/RPC,它与后来Sun公司向互联网工程任务组(Internet Engineering Task Force,IETF)提交的基于通用TCP/IP协议的远程服务标准ONC RPC被认为是现代RPC的共同鼻祖。
源自AFS(卡内基梅隆大学提出)的分布式文件系统(Distributed File System,DFS)规范,当时被称为DCE/DFS;
源自Kerberos(麻省理工大学提出)的服务认证规范;
还有时间服务、命名与目录服务,甚至现在程序中很常用的通用唯一识别符(Universally Unique Identifier,UUID)也是在DCE中发明出来的。
UNIX分布式设计哲学
保持接口与实现的简单性,比系统的任何其他属性,包括准确性、一致性和完整性,都来得更加重要。
但是基于那个时代的计算机技术,想要发展符合UNIX设计哲学的分布式技术不太可能,只能是一种美好的愿景。
2. 单体应用时代
20世纪80年代正是摩尔定律开始稳定发挥作用的黄金时期,微型计算机的性能以每两年增长一倍的惊人速度提升,硬件算力束缚软件规模的链条很快变得松动,信息系统进入以单台或少量几台计算机即可作为服务器来支撑大型信息系统运作的单体时代,且在很长的一段时间内,单体都将是软件架构的绝对主流。
在很多书中都将单体架构作为一种反派角色出现,我甚至在面试过程中遇到过面试官在还没了解项目需求的情况下就直接说你们这种单体架构是有问题的。其实没有放之四海而皆准的架构,单体架构在某些情况下可能是最优选择,单体架构更不应该被打上反派角色。
比如,对于小型系统,单台机器就足以支撑其良好运行的系统,不仅易于开发、测试、部署,且由于系统中各个功能、模块、方法的调用过程都是进程内调用,不会发生进程间通信(Inter-ProcessCommunication,IPC[1]),因此连运行效率也是最高的。
那些不顾需求现状,为了微服务而微服务的开发者才是真正的“反派”。
单体系统的不足,必须在软件的性能需求超过了单机、软件的开发人员规模明显超过了“2 Pizza Team”(6~12人)范畴的前提下才有讨论的价值。
上面讲到的是单体架构的优点,在互联网时代(复杂系统),单体架构存在两点明显的缺点:
-
单机性能难以保证:一个应用中功能越堆越多,单台机器已经难以满足这些功能,摩尔定律失效让堆硬件的做法变成了奢望;
-
缺乏自治隔离能力:比如说一部分的代码出现Bug可能会导致整个服务不可用,比如说一小个改动点需要上线,整个系统必须上线;
-
还有一个缺点就是单体架构需要技术栈统一,比如说所有功能模块都需要用Java语言来编写。
单体架构的缺点不在于不可拆分、难以扩展(这种想法不完全正确)。
- 从纵向拆分角度来看,现代的单体应用都是会拆分成controller,service和dao层的,不存在不能拆分的说法;
- 从横向拆分的角度,单体应用完全可以拆分成多个模块,每个模块负责不同的功能,但是最后还是打成一个包,运行在一个进程中;
- 从横向扩展的角度,可以通过负载均衡机制同时部署若干个相同的单体系统副本,以达到分摊流量压力的效果。
微服务取代单体系统成为潮流趋势的根本原因,笔者认为最重要的原因是:单体系统很难兼容“Phoenix”的特性。这种架构风格潜在的要求是希望系统的每一个部件、每一处代码都尽量可靠,尽量不出或少出缺陷。然而战术层面再优秀,也很难弥补战略层面的不足。单体系统靠高质量来保证高可靠性的思路,在小规模软件上还能运作良好,但当系统规模越来越大时,交付一个可靠的单体系统就变得越来越具有挑战性。如本书前言所说,正是随着软件架构演进,构建可靠系统的观念从“追求尽量不出错”到正视“出错是必然”的转变,才是微服务架构得以挑战并逐步取代单体架构的底气所在。
3. SOA架构时代
SOA架构,面向服务的架构。其包含的许多概念、思想都能在今天的微服务中找到对应的身影了,譬如服务之间的松散耦合、注册、发现、治理,隔离、编排等。
SOA不能简单视为一种架构风格,而是一套软件设计的基础平台。
- 它拥有领导制定技术标准的组织Open CSA;
- 有清晰的软件设计的指导原则,譬如服务的封装性、自治、松耦合、可重用、可组合、无状态,等等;
- 明确了采用SOAP作为远程调用协议,依靠SOAP协议族(WSDL、UDDI和WS-*协议)来完成服务的发布、发现和治理;
- 利用企业服务总线(Enterprise Service Bus,ESB)的消息管道来实现各个子系统之间的交互,令各服务在ESB的调度下无须相互依赖就能相互通信,实现了服务松耦合,也为以后进一步实施业务流程编排(Business Process Management,BPM)提供了基础
- 使用服务数据对象(Service Data Object,SDO)来访问和表示数据,使用服务组件架构(Service Component Architecture,SCA)来定义服务封装的形式和服务运行的容器
但是SOA技术最终还是偃旗息鼓了,最主要的原因还是SOA基于SOAP协议,SOAP协议过于严格的规范定义带来过度的复杂性,而构建在SOAP基础之上的ESB、BPM、SCA、SDO等诸多上层建筑,进一步加剧了这种复杂性。
SOA自诞生的那一天起,就已经注定只能是少数系统阳春白雪式的精致奢侈品,它可以实现多个异构大型系统之间的复杂集成交互,却很难作为一种具有广泛普适性的软件架构风格来推广。SOA最终没有获得成功的致命伤与当年的EJB如出一辙,尽管有Sun和IBM等一众巨头在背后力挺,EJB仍然败于以Spring、Hibernate为代表的“草根框架”,可见一旦脱离人民群众,终究会淹没在群众的海洋之中,连信息技术也不曾例外。
SAO的设计理念和简单透明相悖甚远。
4. 微服务架构时代
微服务架构是一种通过多个小型服务组合来构建单个应用的架构风格,这些服务围绕业务能力而非特定的技术标准来构建。各个服务可以采用不同的编程语言、不同的数据存储技术,运行在不同的进程之中。服务采取轻量级的通信机制和自动化的部署机制实现通信与运维。
微服务的九个核心的业务与技术特征:
- 围绕业务能力构建
- 强终端弱管道
微服务的一些优缺点:
- 每个项目复杂度降低;
- 团队的职责更加明确;
- 扩展更加灵活,只需扩容流量特别大项目;
- 部署更加灵活,不会因为一个小功能部署就部署所以系统,让整个团队留下来验证;
- 独立部署,错误隔离
缺点就是会引入分布式系统的复杂性。
微服务和SOA的区别
从以上微服务的定义和特征中,你应该可以明显地感觉到微服务追求的是更加自由的架构风格,摒弃了几乎所有SOA里可以抛弃的约束和规定,提倡以“实践标准”代替“规范标准”。
可是,如果没有了统一的规范和约束,以前SOA解决的那些分布式服务的问题,不也就一下子都重新出现了吗?的确如此,对于服务的注册发现、跟踪治理、负载均衡、故障隔离、认证授权、伸缩扩展、传输通信、事务处理等问题,微服务中将不再有统一的解决方案。
即使只讨论Java范围内会使用到的微服务,仅一个服务间远程调用问题,可以列入解决方案的候选清单的就有RMI(Sun/Oracle)、Thrift(Facebook)、Dubbo(阿里巴巴)、gRPC(Google)、Motan2(新浪)、Finagle(Twitter)、brpc(百度)、Arvo(Hadoop)、JSON-RPC、REST,等等;仅一个服务发现问题,可以选择的就有Eureka(Netflix)、Consul(HashiCorp)、Nacos(阿里巴巴)、ZooKeeper(Apache)、etcd(CoreOS)、CoreDNS(CNCF),等等。其他领域也与此类似。
微服务所带来的自由是一把双刃开锋的宝剑,当软件架构者拿起这把宝剑,一刃指向SOA定下的复杂技术标准,将选择的权力夺回的同一时刻,另外一刃也正朝着自己映出冷冷的寒光。
在微服务时代,软件研发本身的复杂度确实有所降低。一个简单服务,并不见得会同时面临分布式中的所有问题,也就没有必要背上SOA那百宝袋般沉重的技术包袱。需要解决什么问题,就引入什么工具;团队熟悉什么技术,就使用什么框架。此外,像Spring Cloud这样胶水式的全家桶工具集,通过一致的接口、声明和配置,进一步屏蔽了源自具体工具、框架的复杂性,降低了在不同工具、框架之间切换的成本,所以,作为一个普通的服务开发者,作为一个“螺丝钉”式的程序员,微服务架构是友善的。
可是,微服务对架构者却是满满的“恶意”,对架构能力的要求已提升到史无前例的程度。技术架构者的第一职责就是决策权衡,有利有弊才需要决策,有取有舍才需要权衡,如果架构者本身的知识面不足以覆盖所需要决策的内容,不清楚其中利弊,恐怕将无可避免地陷入选择困难症的境遇之中。微服务时代充满着自由的气息,微服务时代充斥着迷茫的选择。
后微服务时代(云原生时代)
容器技术给分布式架构提供了新思路。
当虚拟化的基础设施从单个服务的容器扩展至由多个容器构成的服务集群、通信网络和存储设施时,软件与硬件的界限便已模糊。一旦虚拟化的硬件能够跟上软件的灵活性,那些与业务无关的技术性问题便有可能从软件层面剥离,悄无声息地在硬件基础设施之内解决,让软件得以只专注业务,真正围绕业务能力构建团队与产品。
从软件层面独立应对分布式架构所带来的各种问题,发展到应用代码与基础设施软、硬一体,合力应对架构问题,这个新的时代现在常被媒体冠以“云原生”这个颇为抽象的名字加以宣传。云原生时代追求的目标与此前微服务时代追求的目标并没有本质改变,都是在服务架构演进的历史进程中,所以笔者更愿意称云原生时代为“后微服务时代”。
Kubernetes成为容器战争胜利者标志着后微服务时代的开启,但Kubernetes仍然没能完美解决全部的分布式问题。
微服务A调用了微服务B的两个服务,称为B1和B2,假设B1表现正常但B2出现了持续的500错,那在达到一定阈值之后就应该对B2进行熔断,以避免产生雪崩效应。如果仅在基础设施层面来处理,这会遇到一个两难问题,切断A到B的网络通路会影响B1的正常调用,不切断则会持续受B2的错误影响。
为了解决这一类问题,虚拟化的基础设施很快完成了第二次进化,引入了今天被称为“服务网格”(Service Mesh)的“边车代理模式”(Sidecar Proxy)。
在虚拟化场景中的边车指的是由系统自动在服务容器(通常是指Kubernetes的Pod)中注入一个通信代理服务器,相当于那个挎斗,以类似网络安全里中间人攻击的方式进行流量劫持,在应用毫无感知的情况下,悄然接管应用所有对外通信。这个代理除了实现正常的服务间通信外(称为数据平面通信),还接收来自控制器的指令(称为控制平面通信),根据控制平面中的配置,对数据平面通信的内容进行分析处理,以实现熔断、认证、度量、监控、负载均衡等各种附加功能。通过边车代理模式,便实现了既不需要在应用层面加入额外的处理代码,也提供了几乎不亚于程序代码的精细管理能力。
无服务架构时代
无服务现在还没有一个特别权威的“官方”定义,但它的概念并没有前面提到的各种架构那么复杂,本来无服务也是以“简单”为主要卖点的,它只涉及两块内容:后端设施(Backend)和函数(Function)。
-
后端设施是指数据库、消息队列、日志、存储等这类用于支撑业务逻辑运行,但本身无业务含义的技术组件,这些后端设施都运行在云中,在无服务中将它们称为“后端即服务”(Backend as a Service,BaaS)。
-
函数是指业务逻辑代码,这里函数的概念与粒度都已经很接近于程序编码角度的函数了,其区别是无服务中的函数运行在云端,不必考虑算力问题,也不必考虑容量规划(从技术角度可以不考虑,从计费的角度还是要掂量一下的),在无服务中将其称为“函数即服务”(Function as a Service,FaaS)。
。。。
分布式和集群的区别
前言:我们在做项目的时候经常会用到集群, 在面试的时候也经常会问到你们有没有用集群, 怎么部署的。 无论你是 web容器集群还是db集群,按照所要解决的问题可以分为如下几种:
高可用集群,提升可用性,(容灾、故障转移), 部署方式有以下三种
- 主从方式:主机工作,备机监控。此方式不能有效的利用服务器资源
- 互为主从:两服务器同时在线,一台服务器故障可切换到另一台上。此 方式有效的利用服务器资源,但当服务器故障时候,将导致一台服务器上运行多个业务。
- 多台服务器主从:大部分服务器在线使用,小部分监控;若有部分服务器故障,可切换到指定的小部分服务器上。此方式为前两种方式的综合。然后多台服务器群集,也增加了管理的复杂度。
高可用集群的另外一个特点是共享资源,多个节点服务器共享一个存储资源,该存储可在不同节点之间转移。相关知识: Raid与DAN、SAN、NAS基础
负载均衡集群,LoadBalance, 提升吞吐量
- 不同节点之间相互独立,不共享任何资源(硬件,网络, 但应用的会话保持需要一定的策略)。
- 通过一定算法将客户端的访问请求分配到群集的各个节点上,充分利用每个节点的资源。
- 负载均衡扩展了网络设备和服务器带宽,增加吞吐量,加强网络数据处理能。
- 每个节点的性能和配置可能不同,根据算法,可以分配不同的权重到不同节点上,以实现不同节点的资源利用。
并行计算群集,Performance, 减少应答时间
- 并行计算或称平行计算是相对于串行计算来说的。
- 并行计算的能力的目的是提高计算速度。
并行计算分为时间计算和空间计算:
- 时间计算既是流水线技术,一个处理器分为多个单元,每个单元负责不同任务,这些单元可并行计算。
- 空间计算利用多个处理器并发的执行计算。目前PC机的计算能力越来越强,将大量低廉的PC机互联起来,组成一个"大型计算机"以解决复杂的计算任务。Beowulf computers为最典型的空间并行计算。