文章目录
微服务框架的演进
微服务架构首先要面对分布式架构的内生复杂性,即:服务通信和服务治理的复杂性,例如:服务发现、熔断、限流、全链路追踪等挑战。
一个完整的微服务系统底座的基本功能应该包含:
- API 网关:微服务 API 托管、认证和鉴权、负载均衡等。
- 资源管理:计算、存储、网络资源的管理。
- 编排(解决服务部署问题):调度、部署和升级。
- 熔断、服务降级、限流(解决服务容错问题)。
- 消息总线(解决服务间调用问题):轻量级的 MQ 或 HTTP。
- 服务中心(解决服务发现问题):服务注册、发现、订阅。
- 监控和告警:监控每个服务的状态,必要时产生告警。
- 日志和审计:日志的汇总,分类和查询。
- 调用链跟踪:问题跟踪调试框架。
第一代微服务框架
第一代微服务框架,如 Dubbo 或 Spring Cloud 以代码库的方式来封装这些能力。这些代码库被构建在应用程序本身中,随着应用一起发布和维护。显而易见的,两者都是只适用于特定的应用场景和开发环境,它们的设计目的并不是为了支持通用性和多语言性。并且它们只是 Dev 层的框架,缺少 DevOps 的整体解决方案(这正是微服务架构需要关注的)。
Spring Cloud
Spring Cloud 为开发者提供了快速构建分布式系统的通用模型的工具,包括:配置管理、服务发现、熔断器、智能路由、微代理、控制总线、一次性令牌、全局锁、领导选举、分布式会话、集群状态等。
主要项目有:
- Spring Cloud Config:由 Git 存储库支持的集中式外部配置管理。配置资源直接映射到 Spring Environment。
- Spring Cloud Netflix:与各种 Netflix OSS 组件(Eureka,Hystrix,Zuul,Archaius 等)集成。
- Spring Cloud Bus:用于将服务和服务实例与分布式消息传递联系起来的事件总线。用于在集群中传播状态更改,例如:配置更改事件。
- Spring Cloud for Cloudfoundry:将您的应用程序与 Pivotal Cloudfoundry 集成。提供服务发现实现,还可以轻松实现通过 SSO 和 OAuth2 保护资源,还可以创建 Cloudfoundry 服务代理。
- Spring Cloud - Cloud Foundry Service Broker:提供构建管理一个 Cloud Foundry 中服务的服务代理的起点。
- Spring Cloud Cluster:领导选举和通用状态模型(基于 ZooKeeper,Redis,Hazelcast,Consul 的抽象和实现)。
- Spring Cloud Consul:结合 Hashicorp Consul 的服务发现和配置管理。
- Spring Cloud Security:在 Zuul 代理中为负载平衡的 OAuth2 休眠客户端和认证头中继提供支持。
- Spring Cloud Sleuth:适用于 Spring Cloud 应用程序的分布式跟踪,与 Zipkin,HTrace 和基于日志(例如 ELK)跟踪兼容。
- Spring Cloud Data Flow:针对现代运行时的可组合微服务应用程序的云本地编排服务。易于使用的 DSL,拖放式 GUI 和 REST-API 一起简化了基于微服务的数据管道的整体编排。
- Spring Cloud Stream:轻量级事件驱动的微服务框架,可快速构建可连接到外部系统的应用程序。使用 Apache Kafka 或 RabbitMQ 在 Spring Boot 应用程序之间发送和接收消息的简单声明式模型。
- Spring Cloud Stream Application Starters:Spring Cloud 任务应用程序启动器是 Spring Boot 应用程序,可能是任何进程,包括不会永远运行的 Spring Batch 作业,并且它们在有限时间的数据处理之后结束/停止。
- Spring Cloud ZooKeeper:ZooKeeper 的服务发现和配置管理。
- Spring Cloud for Amazon Web Services:轻松集成托管的 Amazon Web Services 服务。它通过使用 Spring 的 idioms 和 APIs 便捷集成 AWS 服务,例如:缓存或消息 API。开发人员可以围绕托管服务,不必关心基础架构来构建应用。
- Spring Cloud Connectors:使 PaaS 应用程序在各种平台上轻松连接到后端服务,如:数据库和消息代理。
- Spring Cloud Starters:作为基于 Spring Boot 的启动项目,降低依赖管理(在 Angel.SR2 后,不在作为独立项目)。
- Spring Cloud CLI:插件支持基于 Groovy 言快速创建 Spring Cloud 的组件应用。
Dubbo
Dubbo 是一个阿里巴巴开源出来的一个分布式服务框架,致力于提供高性能和透明化的 RPC 远程服务调用方案,以及 SOA 服务治理方案。
其核心部分包含:
- 远程通讯: 提供对多种基于长连接的 NIO 框架抽象封装,包括多种线程模型,序列化,以及 “请求-响应” 模式的信息交换方式。
- 集群容错:提供基于接口方法的透明远程过程调用,包括多协议支持,以及软负载均衡,失败容错,地址路由,动态配置等集群支持。
- 自动发现:基于注册中心目录服务,使服务消费方能动态的查找服务提供方,使地址透明,使服务提供方可以平滑增加或减少机器。
下一代微服务框架 — Service Mesh
Service Mesh 作为服务间通信的基础设施层,可以简单理解为:Service Mesh 是微服务之间的 TCP 和 IP 协议,负责服务之间的网络调用、限流、熔断和监控。
对于应用程序开发而言,开发者通常不需要关心 L3、L4 层的网络通信协议。同样的,使用 Service Mesh 之后,微服务之间就无须关心服务之间的通信那些,原来使用 Spring Cloud 或 Dubbo 框架来实现的通信代码逻辑了。
在 CaaS 中,Service Mesh 作为 Sidecar 运行,对微服务来说是透明,但所有微服务之间的流量都会通过它,所以对微服务的流量控制都可以在 Service Mesh 中实现。可见 Service Mesh 是云原生理念中 “容器设计模式” 的典范。目前流行的 Service Mesh 开源软件有 Linkerd、Envoy 和 Istio。
Linkerd 和 Envoy 比较相似,都是一种面向服务通信的网络代理,均可实现诸如服务发现、请求路由、负载均衡等功能。它们的设计目标就是为了解决服务之间的通信问题,使得应用对服务通信无感知,这也是 Service Mesh 的核心理念。
Linkerd 和 Envoy 像是分布式的 Sidebar,多个类似 Linkerd 和 Envoy 的 Proxy 互相连接,就组成了 Service Mesh。而 Istio 则是站在了一个更高的角度,它将 Service Mesh 分为了 Data Plane 和 Control Plane。Data Plane 负责微服务间的所有网络通信,而 Control Plane 负责管理 Data Plane Proxy。
Istio
Istio 提供了一个完整的解决方案,通过为整个 Service Mesh 提供行为洞察和操作控制来满足微服务应用程序的多样化需求,且不需要改动任何微服务的业务代码。
Istio 提供了许多 Service Mesh 的关键功能:
- 流量管理:控制服务之间的流量和 API 调用的流向,使得调用更可靠,并使网络在恶劣情况下更加健壮。
- 可观察性:了解服务之间的依赖关系,以及它们之间流量的本质和流向,从而提供快速识别问题的能力。
- 策略执行:将组织策略应用于服务之间的互动,确保访问策略得以执行,资源在消费者之间良好分配。策略的更改是通过配置网格而不是修改应用程序代码。
- 服务身份和安全:为网格中的服务提供可验证身份,并提供保护服务流量的能力,使其可以在不同可信度的网络上流转。
Istio 提供了一种简单的方式来构建 Service Mesh,只需要在 Pod 中部署一个特殊的 Sidecar Container,然后使用 Istio 的控制面来配置和管理代理,拦截微服务之间的所有网络通信。
Istio 的软件架构从逻辑上分为数据面和控制面:
- 数据面:由一组智能代理(Envoy)组成,代理逻辑部署为 Sidecar,调解和控制微服务之间所有的网络通信。
- 控制面:负责管理和配置代理来路由流量,以及在运行时执行策略。
Envoy
Envoy 是一个面向微服务架构的 L7 代理以及通信总线,为了实现:对于应用程序而言,网络应该是透明的,当发生网络和应用程序故障时,能够很容易定位出问题的根源。
Envoy 可提供以下特性:
- 外置进程架构:跨编程语言。
- 可快速升级。
- 使用 C++11 编码:能够提供高效的性能。
- L3/L4 过滤器:核心是一个 L3/L4 网络代理,能够作为一个可编程过滤器实现不同 TCP 代理任务,插入到主服务当中。通过编写过滤器来支持各种任务,如:原始 TCP 代理、HTTP 代理、TLS 客户端证书身份验证等。
- HTTP L7 过滤器:支持一个额外的 HTTP L7 过滤层。HTTP 过滤器作为一个插件,插入到 HTTP 链接管理子系统中,从而执行不同的任务,如:缓冲,速率限制,路由/转发,嗅探 Amazon 的 DynamoDB 等等。
- 支持HTTP/2:在 HTTP 模式下,支持 HTTP/1.1、HTTP/2,并且支持 HTTP/1.1、HTTP/2 双向代理。这意味着 HTTP/1.1 和 HTTP/2 在客户机和目标服务器的任何组合都可以桥接。
- HTTP L7 路由:在 HTTP 模式下运行时,支持根据 content type、runtime values 等,基于 Path 的路由和重定向。
- 支持 gRPC:gRPC 是 RPC 框架,使用 HTTP/2 作为底层的多路传输。HTTP/2 承载的 gRPC 请求和应答,都可以使用 Envoy 的路由和 LB 能力。
- 支持 MongoDB L7:支持获取统计和连接记录等信息。
- 支持 DynamoDB L7:支持获取统计和连接等信息。
- 服务发现:支持多种服务发现方法,包括异步 DNS 解析和通过 REST 请求服务发现服务。
- 健康检查:含有一个健康检查子系统,可以对上游服务集群进行主动的健康检查。也支持被动健康检查。
- 高级 LB:包括自动重试、断路器,全局限速,阻隔请求,异常检测。未来还计划支持请求速率控制。
- 前端代理:可作为前端代理,包括 TLS、HTTP/1.1、HTTP/2,以及 HTTP L7 路由。
- 极好的可观察性:对所有子系统,提供了可靠的统计能力。目前支持 statsd 以及兼容的统计库。还可以通过管理端口查看统计信息,还支持 第三方的分布式跟踪机制。
- 动态配置:提供分层的动态配置 API,用户可以使用这些 API 构建复杂的集中管理部署。
Kubernetes + Service Mesh = 完整的微服务框架
Kubernetes 是容器调度编排的事实标准,并且 Istio 天生的支持 Kubernetes,这就弥合了应用编排框架与 Service Mesh 之间的空隙。Istio 等 Service Mesh 组件的出现补足了 Kubernetes 在微服务间服务通讯上的短板。
虽然 Dubbo、Spring Cloud 等都是成熟的微服务框架,但是它们或多或少都会和具体语言或应用场景绑定,并只解决了微服务 Dev(开发)层面的问题。若想解决 Ops(运维)问题,它们还需和诸如 Cloud Foundry、Mesos、Docker Swarm 或 Kubernetes 这类资源调度框架做结合。但是这种结合又由于初始设计和生态,有很多适用性问题需要解决。
Kubernetes 则不同,它本身就是一个 “不可变基础设施”,与开发语言无关的、通用的容器管理平台,它可以支持运行云原生和传统的容器化应用。并且它覆盖了微服务的 Dev 和 Ops 阶段,结合Service Mesh,它可以为用户提供完整端到端的微服务体验。
在未来,一个趋近于 PaaS 形态的微服务框架技术栈应该是如下形式:
- IaaS:提供了资源能力(计算、存储、网络)。
- CaaS:提供容器编排能力。
- Service Mesh:提供微服务间东西向通信的能力。
- APIGW:对外暴露微服务的南北向业务入口。
容器之于微服务架构
不同微服务之间可能存在一些异构,为了让每一个团队在微服务体系下发挥最大效能,需要允许不同团队采用不同的编程语言,甚至不同的运行环境来去运行这些微服务。因此,在运维和管理微服务时,最初其实并没有一套统一的标准去处理的异构环境,这也是为什么后来容器技术变得流行起来,它的一个重要作用就是通过一层标准的封装以及标准的运行时,来标准化微服务部署。这样从生命周期管理的角度来看,每一个微服务之间的差异就会变少,共同点变多。所以容器也被称为 “不可变基础设施”。
Kubernetes 之于微服务架构
Kubernetes 的作用是帮助把已经标准化的微服务最便捷地运行到底层资源上面。我们讲到的存储、计算、网络都通过 Kubernetes 这层进行了统一抽象和封装,让已经被容器统一的微服务能够直接运行到 Kubernetes 平台。因此,运维人员不用再苦恼如何去把某个微服务分配到具体的某一个资源或计算单元上去。通过容器和容器平台,大大简化了微服务本身的生命周期管理,简化了微服务自身的运维管理问题,也促进了微服务更多地被企业所采用。
Kubernetes 具有一个 Pod 的概念。一个 Pod 实际上是一组容器的集合,在一个 Pod 中可以运行一个或多个容器。一般来讲,当我们采用微服务架构时,会把微服务的主体运行在主容器中,主容器的生命周期跟 Pod 自身的生命周期是一个耦合的状态。除了主容器之外,在同一个 Pod 中还会运行一些边车容器(Sidecar 容器),为主容器提供一些辅助功能,比如:日志采集、网络代理、身份鉴权等,这样微服务除了自身提供的核心业务服务以外,通过 Kubernetes 我们还可以动态添加一些额外的辅助能力,让微服务管理变得更健壮。
这种微服务应用的设计思想被称为 “容器设计模式”。
DevOps 之于微服务架构
当我们将大型的单体应用拆解为多个微服务,也一定会增加 IT 系统研发协同、交付、运维的复杂性。云原生就在于帮助微服务解决生命周期管理以及运维管理难题。
因为微服务的数量非常多,部署、管理的工作量很大。
- 开发方面:如何保证各个服务在持续开发的情况下仍然保持协同合作。
- 测试方面:服务拆分后,几乎所有功能都会涉及多个服务。原本单个程序的测试变为服务间调用的测试。测试变得更加复杂。
而随着 CI/CD 概念推广以及容器技术普及,微服务将这两种理念和技术结合起来,形成新的:“微服务 + API + 平台” 的开发模式,提出了容器化微服务的持续交付概念。
传统单体架构 DevOps 开发方式,要求产品队伍横跨产品管理、开发、QA、DBA 以及系统运维管理。
微服务架构 DevTestOps 开发方式,将一个大臃肿的整体产品开发队伍切分为根据不同微服务的划分的产品队伍,以及一个大的整体的平台队伍负责运营管理,两者之间通过 API 交互,做到了松耦合隔绝。
在测试方面,微服务架构下的测试分为三个层次:
- 端到端(集成)测试:覆盖整个系统,一般在用户界面进行测试。由于端到端测试实施难度较大,一般只对核心功能做端到端测试。一旦端到端测试失败,则需要将其分解到单元测试,分析失败原因,然后编写单元测试来重现这个问题,这样未来我们便可以更快地捕获同样的错误。
- 服务(功能)测试:针对服务接口进行测试。服务测试的难度在于服务会经常依赖一些其他服务。这个问题可以通过 Mock Server 解决:
- 单元测试:针对代码单元进行测试。我们一般会编写大量的单元测试(包括回归测试)尽量覆盖所有代码。
三种测试从上到下实施的容易程度递增,但是测试效果递减。端到端测试最费时费力,但是通过测试后我们对系统最有信心。单元测试最容易实施,效率也最高,但是测试后不能保证整个系统没有问题。
云原生的微服务架构 — 云原生应用架构综上,我们可以感受到微服务架构与容器、Kubernetes、DevOps 等云原生关键技术自然地走到了一起,构成了云原生应用架构的雏形。
云原生应用架构具有下述特点:
- 平台化:利用云作为一个平台,为微服务架构进行更多的赋能。
- 标准化:微服务本身的部署、运维,微服务之间与其它服务之间的通讯都能做到标准化,让服务与服务之间的互联互通变得更容易,服务能够跨到不同的平台上,做到一次编写、一次定义、多处运行。
- 轻量化:让研发人员关心核心业务代码、业务逻辑的研发,而不是复杂的微服务治理相关的逻辑研发。
- 产品化:希望能构建微服务相关的产品,以产品化的方式支持大家使用微服务架构,让它变得更好用、更易用。