Dawn's Blogs

分享技术 记录成长

0%

凤凰架构笔记 (1) 架构的演进

单体系统

需要摆正这样一个观念,单体系统并不是反派角色

单体系统适用于小型系统,有自己的优缺点,并不是一无是处。

优点:

  • 小型系统而言,单体系统不仅易于开发、易于测试、易于部署,且由于系统中各个功能、模块、方法的调用过程都是进程内调用,不会发生进程间通信。

缺点:主要是缺乏隔离性,全部的代码全部在一个进程内运行,这样带来的坏处有两个。

  • 无法隔离错误,如果某个模块出现了错误,遇到了如内存泄漏等 Bug,那么整个程序都会受到影响。
  • 无法做到模块级别的单独停止、升级,因为不可能停止一部分的进程、重启一部分的经常。

单体系统架构潜在的要求整个系统都是可靠的,但是我们在软件架构的演进中应该有这样的观念:从尽量追求不出错,到正视出错是必然

架构如凤凰一样不死,反复涅槃重生,这就是软件架构所追求的目标。

SOA 时代

SOA(Service Oriented Architecture)面向服务的架构,就是将一个大型的单机系统进行拆分,拆分成独立的子系统。看起来 SOA 与微服务的概念差不多,实际上有很大的差异。

微服务架构 vs SOA

SOA(Service Oriented Architecture)指的是面向服务的架构,SOA 也是进行了服务划分,它与微服务架构看似相同,但是深入研究就会发现二者的巨大差异。

  • 服务间的通信:SOA 常吃采用重量级的技术,如 ESB(Enterprise Service Bus)、SOAP 和 WebService。而微服务架构倾向于使用轻量级的技术,如 REST 或者 gRPC 这类轻量级的协议。
  • 数据管理:SOA 一般有一个全局的数据库。而微服务与之相反,每一个服务都有一个自己的私有数据模型。
  • 服务规模:SOA 应用通常包含若干个大型的服务。而微服务架构则常常由属实个甚至上百个更小的服务组成。

微服务时代

微服务是一种通过多个小型服务组合来构建单个应用的架构风格,这些服务围绕业务能力而非特定的技术标准来构建。各个服务可以采用不同的编程语言不同的数据存储技术,运行在不同的进程之中。服务采取轻量级的通信机制自动化的部署机制实现通信与运维。

微服务的九个核心特征如下:

  • 围绕业务能力构建。因为团队之间的沟通成本是巨大的,一个微服务应该是一个可以自治的单体,所以一种业务就应该被限定在一种服务内部。这就是为什么微服务中的服务划分非常重要,而微服务的划分通常与 DDD 一致。即使刚开始的架构并不是按照业务能力划分的,随着时间的发展,最终的架构也会向着这种形式演化。
  • 分散治理。一个微服务应该是一个可以自治的单体,而不会依赖于其他服务。也就是说,服务之间可以是异构的、可以是跨语言的
  • 通过服务来实现独立自治的组件。通过服务,而不是通过类库(Library)来构建组件。因为服务是进程外组件,通过远程调用来提供功能,尽管进程外调用比进程内调用复杂且效率低,但是这是微服务的必然代价。
  • 产品化思维。服务看作是一种产品,开发人员负责整个生命周期(开发、测试、运维、部署等等)。
  • 数据去中心化。每一种服务独立的维护自己的数据库,而不是一个中心化的数据库。中心化的数据库的好处就是数据的一致性可以保证,缺点则是可能会让多个服务使用同一个数据表(服务无法独立的修改数据表 schema),使得服务之间丧失独立性。微服务去中心化的存储选择了维护独立性,而数据之间的一致性可以通过分布式事务保证。
  • 强终端弱管道。管道指进程间通信机制,通信机制采用最基本的即可,特殊的能力需求由服务(终端)完成。
  • 容错性设计。微服务设计中,必须有容错性设计,在必要的时候进行隔离。所以熔断器在实际生产环境中是必不可少的组件,如果没有这种容错性设计,则系统很容易就因为一两个服务的崩溃所带来的雪崩效应淹没。
  • 演进式设计。演进式设计允许服务被升级、淘汰。如果系统中出现了无法升级、淘汰的服务,这是一种设计上的脆弱表现。
  • 基础设施自动化。微服务下运维的对象比起单体架构要有数量级的增长,基础设施自动化减少了构建、发布、运维工作的复杂性。

与 SOA 这种强约束和规定的架构风格不同,微服务是一种自由的风格。

微服务中存在服务发现、进程间调用、负载均衡、事务处理等等问题,但是不会约束具体用什么方式去实现,微服务倡导以实践标准代替规范标准。

后微服务时代(云原生)

将服务发现、负载均衡等这类与业务无关的通用技术问题,下放到基础设施中去解决,就是后微服务时代(云原生)的主要思想。随着 Kubernetes 的兴起,这些问题都可以都可以由基础设施(Kubernetes)去解决,与业务无关的技术可以被剥离出来。

Kubernetes
服务发现 KubeDNS
配置中心 ConfigMap / Secret
服务网关 Ingress
负载均衡 Load Balancer
服务安全 RBAC API
跟踪监控 Metrics API / Dashboard
熔断机制 N/A

但是,Kubernetes 并没有解决全部的问题,这是一种粗粒度的解决方案,只能到容器(Pod)级别。比如一个容器中的某一个服务发生了错误,那么 Kubernetes 只能做的就是熔断对这个容器的访问,而这个容器上的其他可用服务也会变得不可用了。

为了解决这个问题,引入了服务网格(Service Mesh),具体的方法就是 Pod 中不仅仅有服务容器,还会注入一个通信代理服务器。在应用毫无感知的情况下,悄然接管应用所有对外通信。这个代理除了实现正常的服务间通信外(称为数据平面通信),还接收来自控制器的指令(称为控制平面通信)。根据控制平面中的配置,对数据平面通信的内容进行分析处理,以实现熔断、认证、度量、监控、负载均衡等各种附加功能。这样便实现了既不需要在应用层面加入额外的处理代码,也提供了几乎不亚于程序代码的精细管理能力。

无服务时代

无服务(Serverless)= BaaS + FaaS

  • BaaS:后端即服务,指 DB、MQ、网关、日志等用于支撑业务逻辑运行,但本身无业务含义的技术组件。
  • FaaS:函数即服务,指业务逻辑代码。无服务中的函数运行在云端,不必考虑算力问题,不必考虑容量规划。

无服务架构让开发者更加专注于业务,不需要考虑技术组件,也不需要考虑算力问题、部署问题。

对于实际的业务,采用函数的方式运行,开发人员只需要编写业务函数,而不用关心这个函数放在哪里运行,有种即插即用的感觉。

无服务并不是一种比微服务更加先进的架构模式,因为无服务架构是无状态的,只适用于简单的业务,对于直播、游戏服务器等复杂的业务上应用无服务架构可能会有点无从下手,并且无服务架构中的函数存在冷启动时间。