第10周,主要介绍微服务、DDD、中台的内容

微服务

巨无霸应用的问题

  • 编译部署困难
  • 代码分支管理困难,团队协作开发成本高
  • 系统高可用差
  • 线上发布变慢
  • 数据库连接池耗尽
  • 开发新业务缓慢

服务化:通俗的理解,服务化就是把传统的单机应用中通过 JAR 包依赖产生的本地方法调用,改造成通过 RPC 接口产生的远程方法调用。

微服务:

  • 服务拆分粒度更细。微服务可以说是更细维度的服务化,小到一个子模块,只要该模块依赖的资源与其他模块都没有关系,那么就可以拆分为一个微服务。
  • 服务独立部署。每个微服务都严格遵循独立打包部署的准则,互不影响。比如一台物理机上可以部署多个 Docker 实例,每个 Docker 实例可以部署一个微服务的代码。
  • 服务独立维护。每个微服务都可以交由一个小团队甚至个人来开发、测试、发布和运维,并对整个生命周期负责。
  • 服务治理能力要求高。因为拆分为微服务之后,服务的数量变多,因此需要有统一的服务治理平台,来对各个服务进行管理。

微服务框架的需求:

  • 服务注册与发现
  • 服务调用
  • 失效转移,实现服务高可用
  • 负载均衡
  • 高效的远程通讯
  • 对应用最少侵入
  • 版本管理

微服务框架:

dubbo

/dev-guide/images/dubbo-framework.jpg
dubbo整体设计
/dev-guide/images/dubbo-relation.jpg
依赖关系
/dev-guide/images/dubbo-extension.jpg
调用链
/dev-guide/images/dubbo-export.jpg
暴露服务时序
/dev-guide/images/dubbo-refer.jpg
引用服务时序

spring cloud

全家桶的feature:

Spring Cloud focuses on providing good out of box experience for typical use cases and extensibility mechanism to cover others.

  • Distributed/versioned configuration
  • Service registration and discovery
  • Routing
  • Service-to-service calls
  • Load balancing
  • Circuit Breakers
  • Global locks
  • Leadership election and cluster state
  • Distributed messaging
spring核心特性(小马哥的spring课程)

spring cloud的内容非常丰富,资料自行学习

service mesh

Control Plane 的主要作用包括以下几个方面:

  • 服务发现。服务提供者会通过 SideCar 注册到 Control Plane 的注册中心,这样的话服务消费者把请求发送给 SideCar 后,SideCar 就会查询 Control Plane 的注册中心来获取服务提供者节点列表。
  • 负载均衡。SideCar 从 Control Plane 获取到服务提供者节点列表信息后,就需要按照一定的负载均衡算法从可用的节点列表中选取一个节点发起调用,可以通过 Control Plane 动态修改 SideCar 中的负载均衡配置。
  • 请求路由。SideCar 从 Control Plane 获取的服务提供者节点列表,也可以通过 Control Plane 来动态改变,比如需要进行 A/B 测试、灰度发布或者流量切换时,就可以动态地改变请求路由。
  • 故障处理。服务之间的调用如果出现故障,就需要加以控制,通常的手段有超时重试、熔断等,这些都可以在 SideCar 转发请求时,通过 Control Plane 动态配置。
  • 安全认证。可以通过 Control Plane 控制一个服务可以被谁访问,以及访问哪些信息。
  • 监控上报。所有 SideCar 转发的请求信息,都会发送到 Control Plane,再由 Control Plane 发送给监控系统,比如 Prometheus 等。
  • 日志记录。所有 SideCar 转发的日志信息,也会发送到 Control Plane,再由 Control Plane 发送给日志系统,比如 Stackdriver 等。
  • 配额控制。可以在 Control Plane 里给服务的每个调用方配置最大调用次数,在 SideCar 转发请求给某个服务时,会审计调用是否超出服务对应的次数限制。

微服务架构实践

  • 业务先行,先理顺业务边界和依赖,技术是手段而不是目的
  • 先有独立的模块,后有分布式的服务
  • 业务耦合严重,逻辑复杂多变的系统进行微服务重构的时候要谨慎
  • 要搞清楚微服务的目的是什么

CQRS

事件溯源

断路器

  • 闭合(Closed)状态:我们需要一个调用失败的计数器,如果调用失败,则使失败次数加 1。如果最近失败次数超过了在给定时间内允许失败的阈值,则切换到断开 (Open) 状态。此时开启了一个超时时钟,当该时钟超过了该时间,则切换到半断开(Half-Open)状态。该超时时间的设定是给了系统一次机会来修正导致调用失败的错误,以回到正常工作的状态。在 Closed 状态下,错误计数器是基于时间的。在特定的时间间隔内会自动重置。这能够防止由于某次的偶然错误导致熔断器进入断开状态。也可以基于连续失败的次数。
  • 断开 (Open) 状态:在该状态下,对应用程序的请求会立即返回错误响应,而不调用后端的服务。这样也许比较粗暴,有些时候,我们可以 cache 住上次成功请求,直接返回缓存(当然,这个缓存放在本地内存就好了),如果没有缓存再返回错误(缓存的机制最好用在全站一样的数据,而不是用在不同的用户间不同的数据,因为后者需要缓存的数据有可能会很多)。
  • 半开(Half-Open)状态:允许应用程序一定数量的请求去调用服务。如果这些请求对服务的调用成功,那么可以认为之前导致调用失败的错误已经修正,此时熔断器切换到闭合状态,同时将错误计数器重置。如果这一定数量的请求有调用失败的情况,则认为导致之前调用失败的问题仍然存在,熔断器切回到断开状态,然后重置计时器来给系统一定的时间来修正错误。半断开状态能够有效防止正在恢复中的服务被突然而来的大量请求再次拖垮。

