本部分节选自《 软件架构设计》
软件开发就是把一个复杂的问题分解为一系列简单的问题,再把一系列简单的解决方案组合成一个复杂的解决方案。而软件开发中最大的挑战,就是即可以快速高效地针对需求、环境的变化作出改变,也可以持续提供稳定、高可用的服务。而软件架构,就是软件系统的骨骼与框架。javascript
所谓架构,见仁见智,很难有一个明确或标准的定义;但架构并不是镜花水月或阳春白雪,有系统的地方就须要架构,大到航空飞机,小到一个电商系统里面的一个功能组件,都须要设计和架构。抽象而言,架构就是对系统中的实体以及实体之间的关系所进行的抽象描述,是对物/信息的功能与形式元素之间的对应状况所作的分配,是对元素之间的关系以及元素同周边环境之间的关系所作的定义。架构能将目标系统按某个原则进行切分,切分的原则,是要便于不一样的角色进行并行工做,结构良好的创造活动要优于毫无结构的创造活动。前端
软件架构的核心价值,便是控制系统的复杂性,将核心业务逻辑和技术细节的分离与解耦。软件架构是系统的草图,它描述的对象是直接构成系统的抽象组件;各个组件之间的链接则明确和相对细致地描述组件之间的通讯。在实现阶段,这些抽象组件被细化为实际的组件,好比具体某个类或者对象。在面向对象领域中,组件之间的链接一般用接口来实现。架构师的职责是努力训练本身的思惟,用它去理解复杂的系统,经过合理的分解和抽象,理解并解析需求,建立有用的模型,确认、细化并扩展模型,管理架构;可以进行系统分解造成总体架构,可以正确的技术选型,可以制定技术规格说明并有效推进实施落地。java
在笔者的知识体系中,实际上将架构分为业务架构、应用架构、云基础架构这几大类,业务架构主要着眼于控制业务的复杂性,基础架构着眼于解决分布式系统中存在的一系列问题。不管何种架构,都但愿能实现系统的可变的同时保障业务的高可用。另外一个层面,根据企业中职责的划分,咱们每每能够将软件架构,及关联的架构师划分为如下几类:python
软件架构设计的一个核心问题是可否使用重复的架构模式,即可否达到架构级的软件重用。也就是说,可否在不一样的软件系统中,使用同一架构。当咱们讨论软件架构时,经常会说起软件架构模式(Architectural Pattern)与软件架构风格(Architectural Style)。git
软件架构模式每每会用于具体地解决某个具体的重复的架构问题,而架构风格则是对于某个具体的架构设计方案的命名。软件架构风格是描述某一特定应用领域中系统组织方式的惯用模式;架构风格反映了领域中众多系统所共有的结构和语义特性,并指导如何将各个模块和子系统有效组织成一个完整的系统。程序员
在笔者的系列文章中,CRUD、分层架构、六边形架构、洋葱架构、REST 以及 DDD,都算是架构风格;而 CQRS、EDA、UDLA、微服务等则被划分到架构模式中。github
在软件开发中,程序员每每可以脱离现实规律的束缚,创造出天马行空的世界,其也是最具备创造力的活动之一。编程惟一须要的是创造力思惟和思惟组织能力,这意味着在软件开发过程当中最大限制是理解咱们正在建立的对象。随着软件的演进,加入更多的功能点,系统变得愈来愈复杂:各个模块(Module)间存在着各类微妙的依赖关系。系统的复杂性随着时间积累,对于程序员来讲,修改系统时考虑周全全部的的相关因素变得愈来愈困难。这就会使软件开放进度变缓慢,而且引入 Bug,而致使会进一步延缓开发进度,增长开发成本。在任何一个系统的生命周期中,复杂性不可避免会增长;系统越大,须要更多的人开发,管理系统复杂性的工做就越困难。web
Eric Evans 在 Domain‐Driven Design 一书中吐槽了所谓的意大利面式架构,即代码确实作了有用的事,但很难解释它是如何去执行的;他认为形成这种窘境的主要缘由是,将领域问题的复杂度与技术细节的复杂度混合在了一块儿,最终致使总体复杂度的指数级增加。面试
复杂性不是凭空而来,不少时候也不是刻意为之,这也就意味着复杂性的增长每每不会以咱们的主观意志为转移。就像房间里的大象,咱们没法逃避,也不能视而不见。复杂性的来源多是:算法
复杂性的应对永远不会是一劳永逸,咱们须要不断地推陈出新,是动态、渐进的重塑本身对软件系统的认识,不断认识问题和寻找更优解的持续迭代。第一个控制复杂性的途径是代码简单,意图清晰(Obvious)。例如: 减小特殊场景的处理,或变量命名一致性都能下降系统复杂性。另外一种方式就是对复杂问题的抽象而后分而治之。
本部分节选自《 领域驱动设计》
DDD 领域驱动设计,起源于 2004 年著名建模专家 Eric Evans 发表的他最具影响力的著名书籍:《Domain-Driven Design – Tackling Complexity in the Heart of Software》,Eric Evans 在该书中只是提供了一套原始理论,并无提供一套方法论,所以多年来对于 DDD 也是见仁见智。更早些时候 MartinFowler 曾经提出贫血模型与充血模型的概念,他认为咱们大多数系统以 POJO 做为模型,只有普通的 getter、setter 方法,没有真正的行为,好像缺乏血液的人,在 Evans 看来,DDD 中模型都是以充血形式存在,也就是说在 DDD 中,咱们设计的模型不只包含描述业务属性,还要包含可以描述动做的方法,不一样的是,领域中一些概念不能用在模型对象,如仓储、工厂、服务等,如强加于模型中,将破坏模型的定义。
领域驱动设计的战略核心便是将问题域与应用架构相剥离,将业务语义显现化,把原先晦涩难懂的业务算法逻辑,经过领域对象(Domain Object),统一语言(Ubiquitous Language)转化为领域概念清晰的显性化表达出来。
本部分节选自《 微服务与云原生》
在 Web 应用程序发展的早期,大部分工程是将全部的服务端功能模块打包到单个巨石型(Monolith)应用中,譬如不少企业的 Java 应用程序打包为 war 包,最终会造成以下的架构:
巨石型应用易于搭建开发环境、易于测试、易于部署;其缺陷也很是明显,没法进行局部改动与部署,编译时间过长,回归测试周期过长,开发效率下降等。集中式架构分为标准的三层:数据访问层、服务层和 Web 层。
在 Web2.0 时代刚刚流行的时候,互联网应用与企业级应用并无本质的区别,集中式架构分为标准的三层:数据访问层、服务层和 Web 层。
SOA(Service-Oriented Architecture) 面向服务架构,是在互联网应用规模迅速增加,集中式架构已没法作到无限制地提高系统的吞吐量的背景下,产生的涉及模块化开发、分布式扩展部署等相对宽泛的概念。
SOA 是一个组件模型,它将应用程序的不一样功能单元(称为服务)经过这些服务之间定义良好的接口和契约联系起来。SOA 中的接口独立于实现服务的硬件平台、操做系统和编程语言,采用中立的方式进行定义。这使得构建在各类各样的系统中的服务能够以一种统一和通用的方式进行交互。面向服务架构,它能够根据需求经过网络对松散耦合的粗粒度应用组件进行分布式部署、组合和使用。服务层是 SOA 的基础,能够直接被应用调用,从而有效控制系统中与软件代理交互的人为依赖性。
实施 SOA 的关键目标是实现企业 IT 资产的最大化做用。要实现这一目标,就要在实施 SOA 的过程当中牢记如下特征:可从企业外部访问、随时可用、粗粒度的服务接口分级、松散耦合、可重用的服务、服务接口设计管理、标准化的服务接口、支持各类消息模式、精肯定义的服务契约。
服务消费者(Service Consumer)能够经过发送消息来调用服务,这些消息由一个服务总线(Service Bus)转换后发送给适当的服务实现。这种服务架构能够提供一个业务规则引(Business Rules Engine),该引擎允许业务规则被合并在一个服务里或多个服务里。这种架构也提供了一个服务管理基础(Service Management Infrastructure),用来管理服务,相似审核,列表(billing),日志等功能。此外,该架构给企业提供了灵活的业务流程,更好地处理控制请求(Regulatory Requirement),例如 Sarbanes Oxley(SOX),而且能够在不影响其余服务的状况下更改某项服务。
因为分布式系统十分复杂,所以产生了大量的用于简化分布式系统开发的分布式中间件和分布式数据库,服务化的架构设计理念也被愈来愈多的公司所认同。以下是 Dubbo 官方文档公布了一张有关 SOA 系统演化过程的图片:
微服务(Microservices Architecture Pattern)由 Martin Fowler 在 2014 年提出的,是但愿将某个单一的单体应用,转化为多个能够独立运行、独立开发、独立部署、独立维护的服务或者应用的聚合,从而知足业务快速变化及分布式多团队并行开发的需求。如康威定律(Conway’s Law)所言,任何组织在设计一套系统(广义概念)时,所交付的设计方案在结构上都与该组织的通讯结构保持一致,微服务与微前端不只仅是技术架构的变化,还包含了组织方式、沟通方式的变化。
对于微服务,不一样背景的人也有不一样的看法,对于熟悉 SOA 的开发者,微服务也能够认为是去除了 ESB 的 SOA 的一种实现方案;ESB 是 SOA 架构中的中心总线,设计图形应该是星形的,而微服务是去中心化的分布式软件架构。SOA 更多强调重用,而微服务偏向于重写。SOA 偏向水平服务,微服务偏向垂直服务;SOA 偏向自上而下的设计,微服务偏向自下而上的设计。
微服务与微前端原理和软件工程,面向对象设计中的原理一样相通,都是遵循单一职责(Single Responsibility)、关注分离(Separation of Concerns)、模块化(Modularity)与分而治之(Divide & Conquer)等基本的原则。从巨石型应用到微服务的衍化也并不是一蹴而就,以下图也演示了简单的渐进式替代过程:
云原生是经过构建团队、文化和技术,利用自动化和架构来管理系统的复杂性和解放生产力。
— Joe Beda,Heotio CTO,联合创始人
Pivotal 是云原生应用的提出者,并推出了 Pivotal Cloud Foundry 云原生应用平台和 Spring 开源 Java 开发框架,成为云原生应用架构中先驱者和探路者。早在 2015 年 Pivotal 公司的 Matt Stine 写了一本叫作迁移到云原生应用架构的小册子,其中探讨了云原生应用架构的几个主要特征:符合 12 Factors 应用、面向微服务架构、自服务敏捷架构、基于 API 的协做以及抗脆弱性。2015 年 Google 主导成立了云原生计算基金会(CNCF),起初 CNCF 对云原生(Cloud Native)的定义包含如下三个方面:应用容器化、面向微服务架构、应用支持容器的编排调度。
云原生应用程序简单地定义为从头开始为云计算架构而构建应用程序;这意味着,若是咱们将应用程序设计为预期将部署在分布式、可扩展的基础架构上,咱们的应用程序就是云原生的。随着公共云将承载愈来愈多的算力,将来云计算将是主流的 IT 能力交付方式,CNCF 也对云原生进行了从新定义:云原生技术有利于各组织在公有云、私有云和混合云等新型动态环境中,构建和运行可弹性扩展的应用;云原生的表明技术包括容器、服务网格、微服务、不可变基础设施和声明式 API。
这些技术组合搭配,可以构建容错性好、易于管理和便于观察的松耦合系统;再结合可靠的自动化手段,云原生技术可以使工程师轻松地对系统做出频繁和可预测的重大变动。因而可知,云原生是保障系统能力灵动性地有效抓手;云原生技术有利于各组织在公有云、私有云和混合云等新型动态环境中,构建和运行可弹性扩展的应用。微服务架构很是适合云原生应用程序;可是,云原生一样存在着必定的限制,若是你的云原生应用程序部署在 AWS 等公有云上,则云原生 API 不是跨云平台的。
云原生应用的关键属性包括了:使用轻量级的容器打包、使用最合适的语言和框架开发、以松耦合的微服务方式设计、以 API 为中心的交互和协做、无状态和有状态服务在架构上界限清晰、不依赖于底层操做系统和服务器、部署在自服务、弹性的云基础设施上、经过敏捷的 DevOps 流程管理、自动化能力、经过定义和策略驱动的资源分配。云原生是分布式应用当下重要的发展路径,其终态应当是 Distributionless,全部与分布式相关的问题由云平台解,分布式应用的开发会跟传统应用的开发同样方便,甚至更加便捷。
本部分节选自《 分布式基础架构之虚拟化与编排》
虚拟机由某些特定的硬件和内核虚拟化组成,运行客户操做系统。称为管理程序的软件建立虚拟化硬件,其能够包括虚拟磁盘,虚拟网络接口,虚拟 CPU 等。虚拟机还包括能够与此虚拟硬件通讯的宾客内核。管理程序能够托管,这意味着它是一些在主机操做系统(MacOS)上运行的软件,如示例中所示。它也能够是裸机,直接在机器硬件上运行(替换你的操做系统)。不管哪一种方式,管理程序方法都被认为是重量级的,由于它须要虚拟化多个部分(若是不是所有硬件和内核)。
VM 须要硬件虚拟化才能实现机器级隔离,而容器则只须要在同一操做系统内进行隔离操做。 随着隔离空间数量的增长,开销差别变得很是明显。
在过去几年里,云平台发展迅速,但其中困扰运维工程师最多的,是须要为各类迥异的开发语言安装相应的运行时环境。虽然自动化运维工具能够下降环境搭建的复杂度,但仍然不能从根本上解决环境的问题。
Docker 的出现成为了软件开发行业新的分水岭,容器技术的成熟也标志着技术新纪元的开启。Docker 提供了让开发工程师能够将应用和依赖封装到一个可移植的容器中的能力,这项举措使得 Docker 大有席卷整个软件行业而且进而改变行业游戏规则的趋势,这像极了当年智能手机刚出现时的场景——改变了整个手机行业的游戏规则。Docker 经过集装箱式的封装方式,让开发工程师和运维工程师都可以以 Docker 所提供的镜像分发的标准化方式发布应用,使得异构语言再也不是捆绑团队的枷锁。
容器是包含应用程序代码,配置和依赖关系的软件包,可提供运营效率和生产力。容器为咱们提供了可预测的,可重复的和不可变的运行预期,容器的兴起是 DevOps 即服务的一个巨大推进因素,能够克服当今面临的最大安全障碍。容器化经过在操做系统级别进行虚拟化来使应用程序可移植,从而建立基于内核的隔离的封装系统。容器化的应用程序能够放在任何地方,无需依赖项运行或须要整个 VM,从而消除了依赖关系。
做为独立的单元,容器可以在任何主机操做系统,CentOS,Ubuntu,MacOS,甚至是像 Windows 这样的非 UNIX 系统中运行。容器还充当标准化的工做或计算单元。一个常见的范例是每一个容器运行单个 Web 服务器,数据库的单个分片或单个 Spark 工做程序等,只须要扩展容器的数量就可以便捷地扩展应用。每一个容器都有一个固定的资源配置(CPU,RAM,线程数等),而且扩展应用程序须要只扩展容器的数量而不是单个资源原语。当应用程序须要按比例放大或缩小时,这为工程师提供了更容易的抽象。容器也是实现微服务架构的一个很好的工具,每一个微服务只是一组协做容器。例如,可使用单个主容器和多个从容器来实现 Redis 微服务。
随着虚拟化技术的成熟和分布式架构的普及,用来部署、管理和运行应用的云平台被愈来愈多地说起。IaaS、PaaS 和 SaaS 是云计算的三种基本服务类型,分别表示关注硬件基础设施的基础设施即服务、关注软件和中间件平台的平台即服务,以及关注业务应用的软件即服务。容器的出现,使原有的基于虚拟机的云主机应用,完全转变为更加灵活和轻量的容器与编排调度的云平台应用。
然而容器单元愈来愈散落使得管理成本逐渐上升,你们对容器编排工具的需求史无前例的强烈,Kubernetes、Mesos、Swarm 等为云原生应用提供了强有力的编排和调度能力,它们是云平台上的分布式操做系统。容器编排是一般能够部署多个容器以经过自动化实现应用程序的过程。像 Kubernetes 和 Docker Swarm 这样的容器管理和容器编排引擎,使用户可以指导容器部署并自动执行更新,运行情况监视和故障转移过程。
Kubernetes 是目前世界范围内关注度最高的开源项目,它是一个出色的容器编排系统,用于提供一站式服务。Kubernetes 出身于互联网行业巨头 Google,它借鉴了由上百位工程师花费十多年时间打造的 Borg 系统的理念,安装极其简易,网络层对接方式十分灵活。Kubernetes 和 Mesos 的出色表现给行业中各种工程师的工做模式带来了颠覆性的改变。他们不再用关注每一台服务器,当服务器出现问题时,只要将其换掉便可。业务开发工程师没必要再过度关注非功能需求,只需专一本身的业务领域便可。而中间件开发工程师则须要开发出健壮的云原生中间件,用来链接业务应用与云平台。
Kubernetes、Service Mesh 和 Serverless 三者共同演绎不一样层次的封装和向上屏蔽下面的细节。Kubernetes 引入了不一样的设计模式,实现对各类云资源全新、有效和优雅的抽象和管理模式,让集群的管理和应用发布变成了件至关轻松且不易出错的事。被普遍采用的微服务软件架构将分布式应用的各类复杂度迁移到了服务之间,如何经过全局一致、体系化、规范化和无侵入的手段进行治理就变成了微服务软件架构下相当重要的内容。Kubernetes 细化的应用程序的分解粒度,同时将服务发现、配置管理、负载均衡和健康检查等做为基础设施的功能,简化了应用程序的开发。而 Kubernetes 这种声明式配置尤为适合 CI/CD 流程,何况如今还有如 Helm、Draft、Spinnaker、Skaffold 等开源工具能够帮助咱们发布 Kuberentes 应用。
Service Mesh 经过将各服务所共用和与环境相关的内容剥离到部署于每一个服务边上的 Sidecar 进程而轻松地作到了。这一剥离动做使得服务与平台能充分解耦而方便各自演进与发展,也使得服务变轻而有助于改善服务启停的及时性。Service Mesh 由于将那些服务治理相关的逻辑剥离到了 Sidecar 中且做为独立进程,因此 Sidecar 所实现的功能自然地支持多语言,为上面的服务采用多语言开发创造了更为有利的条件。经过 Service Mesh 对整个网络的服务流量进行技术收口,让异地多活这样涉及流量调度的系统工程实现起来更加优雅、简洁与有效,也能更加方便地实现服务版本升级时的灰度、回滚而改善安全生产质量。因为技术收口,给服务流量的治理和演进、排错、日志采集的经济性等疑难问题创造了新的发展空间。
您能够经过如下导航来在 Gitbook 中阅读笔者的系列文章,涵盖了技术资料概括、编程语言与理论、Web 与大前端、服务端开发与基础架构、云计算与大数据、数据科学与人工智能、产品设计等多个领域:
此外,你还可前往 xCompass 交互式地检索、查找须要的文章/连接/书籍/课程;或者在 MATRIX 文章与代码索引矩阵中查看文章与项目源代码等更详细的目录导航信息。最后,你也能够关注微信公众号:『某熊的技术之路』以获取最新资讯。