前页
随着 DevOps 和以 Docker 为主的容器技术的发展,云原生应用架构和微服 务变得流行起来。 云原生包含的内容很多,如 DevOps、持续交付、微服务、敏捷等
第一章,微服务架构介绍
架构的演进从单体到 SOA,再到微服务架构。 微服务架构是 SOA 思想的一种具体实践。
微服务架构将早期的单体应用从数据存储开始垂直拆分成多个不同的服务,每个服务都能独立部署,独立维护,独立扩展.
服务与服务间通过诸如 RESTful API的方式互相调用。只有业务复杂到一定程度的时候才适合采用微服务架构。
1、微服务架构的出现
单体应用架构
单体应用架构,即传统的Web应用程序中分层架构,按照调用顺序,从上到下为表示层、业务层、数据 访问( DAO)层、 DB 层。
表示层负责用户体验;业务层负责业务逻辑;数据访问层负责 DB 层的数据存取, 实现增删改查的功能。 业务层定义了应用的业务逻辑,是整个应用的核心。
在单体应用中,所有这些模块都集成在一起,或称为巨石型应用架构。
单体应用的缺点:
- 可靠性,所有模块在同一个进程中,任何一个模块中的bug,都会影响进程
- 复杂性高,代码模块化不清晰,复杂
- 持续部署困难,更新组件需要整体部署。。 这会中断那些可能与更改无关的后台任务(例如 Java 应用 中的 Quartz 任务),同时可能引发其他问题。
- 扩展能力受限:单体架构只能进行一维扩展。 这个不懂??
- 阻碍技术创新: 单体应用往往使用统一的技术平台或方案解决所有问题,,团队的每 个成员都必须使用相同的开发语言和架构,想要引人新的框架或技术平台非常困难。
SOA架构
面向服务的架构(SOA)是 Gartner 于 20 世纪 90 年代中期提出的。
SOA 的核心主体是服务,其目标是通过服务的流程化来实现业务的灵活性。 服务就像 一堆“元器件”,这些元器件通过封装形成标准服务,它们有相同的接口和语义表达规则。
SOA 治理是将 SOA 的一堆元 器件进行有效组装
完整的 SOA 架构由五大部分组成:
- 基础设施服务、 为整个 SOA 组件和框架提供一个可靠的运行环境,以及服务组件容器, 它的核心组件是应用服务器等基础软件支撑设施
- 企业服务总线 、 提供可靠消息传输、服务接入、协议转换、数据格式转换、基于内 容的路由等功能,屏蔽了服务的物理位置、协议和数据格式。
- 关键服务组件、SOA 在各种业务服务组件的分类。
- 开发工具、管理工具等提供完善的、可视化的服务开发和流程编排工具,包括服务 的设计、开发、 配置、部署、监控、重构等完整的 SOA 项目开发生命周期。
微服务架构
微服务的定义可以概括如下:
- 微服务架构是一种使用 一系列粒度较小的服务来开发单个应用的方式;每个服务运行在自己的进程中;
- 服务间采用轻量级的方式进行通信(通常是 HTTPAPI);这些服务是基于业务逻辑和范围,通过自动化部署的机制来独立部署的
- 并且服务的集中管理应该是最低限度的,即每个服务可以采用不同的编程语言编写,使用不同的数据存储技术。
组成
- 服务注册与发现: 服务提供方将己方调用地址注册到服务注册中心,让服务调用方能够方便地找到自己;服务调用方从服务注册中心找到自己需要调用的服务的地址。
- 负载均衡:服务提供方一般以多实例的形式提供服务,负载均衡功能能够让服务调用方连接到合适的服务节点。 并且,服务节点选择的过程对服务调用方来说是透明的。
- 服务网关:服务网关是服务调用的唯一入口,可以在这个组件中实现用户鉴权、动态路由、灰度发布、 A/B 测试、负载限流等功能。
- 配置中心:将本地化的配置信息( Properties、 XML、 YAML 等形式)注册到配置中心,实现程序包在开发、测试、生产环境中的无差别性,方便程序包的迁移。
- 集成框架:微服务组件都以职责单一的程序包对外提供服务,集成框架以配置的形式将所有微服务组件(特别是管理端组件)集成到统一的界面框架下,让用户能够在统一的界面中使用系统。
- 调用链监控:记录完成一次请求的先后衔接和调用关系,并将这种串行或并行的调 用关系展示出来。 在系统出错时,可以方便地找到出错点。
- 支撑平台:系统微服务化后,各个业务模块经过拆分变得更加细化,系统的部署、 运维、监控等都比单体应用架构更加复杂,这就需要将大部分的工作自动化。 现 在, Docker 等工具可以给微服务架构的部署带来较多的便利,例如持续集成、蓝绿 发布、健康检查、性能健康等等。 如果没有合适的支撑平台或工具,微服务架构就 无法发挥它最大的功效。
优点
- 解决了复杂性问题,单个服务变得很容易开发、理解和维护。
- 微服务架构模式使得团队并行开发得以推进,可以随便选择语言
- 微服务架构模式中每个微服务独立都是部署的。 理想情况下,开发者不需要协 调其他服务部署对本服务的影响。 这种改变可以加快部署速度
挑战:
- 运维要求较高。
- 分布式固有的复杂性。
- 接口调整成本高。
- 重复劳动。
- 可测试性的挑战
2、微服务架构的流派
常见的微服务架构方案有四种,分别是 ZeroC IceGrid、 基于消息队列 、 Docker Swarm 和 Spring Cloud。 下面分别介绍这四种方案。
ZeroC IceGrid
ZeroC IceGrid 是基于 RPC 框架 Ice 发展而来的一种微服务架构, Ice 不仅仅是一个 RPC 框架,它还为网络应用程序提供了一些补充服务。 Ice 是一个全面的 RPC 框架, 支持 C++、 C#、 Java、 JavaScript、 Python 等语言。 IceGrid 具有定位、部署和管理 Ice 服务器的功能, 具有良好的性能与分布式能力。
Ice 的 DNS。 DNS 用于将域名信息映射到具体的 IP 地址 ,通过域名得到该域名对应的 IP 地址的过程叫做域名解析。
基于消息队列
在微服务架构的定义中讲到,各个微服务之间使用“轻量级”的通信机制。 所谓轻量级,是指通信协议与语言无关、 与平台无关。 微服务之间的通信方式有两种:同步和异步。同步方式有 RPC , REST 等;除了标准的基于同步通信方式的微服务架构外,
还有基于消息 队列异步方式通信的微服务架构。
在基于消息队列的微服务架构方式中,微服务之间采用发布消息与监听消息的方式来实现服务之间的交互
Docker Swarm
Swarm 项目是 Docker 公司发布的三剑客中的一员,用来提供容器集群服务 ,目的是更好地帮助用户管理多个 Docker Engine,方便用户使用。 通过把多个 Docker Engine 聚集 在一起,形成一个大的 Docker Engine,对外提供容器的集群服务。 同时这个集群对外提供 Swarm API,用户可以像使用 Docker Engine 一样使用 Docker 集群。
Swarm 集群中有两种角色的节点:
Manager: 负责集群的管理、集群状态的维持及将任务(Task)调度到工作节点上等。
Worker : 承载运行在 Swarm 集群中的容器实例,每个节点主动汇报其上运行的任 务并维持同步状态。
Spring Cloud
Spring Cloud 是一个基于 Spring Boot 实现的云应用开发工具,是一系列框架的集合,当添加这些工具库到应用后会增强应用的行为。 Spring Boot 秉持约定优于配置的思想,因此可以利用这些组件基本的默认行为来快速入门 ,并在需要的时候可以配置或扩展,以创建自定义解决方案。
Spring Cloud 利用 Spring Boot 的开发便利性,巧妙地简化了分布式系统基础设施的开发,如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等,都可以基 于 Spring Boot 组件进行开发,做到一键启动和部署。
以下为 Spring Cloud 的核心功能 :
分布式/版本化配置
服务注册和发现
服务路由
服务和服务之间的调用
负载均衡
断路器
分布式消息传递
3、云原生于微服务
CNCF(云原生计算基金会)
云原生 :
CNCF 宪章中给出了云原生应用的三大特征,概括如下:
- 容器化封装:以容器为基础,提高整体开发水平,形成代码和组件重用,简化云原生应用程序的维护。 在容器中运行应用程序和进程,并作为应用程序部署的独立单 元,实现高水平资源隔离。
- 动态管理:通过集中式的编排调度系统来动态管理和调度。
- 面向微服务:明确服务间的依赖,互相解藕。
可以理解为云原生应用即面向云环境的软件架构,
12原则 :
基准代码。显式声明依赖关系。在环境中存储配置。把后端服务当作附加资源。 严格分离构建、发布和运行。无状态进程。 通过端口绑定提供服务。 通过进程模型进行扩展。快速启动和优雅终止。开发环境与线上环境等价。 日志作为事件流。管理进程。&&&& API 声明管理、认证和授权、 监控与告警。
容器化:
Docker 是一个开源引擎,可以轻松地为任何应用创建一个轻量级的、 可移植的、自给自足的容器。Docker 让开发工程师可以将他们的应用和依赖封装到一个可移植的容器中。 Docker 根本的想法是创建软件程序可移植的轻量容器,让其可以在任何安装了 Docker 的机器上运 行, 而不用关心底层操作系统。
优势:
- 隔离应用依赖。
- 创建应用镜像并进行复制。
- 创建容易分发的、即启即用的应用。
- 允许实例简单、快速地扩展。
- 测试应用并随后销毁它们。
DevOps
DevOps 是软件开发人员( Dev)和 IT 运维技术人员( Ops)之间的合作,目标是自动执行软件交付和基础架构更改流程,使得构建 、测试、发布软件能够更加地快捷和可靠。 它创造了一种文化和环境,可在其中快速、频繁且更可靠地构建、 测试和发布软件。
微服务
微服务将单体业务系统分解为多个可独立部署的服务。 这个服务通常只关注某项业务, 或者最小可提供业务价值的“原子”服务单元。
优势:
- 能够将相关的变更周期解藕
- 扩展更多的部署组件本身可以加快部署。
- 可以加快采用新技术的步伐。
- 微服务提供独立、高效的服务扩展
第二章、Spring Cloud 总览
Spring Cloud 是一系列框架的有机集合,基于 Spring Boot 实现的云应用开发工具,为云原生应用 开发中的服务发现与注册、熔断机制 、 服务路由 、分布式配置中心 、消息总线、负载均衡 和链路监控等功能的实现提供了一种简单的开发方式。
Spring Cloud 架构
版本说明
Springboot Cloud特点:
- 约定优于配置
- 适用于各种环境,部署在PC Server或各种云环境。均可
- 隐藏了组件的复杂性,并提供声明式,无xml配置方式。
- 开箱即用,快速启动。
- 轻量级的组件,Spring Cloud 整合的组件大都轻量
- 组件丰富,功能齐全。
- 选型中立
- 灵活,组成部分解耦。
Spring Cloud 组成
- 服务注册与发现组件: Eureka、 Zookeeper 和 Consul 等。 本书将会重点讲解 Eureka, Eureka 是一个 REST 风格的服务注册与发现的基础服务组件。
- 服务调用组件: Hystrix、 Ribbon 和 OpenFeign ;
- 其中 Hystrix 能够使系统在出现依 赖服务失效的情况下,通过隔离系统依赖服务的方式,防止服务级联失败, 同时提供失败回滚机制,使系统能够更快地从异常中恢复;
- Ribbon 用于提供客户端的软件 负载均衡算法,还提供了一系列完善的配置项如连接超时、 重试等;
- OpenFeign 是 一个声明式 RESTful 网络请求客户端,它使编写 Web 服务客户端变得更加方便和 快捷。
- 路由和过滤组件:包括 Zuul 和 Spring Cloud Gateway。 Spring Cloud Gateway 提供 了一个构建在 Spring 生态之上的 API 网关, 其旨在提供一种简单而有效的途径来 发送 API, 并为他们提供横切关注点 ,如: 安全性、 监控指标和弹性。
- 配置中心组件: Spring Cloud Config 实现了配置集中管理、动态刷新等配置中心的 功能。 配置通过 Git 或者简单文件来存储,支持加解密。
- 消息组件: Spring Cloud Stream 和 Spring Cloud Bus。
- Spring Cloud Stream 对于分布式消息的各种需求进行了抽象,包括发布订阅 、分组消费和消息分区等功能,实现了微服务之间的异步通信。
- Spring Cloud Bus 主要提供了服务间的事件通信(如 刷新配置)。
- 安全控制组件:Spring Cloud Security于 0Auth2.0 开放网络的安全标准, 提供了 微服务环境下的单点登录、资源授权和令牌管理等功能。
- 链路监控组件: Spring Cloud Sleuth 提供了全自动、可配置的数据埋点, 以收集微 服务调用链路上的性能数据, 并可以结合 Zipkin 进行数据存储、统计和展示。
Spring Cloud 特性
Spring Cloud 提供了多种方式来促进云原生开发风格。 Spring Cloud 提供了一系列组件,可 以在分布式系统中直接使用,这些组件大大降低了分布式系统的搭建和开发难度。
组件大多数由 Spring Boot 提供, Spring Cloud 在此基础上添加了分布式系统的相关特性。 Spring Cloud 依赖于 Spring Cloud Context 和 Spring Cloud Commons 两个公共库,
- Spring Cloud Context 为 Spring Cloud 应用程序上下文( ApplicationContext)提供了大 量的实用工具和特性服务
- Spring Cloud Common 是针对不同的 Spring Cloud 实现(如 Spring Cloud Netflix Eureka fl Spring Cloud Consul 两种不同的服务注册与发现实现)提供 上层抽象和公共类。
Spring Cloud Context :应用上下文
Bootstrap 上下文 :
除了应用上下文配置( application.yml 或者 application.properties)之外, Spring Cloud 应用程序提供与 Bootstrap 上下文配置相关的应用属性。 Bootstrap 上下文对于主程序来说是一个父级上下文,它支持从外部资源中加载配置文件,和解密本地外部配置文件中 的属性。 Bootstrap 上下文和应用上下文将共享一个环境( Environment),这是所有 Spring 应用程序的外部属性来源。 一般来讲, Bootstrap 上下文中的属性优先级较高,所以它们不能被本地配置所覆盖。
Bootstrap 上下文使用与主程序不同的规则来加载外部配置。 bootstrap.yml 用于为 Bootstrap 上下文加载外部配置,区别于应用上下文的 application.yml 或者 application. properties
-
spring:
-
application:
-
name: my-application
-
cloud:
-
config:
-
uri:
${CONFIG_SERVER :http://localhost:8080}
2. 应用上下文层级
Spring 的上下文有一个特性 :子级上下文将从父级中继承属性源和配置文件。
如果通过 bootstrap.yml 来配置 Bootstrap 上下文,且在设定好 父级上下文的情况下, bootstrap.yml 中的属性会添加到子级的上下文。 它们的优先级低于 application.yml 和其他添加到子级中作为创建 Spring Boot 应用的属性源。
基于属性源的排序规则, Bootstrap 上下文中的属性优先,但是需要注意这些属性并不 包含任何来自 bootstrap.yml 的数据。 bootstrap.yml 中的属性具备非常低的优先级,因此可 以作为默认值。
将父级上下文设置为应用上下文来扩展上下文的层次结构。 Bootstrap 上下 文将会是最高级别上下文的父级。 每一个在层次结构中的上下文都有它自 己的 Bootstrap 属 性源(可能为空),来避免无意中将父级上下文中的属性传递到它的后代中。
3. 修改 Bootstrap 配置文件的位置
bootstrap.yml 的位置可以通过在配置属性中设置 spring.cloud.bootstrap.name (默认是 bootstrap)或者 spring.cloud.bootstrap. location 来修改。
4. 重载远程属性
通过 Bootstrap 上下文添加到应用程序的属性源通常是远程的,例如来自配置中心,通常本地的配置文件不能覆盖这些远程属性源。一般来说过,启动命令行参数的优先级高于远程配置,可以通过设定启动命令行参数的方式覆盖远程配置
应用程序的系统属性或者配置文件覆盖远程属性,那么远程属性源必须设 置为 spring.cloud.config.allowOverride=true (这个配置在本地设置不会生效)。 在远程属性 源中设定上述配置后,就可以通过更为细粒度的设置来控制远程属性是否能被重载。
5. 自定义 Bootstrap 配置
第四章,服务注册与发现: Eureka
通常来说服务注册与发现包括两部分一个是服务器端,另一个是客户端。
Server 是 一个公共服务, 为 Client 提供服务注册和发现的功能,维护注册到自身的 Client 的相关信 息,同时提供接口给 Client 获取注册表中其他服务的信息,使得动态变化的 Client 能够进 行服务间的相互调用。
Client 将自己的服务信息通过一定的方式登记到 Server 上,并在正 常范围内维护自己信息一致性,方便其他服务发现自己,同时可以通过 Server 获取到自己 依赖的其他服务信息,完成服务调用。
Spring Cloud Netflix Eureka 是 Spring Cloud 提供用于服务发现和注册的基础组件,是 搭建 Spring Cloud 微服务架构的前提之一。 Eureka 作为一个开箱即用的基础组件,屏蔽了 底层 Server 和 Client 交互的细节,使得开发者能够将精力更多地放在业务逻辑上,加快微 服务架构的实施和项目的开发。
基础应用
在 Netflix 中 , Eureka 是一个 RESTful 风格的服务注册与发现的基础服务组件。 Eureka 由两部分组成,
- Eureka Server, 提供服务注册和发现功能,即我们上面所说的服务 器端;
- Eureka Client,它简化了客户端与服务端之间的交互。
Eureka Client 会定 时将自己的信息注册到 Eureka Server 中,并从 Server 中发现其他服务。 Eureka Client 中内 置一个负载均衡器,用来进行基本的负载均衡。
通常来讲,一个 Eureka Server 也是一个 Eureka Client,它会尝试注册自己,所以需要至少一个注册中心 的 URL 来定位对等点 peer。 如果不提供这样一个注册端点,注册中心也能工作,但是会 在日志中打印无法向 peer 注册自己的信息。 在独立( Standalone) Eureka Server 的模式下, Eureka Server 一般会关闭作为客户端注册自己的行为。
Eureka Server 与 Eureka Client 之间的联系主要通过心跳的方式实现。 心跳( Heartbeat) 即 Eureka Client 定时向 Eureka Server 汇报本服务实例当前的状态,维护本服务实例在注册 表中租约的有效性。
启动 Eureka Server 后,应用会有一个主页面用来展示当前注册表中的服务实例信息并 同时暴露一些基于 HTTP 协议的端点在/eureka 路径下,这些端点将由 Eureka Client 用于注 册自 身、获取注册表信息以及发送心跳等。
- 搭建 Eureka 服务注册中心
- 搭建 Eureka 服务提供者
- 搭建 Eureka 服务调用者
- Eureka 服务注册和发现
与服务注册中心交换信息 :DiscoveryC!ient 来源于 spring-cloud-client-discove可, 是 Spring Cloud 中定义用来服务发 现的公共接口,在 Spring Cloud 的各类服务发现组件中(如 Netflix Eureka 或 Consul)都有相应的实现。 它提供从服务注册中心根据 serviceld 获取到对应服务实例信息的能力。 当一个 服务实例拥有 DiscoveryClient 的具体实现时,就可以从服务注册中心中发现其他的服务实例。
服务发现原理
首先对 AWS 上的区域(Regin )和可用区(Availability Zone )进行简单的介绍。
- 区域: AWS 根据地理位置把某个地区的基础设施服务集合称为一个区域,区域之 间相对独立。 在架构图上, us-east- 1c、 us-east-1 d 、 us-east-1巳表示 AWS 中的三个 设施服务区域,这些区域中分别部署了一个 Eureka 集群。
- 可用区 : AWS 的每个区域都是由多个可用区组成的,而一个可用区一般都是由多 个数据中心(简单理解成一个原子服务设施)组成的。 可用区与可用区之间是相互 独立的,有独立的网络和供电等,保证了应用程序的高可用性。 在上述的架构图 中, 一个可用区中可能部署了多个 Eureka, 一个区域中有多个可用区,这些 Eureka 共同组成了一个 Eureka 集群。
组件与行为 :
- Application Service:是一个 Eureka Client,扮演服务提供者的角色,提供业务服务, 向 Eureka Server 注册和更新自己的信息,同时能从 Eureka Server 注册表中获取到其他服务的信息。
- Eureka Server :扮演服务注册中心的角色,提供服务注册和发现的功能。 每个 Eureka Cient 向 Eureka Server 注册自己的信息,也可以通过 Eureka Server 获取到其 他服务的信息达到发现和调用其他服务的目的。
- Application Client :是一个 Eureka Client,扮演了服务消费者的角色,通过 Eureka Server 获取注册到其上其他服务的信息,从而根据信息找到所需的服务发起远程调用。
- Replicate: Eureka Server 之间注册表信息的同步复制,使 Eureka Server 集群中不同 注册表中服务实例信息保持一致。
- Make Remote Call :服务之间的远程调用。
- Register:注册服务实例, Client 端向 Server 端注册自身的元数据以供服务发现。
- Renew :续约,通过发送心跳到 Server 以维持和更新注册表中服务实例元数据的有 效性。 当在一定时长内, Server 没有收到 Client 的心跳信息,将默认服务下线,会 把服务实例的信息从注册表中删除。
- Cancel :服务下线, Client 在关闭时主动向 Server 注销服务实例元数据,这时 Client 的服务实例数据将从 Server 的注册表中删除。
- Get Registry : 获取注册表, Client 向 Server 请求注册表信息,用于服务发现,从而 发起服务间远程调用。
Eureka Client 源码解析:
DiscoveryClient 是 Spring Cloud 中用来进行服务发现的顶级接 口,在 Netflix Eureka 或者 Consul 中都有相应的具体实现类 , 在 4.1 节基础应用中有所介绍 ,该接口提供的方法如下:
-
//DiscoveryClient. java
-
public
interface DiscoveryClient {
-
//获取实现类的描述
-
String description() ;
-
//通过服务工d获取服务实例的信息
-
List<Serviceinstance> getInstatces(String serviceid) ; //获取所有的服务实例
Id List<String> getServices() ;
EurekaClient 来 自于 com.netflix.discovery 包中,其默认实现为 com.netflix.discovery. DiscoveryClient,属于 eureka-client 的源代码, 它提供了 Eureka Client 注册到 Server 上、续 租、 下线以及获取 Server 中注册表信息等诸多 关键功能。 Spring Cloud 通过组合方式调用了Eureka 中的服务发现方法。
服务发现客户端
为了对 Eureka Client 的执行原理进行讲解, 首先需要对服务发现客户端 com.netflix. discover.DiscoveryClient 职能以及相关类进行讲解,它负责了与 Eureka Seever 交互的关键逻辑。
DiscoveryClient 职责
DiscoveryClient 是 Eureka Client 的核心类,包括与 Eureka Server 交互的关键逻辑,具 备了以下职能:
- 注册服务实例到 Eureka Server 中;
- 发送心跳更新与 Eureka Server 的租约;
- 在服务关闭时从 Eureka Server 中取消租约,服务下线;
- 查询在 Eureka Server 中注册的服务实例列表。
2. DiscoveryClient 类结构:
DiscoveryClient 继承了 LookupService 接口, LookupService 作用是发现活跃的服务实例,
-
//
-
// Source code recreated from a .class file by IntelliJ IDEA
-
// (powered by Fernflower decompiler)
-
//
-
-
package com.netflix.discovery.shared;
-
-
import com.netflix.appinfo.InstanceInfo;
-
import java.util.List;
-
-
public
interface LookupService<T> {
-
-
Application getApplication(String var1);
-
-
Applications getApplications();
-
-
List<InstanceInfo> getInstancesById(String var1);
-
-
InstanceInfo getNextServerFromEureka(String var1, boolean var2);
-
}
Application 持有服务实例信息列表 ,它可以理解成同一个服务的集群信息,这些服务 实例都挂在同一个服务名 appName 下。 InstanceInfo 代表一个服务实例信息。 Application 部分代码如下:
为了保证原子性操作, Application 中对 Instancelnfo 的操作都是同步操作。
Applications 是注册表中所有服务实例信息的集合, 里面的操作大多也是同步操作。 EurekaC!ient 继承了 LookupService 接口,为 DiscoveryClient 提供了一个上层接 口,
EurekaCient 在 LookupService 的基础上扩充了更多的接 口 ,提供了更丰富的获取服务 实例的方式 , 主要有:
- 提供了多种方式获取 Instancelnfo, 例如根据区域、 Eureka Server 地址等获取。
- 提供了本地客户端(所处的区域、 可用区等) 的数据,这部分与 AWS 密切相关。 q 提供了为客户端注册和获取健康检查处理器的能力。
转载:https://blog.csdn.net/sanhewuyang/article/details/104809338