服务重试及调用超时

dubbo心跳设计的文章,参考

https://www.cnkirito.moe/heartbeat-design/

微服务网关

网关的作用:

它提供客户端一个统一的接入地址,API 网关可以将用户的请求动态路由到不同的业务服务上,并且做一些必要的协议转换工作。在你的系统中,你部署的微服务对外暴露的协议可能不同:有些提供的是 HTTP 服务;有些已经完成 RPC 改造,对外暴露 RPC 服务;有些遗留系统可能还暴露的是 Web Service 服务。API 网关可以对客户端屏蔽这些服务的部署地址以及协议的细节,给客户端的调用带来很大的便捷。

另一方面,在 API 网关中,我们可以植入一些服务治理的策略,比如服务的熔断、降级、流量控制和分流等等。

再有,客户端的认证和授权的实现,也可以放在 API 网关中。你要知道,不同类型的客户端使用的认证方式是不同的。手机 APP 使用 Oauth 协议认证,HTML5 端和 Web 端使用 Cookie 认证,内部服务使用自研的 Token 认证方式。这些认证方式在 API 网关上可以得到统一处理,应用服务不需要了解认证的细节。另外,API 网关还可以做一些与黑白名单相关的事情,比如针对设备 ID、用户 IP、用户 ID 等维度的黑白名单。

最后,在 API 网关中也可以做一些日志记录的事情,比如记录 HTTP 请求的访问日志,分布式追踪系统时,提到的标记一次请求的 requestId 也可以在网关中来生成。

zuul的责任链模式

spring cloud gateway

参考文章和官网介绍

常用的一种网关部署方式

老师的flower已经star,回头好好研究一下

OAuth2.0

极客时间有专门的课,很详细

https://time.geekbang.org/column/article/267315

DDD

https://time.geekbang.org/column/intro/238

软件架构模式的演进

DDD 包括战略设计和战术设计两部分。

战略设计主要从业务视角出发,建立业务领域模型,划分领域边界,建立通用语言的限界上下文,限界上下文可以作为微服务设计的参考边界。

战术设计则从技术视角出发,侧重于领域模型的技术实现,完成软件开发和落地,包括:聚合根、实体、值对象、领域服务、应用服务和资源库等代码逻辑的设计和实现。

DDD 战略设计会建立领域模型,领域模型可以用于指导微服务的设计和拆分。事件风暴是建立领域模型的主要方法,它是一个从发散到收敛的过程。它通常采用用例分析、场景分析和用户旅程分析,尽可能全面不遗漏地分解业务领域,并梳理领域对象之间的关系,这是一个发散的过程。事件风暴过程会产生很多的实体、命令、事件等领域对象,我们将这些领域对象从不同的维度进行聚类,形成如聚合、限界上下文等边界,建立领域模型,这就是一个收敛的过程。

我们可以用三步来划定领域模型和微服务的边界。

第一步:在事件风暴中梳理业务过程中的用户操作、事件以及外部依赖关系等,根据这些要素梳理出领域实体等领域对象。

第二步:根据领域实体之间的业务关联性,将业务紧密相关的实体进行组合形成聚合,同时确定聚合中的聚合根、值对象和实体。在这个图里,聚合之间的边界是第一层边界,它们在同一个微服务实例中运行,这个边界是逻辑边界,所以用虚线表示。

第三步:根据业务及语义边界等因素,将一个或者多个聚合划定在一个限界上下文内,形成领域模型。在这个图里,限界上下文之间的边界是第二层边界,这一层边界可能就是未来微服务的边界,不同限界上下文内的领域逻辑被隔离在不同的微服务实例中运行,物理上相互隔离,所以是物理边界,边界之间用实线来表示。

有了这两层边界,微服务的设计就不是什么难事了。

在战略设计中我们建立了领域模型,划定了业务领域的边界,建立了通用语言和限界上下文,确定了领域模型中各个领域对象的关系。到这儿,业务端领域模型的设计工作基本就完成了,这个过程同时也基本确定了应用端的微服务边界。在从业务模型向微服务落地的过程中,也就是从战略设计向战术设计的实施过程中,我们会将领域模型中的领域对象与代码模型中的代码对象建立映射关系,将业务架构和系统架构进行绑定。当我们去响应业务变化调整业务架构和领域模型时,系统架构也会同时发生调整,并同步建立新的映射关系。

组件设计原则

  • 组件内聚原则
  • 复用发布等同原则
  • 共同封闭原则
  • 共同复用原则
  • 组件耦合原则
  • 无循环依赖原则
  • 稳定依赖原则
  • 稳定抽象原则

RPC原理

涉及rpc的方方面面

https://time.geekbang.org/column/intro/280