微服务是一种应用程序架构风格,它将应用程序划分为组件,其中每个组件都是一个完整但微型的应用程序,专注于根据单一责任原则生成单个业务任务。从GUI到数据库或从服务API到数据库,以便不同的GUI和客户端应用程序可以重用相同的业务任务功能。每个微服务都有明确定义的接口和依赖关系(例如,对于其他微服务和外部资源),以便微服务可以相当独立地运行。
微服务的宗旨:使得开发更高效。通过最大限度地减少人与人之间的沟通和协调它(少一些会议多一些开发等),以及减少变更范围和风险来加速交付。
微服务架构的目标是将app组件彼此完全decouple/分离,以便可以维护、扩展等。
===========【SOA VS Microservices】================
- SOA/service-oriented architecture : Focus on reuse, technical integration issues, technical APIs
- Microservices: Focus on functional decomposition, business capabilities, business APIs
翻译为:
- SOA:专注于重用,技术集成问题,技术API
- 微服务:专注于功能分解,业务功能,业务API
=====【Key tenets of a microservices architecture】========
1)大型整体结构分为许多小型服务
- 每个服务都在自己的进程中运行
- 适用的云规则是每个容器一服务
2)服务针对单个功能进行了优化
- 每项服务只有一个业务功能
- 单一责任原则:微服务应该只有一个改变的理由
3) 通过REST API和消息代理进行通信
- 避免通过DB通信引入紧密耦合
4) 每个服务定义CI/CD(持续集成和持续部署)
- 服务以不同的速度发展
- 设置架构原则以指导系统进化发展
5) 每个服务定义HA(高可用性)和群集决策
- 一种规模或扩展策略并不适合所有微服务
- 并非所有服务都需要扩展,其他微服务需要自动扩展到大数
===========【Monolithic VS Microservices】===========
/ | Monolithic | Microservice |
架构 | 以单个逻辑可执行文件构建 | 以一套小型服务构建 |
模块化 | 基于语言功能 | 基于业务能力 |
敏捷度 | 更改涉及构建和部署整个应用程序的新版本 | 更改可以独立应用于每个服务 |
扩展 | 当有一部分是瓶颈时,需要整个应用程序进行扩展。 | 每个服务在需要时独立扩展 |
实现 | 通常全部由一种编程语言开发实现 | 每种服务都可以用不同的编程语言开发实现 |
可维护性 | 大型代码库对新开发人员是一种intimidating/威胁 | 较小的代码库更易于管理 |
部署 | 复杂部署,需要维护窗口和计划停机时间。 | 简单部署,因为每个服务都可以单独部署,停机时间最短。 |
微服务最大的要求是操作复杂性,因为有更多的移动部件需要监控和管理,一个大型的业务需求有可能需要上千个应用程序,这就需要管理和监控上千个应用程序运行情况,这对企业来说是个巨大的挑战。微服务存在的隐患:
- 微服务重视服务之间的重用独立性,重用会产生依赖关系就会存在团队之间的交互因此无法独立工作。
- 独立运行的部分越多,分布式系统就会越成为问题(网络延迟、断开连接、容错、序列化);那么找到bugEnd2End测试难度就会增加。
============= Microservice Advantages ==============
- 独立开发,并对其他服务存在有限的、显式的依赖
- 可以由一个所有团队成员都理解整个代码库的小团队开发
- 根据本团队时间表开发,以便独立于其他服务提供新版本
- 独立扩展和失败,可以隔离任何问题,不影响整个app
- 每种服务都可以用不同的语言开发实现
- 管理自己的数据以选择最佳技术和架构
===============应用架构发展—从SOA到微服务===========
SOA和微服务处理的都是通过网络进行通信的服务系统,但两者存在差异,如下面表格和diagram:
架构 | 关注点 | 结果 |
SOA | 复用 | 1.tends to align with a centrally funded model. 2. tend to be "servants of many masters" 3. 对SOA服务的更改可能会影响多个消费者。 |
Micro services | 将monolithic应用程序分解为更小,更易于管理的组件 |
2.面临DevOps,管理视图和控件的挑战 |
================================================
SOA 栈
域层(The domain layer)作为了一个服务层并封装了记录的后端系统/SoR(system of record)和记录数据库。SOA栈必须将服务序列串联为业务流程,这些业务流程本身就是宏服务(macroservices)。但是很难能保持垂直切片。
==========【微服务类型层次结构】===========
所有业务服务在架构上几乎相同,但是调度程序子类型专业化(这不显示类或继承层次结构并且显示了专业化)。这个取决于application支持的客户端类型以及这些客户端需要其调度程序的妆也化程度。如下图:
============【开发语言选择】=============
每个微服务都可以使用任何语言进行开发,只要它可以部署在云上并支持REST API。Dispatchers通常用Node实现,因为Node 擅长处理大量客户端和大量并发I/O。对于运行JS的客户端,服务器上的Node更容易适应。业务服务通常用Java编写,因为Java可以很好地处理CPU密集型任务,并且擅长连接外部系统,尤其是管理共享连接池。
==========【Backend for frontend BFF】========
前后端开发:尽量保证dispatcher/client pair在同一个团队里开发即某一个模块的前后端开人员都在同一个团队内,为了便于开发过程中的良好沟通、联调成本节约等。不到万不得已,切勿将前后端划分给不同团队之间的协作或不专业的团队来完成,这样会影响项目的开发进度。---这些类似《人月神话》,讲究是“术业有专攻”。
====【Business service microservice dependencies】====
【Typical/典型】
业务服务可以依赖于其他业务服务,只需要确保每项服务都是完整的业务任务, 切勿将DB访问层独立分离为单独的服务。若服务都是一项完整的业务任务,那么服务间(不存在相互依赖的)的协作就很好。
【Death Star/~~】
存在相互依赖的循环有向图表示了微服务之间依赖关系。遇到类似这样的业务服务相互连接成Death Star形状,面临着如何部署这样的架构?首先部署哪一个?若必须在一个(新版本)上更改API,应该更改哪些相关联的API?--避免让这样的Death Star出现在架构中!!!
===========【微服务整合/integration】===========
微服务间通信是language-neutral(语言中立),各个微服务可以用不同的语言实现。目前的标准是REST和JSON/REST,对于异步集成(asynchronous integration)尽量遵循开放的云标准,如Apache Kafka。异步协议包括AMQP、MQ Light、RabbitMQ等。
尽量不要使用XML或序列化等其他方式,这样会导致每个API提供者和消费者必须支持某种特定协议,不利用扩展。K8s服务是一组pods并提供pods之间的网络连接,而不会暴露每个pod的实际私有IP地址。同样,可以选择保持微服务的私密性并使用内置安全功能。
【同步/synchronous通信 VS 异步/asynchronous通信】
对于同步,整个循环(请求者,提供者,消息)必须在调用的整个生命周期中保持工作。根据请求的性质(长时间在后台运行)或使集成更可靠和健壮/robust,需要将一些集成点转换为异步。 使用异步,调用被分为3-4个部分。 如果任何一个失败,系统可能会重试。 并且因为请求者是无状态的,所以接收响应的实例甚至不需要是发送请求的实例。
【异步通信使微服务更加健壮】
- 在提供程序运行时,请求者不必阻塞
- 不同的请求者实例可以处理响应
- 消息传递系统保存动作和结果
【微服务内部通信】
可以混合和匹配同步/synchronous和异步/asynchronous通信,通常请求/响应—request/response调用全部是同步的或者全部是异步的,但这表明单个调用可以在一个方向同步而在另一个方向异步。常见的轻量级协议:REST(如JSON或HTTP)和Messaging(如Kafka)。可以通过以下方法实现完全解耦:
- Messaging wherever possible 尽可能使用消息
- Service registry or discovery 服务注册或发现
- Load balancing 负载均衡
- Circuit breaker patterns 断路器模式
IBM Cloud支持两种类型的APIs: 一种简单的HTTP REST API和一种复杂但功能很强的Kafka API。
===========【服务网格/Service Mesh】===========
| Monolithic Architecture | Microservice Architecture |
资源配置 | 1.明确定义的、静态的 | 1.服务可以存储在任何位置,如Data Center、公共云提供商或某种组合中 2.托管在裸机服务器、VM、容器等 服务具有多个实例或副本, 不同负载下可扩展 |
当使用微服务时会遇到如下的问题以及相应的对策:
【服务注册/Service Registry】
每个服务网格都有一个服务注册表,服务注册表是一个简单的键值对数据存储,维护所有工作服务实例及其位置的当前列表。当每个服务实例启动时,它将通过其自己的客户端代码或第三方注册器功能向服务注册表注册自己,如K8S为其集群中的容器提供第三方注册服务。服务注册表用于跟踪服务的位置和健康状况,可以以可靠的方式将请求服务定向到提供者服务。在服务实例向服务注册表注册后,服务注册表将使用in-bound和out-bound的心跳机制来保持其实例列表的最新状态。服务注册表需要以某种方式使其具有HA(高可用性)。
【服务发现和服务代理/service discovery and service proxy】
任何Service Mesh的核心是服务注册表和服务发现功能。服务注册表维护着所有服务实例及其位置的列表,当每个服务实例启动时,它会check in 服务注册表,提供其名称和位置。在check in 之后,每个服务注册表实现将具有某种心跳机制,以使其列表保持最新状态,从而删除它无法连接的任何实例。
每个服务实例类型可以是Client/服务客户端(从其他服务请求数据或功能),也可以是Server/服务提供者(向服务客户端提供数据或功能)。只要服务需要其他服务,它就会使用服务发现/Service discovery功能来查找该服务的实例。
~~~~~~~~~~~两种类型的服务发现~~~~~~~~~
1.【客户端发现/client-side discovery】
请求服务或服务客户端直接与服务注册表一起工作,以确定其所需的所有可用服务实例,并且还负责决定哪些将用于其请求的哪些服务实例中的服务实例。
可以使用几种可能的规则来确定要使用的实例。如Round-robin load balancing/循环负载均衡:将每个请求均匀地分布在所有实例上,这会将每个请求发送到列表中的下一个实例。可以使用不同类型的规则,让某些客户端访问某些提供程序实例,如测试新版本或其他。在任何情况下,客户端发现将通过客户端代码来实现负责做出决策并决定联系相应的服务实例。
2.【服务端发现/server-side discovery】
此类型需要引入两一个组件:负载均衡器/服务代理。查询服务注册表并将请求定向到适当的服务实例的任务委托给负载均衡器。 在一些实现中,例如Istio,除了仅使用循环负载平衡之外,负载平衡器可以用特定规则来编程以管理其对服务实例的选择。例如 nginx负载均衡器,它内置于普遍的几个服务网格中。
优点:只需要查询服务注册表并将请求定向到负载均衡器中实现一次的服务实例。缺点:负载均衡器是另一个要管理的组件。在大多数情况下,通常是由服务网格提供。
【自动化测试/Automated Testing】
没有什么是可靠的!常期望组件失败并为application构建弹性,以便它们能够承受/withstan这些故障。一个基本的策略是始终拥有任何给定服务的多个实例,以便application可以在给定实例的失败后继续运行,并在重新启动该实例时继续运行。
常见的自动化测试工具可以确保应用程序的弹性,如Netflix Chaos Monkey,Netflix Simian Army以及Istio内置的功能。简单介绍一下K8s内置的自动化测试流程:
- 首先创建部署
- Roll out对微服务的更改。例如希望更改初始部署中使用的镜像。使用K8S部署微服务时,更改变换会立刻体现、应用并记录在roll-out历史中。
- 使用操作和测试工具测试部署状态
- 查看部署的rollout历史并确定上次部署的版本号
- 准备就绪后,回滚到以前的版本或指定修订版本。
【断路器/Circuit breaker】
断路器模式是Istio和Netflix Hystrix附带的编程工具。断路器用于防止由于故障或延迟导致的给定服务依赖性的相应延迟,因为延迟不会导致整个应用程序中更广泛的延迟和故障。断路器允许设置超时阙值和故障阈值来实现快速失败(Fast-fail),以满足内置的构建替代计划。
可以为再次打开电路之前允许的恢复时间、再次尝试呼叫服务以及测试阈值(thresholds)这些情况配置相应的值。
【隔板/Bulkhead】
Bulkhead模式是Netflix Hystrix附带的另一个工具,它可以防止给定服务调用的响应延迟导致整个应用程序出现更广泛的问题。通过使用单独的线程池连接到其他系统的连接尝试来完成此行为,以便由给定服务的延迟或失败调用的延迟与该服务隔离,并且在进行更过请求时不使用应用程序的所有县城。通过为每个从属服务使用单独的连接池,任何服务上的故障都与该服务隔离,并且不会在应用程序中引起更广泛的问题。
===========【Istio 智能服务网格】===========
Istio是一个开放平台服务网格/Service Mesh实现,用于连接、管理和保护微服务。 通过负载平衡,服务到服务身份验证,监控等。Istio提供了一种简单的方法来创建已部署服务的网络,而无需对服务代码进行任何更改。 可以通过在整个环境中部署特殊的sidecar代理来添加对服务的Istio支持,该代理拦截微服务之间的所有网络通信,这些通信使用Istio的控制平面功能进行配置和管理。
Istio是IBM、Google和Lyft合作发布的,目的在于不需要更改应用程序代码情况下,提供微服务之间的流量管理/traffic flow management、访问策略实施/access policy enforcement、遥测数据聚合/telemetry data aggregation等功能,使得开发人员可以专注于业务逻辑并快速集成新功能。
【Why use Istio ???】
背景:随着服务网格的大小和复杂性的增加,理解和管理变得很困难。其中包括:服务发现/discovery、负载均衡/load balancing、故障恢复/failure recovery、指标和监控/metrics and monitoring以及更复杂的操作要求(如A/B testing、canary releases/canary版本、速率限制/rate limiting、访问控制/access control、端到端身份验证/end-to-end authentication)。Istio通过整体服务网格的行为洞察/behavioral insight和操作控制/operational control提供了以下几个关键功能:
1. 流量管理/Traffic management:控制服务之间的流量和API调用流量,使调用更加可靠,并在不利条件下使网络更加健壮/robust
2.可观察性/Observability:了解服务之间的依赖关系以及它们之间流量的性质和流量,提供快速识别问题的能力。
3.策略实施/Policy enforcement:将组织策略应用于服务之间的交互,并确保实施访问策略,并在消费者之间公平分配资源。通过配置网格而不是通过更改应用程序代码来进行策略更改。
4.服务标识和安全性/Service identity and security:在网格中提供具有可验证身份的服务,并提供在不同可信度的网络上流动时保护服务流量的能力。
5.平台支持/Platform support:Istio可以在各种环境中运行,包括跨云、本地、K8S、Mesos等的环境。
6.集成和定制/Integration and customization:策略实施组件可以进行扩展和自定义,以与现有的ACL、日志记录、监控、配额/quotas、审计/audit等解决方案集成。
【How Istio works】
Istio服务网格在逻辑上被分成数据平面和控制平面。两者功能如下:
- 数据平面:由一组智能代理(Envoy)组成,这些代理被部署为sidecars,用于调解和控制微服务之间的所有网络通信。
- 控制平面:负责管理和配置代理以路由流量并在运行时实施策略。
1.Sidecar Proxy/侧车代理
服务网格实现(如Istio)使用通常在pod中部署为sidecars的代理,代理控制对另一个对象的访问。Istio使用服务和客户端之间的代理,使得服务网格能够管理交互。
K8s将容器部署到pod中,并且pod中的所有容器都托管在同一节点上,pod可以管理对pod中容器的网络访问。Pod通常托管单个容器,但可以将多个pod作为一个托管单元。
Sidecars在没有改变的情况下向容器添加行为。即Sidecars和服务表现为单个增强单元。 pods作为一个单元托管Sidecars和服务。
2.Envoy/代理:一种用C++开发的高性能代理
用于调解服务网格中所有服务的所有inbound/ingress和outbound/egress流量。Istio使用Envoy的许多内置功能,例如动态服务发现,负载平衡,TLS终止,HTTP / 2和gRPC代理,断路器,运行状况检查,基于%的流量分配的分阶段部署,故障注入和丰富的指标。
Envoy作为相关服务的sidecar部署在同一个K8s pod中,这允许Istio将关于流量行为的大量信号作为属性提取,并反过来可以在混合器Mixer中用于执行策略决策并被发送到监控系统以提供关于整个网格的行为的信息。Sidecar代理模型还允许将Istio功能添加到现有部署,而无需重新构建或重写代码。
3.Mixer/混合器
Mixer是一个独立于平台的组件,负责跨服务网格实施访问控制和使用策略,并从Envoy代理和其他服务收集遥测数据。代理提取请求级别属性,将其发送到Mixer进行评估。Mixer包含一个灵活的插件模型,使其能够与各种主机环境和基础架构后端进行交互,从而根据这些细节抽象出Envoy代理和Istio管理的服务。
4.Pilot/领航员—服务发现/service discovery
Pilot为Envoy Sidecar提供服务发现,为智能路由提供流量管理功能(例如A/B 测试和canary 部署)以及弹性(超时/timeouts、重试/retries、断路器/circuit breaker等)。它将控制流量行为的高级路由规则转换为特定于Envoy的配置,并在运行时将它们传播到sidecars。 Pilot将特定于平台的服务发现机制抽象化,并将其合成为符合Envoy数据平面API的任何边车所消耗的标准格式。 这种松散耦合允许Istio在多个环境(例如,Kubernetes,Consul / Nomad)上运行,同时保持相同的运营商接口以进行流量管理。
5.Citadel/堡垒—服务发现/service discovery
Citadel(以前称为Istio Auth)使用相互TLS提供强大的服务到服务和最终用户身份验证,具有内置身份和凭证管理。 它可用于升级服务网格中的未加密流量,并使运营商能够实施基于服务标识而非网络控制的策略。 未来版本的Istio将添加细粒度的访问控制和审计,以控制和监控谁使用各种访问控制机制访问您的服务,API或资源,包括属性和基于角色的访问控制和授权挂钩。
【Istio Mesh 请求流程】
Sidecar 可以处理服务的入口和出口流量,以类似方式,Istio网格管理和控制服务和用户访问其控制下的服务的能力。使用sidecars可以在服务网格中包含以下几个属性:
1. 应用程序代码中执行的常用功能可以包含在sidecars中,这些包括遥测/telemetry,分布式跟踪/distributed tracing和TLS终止termination/启动initiation。
2.一些有用的功能(如断路器/circuit breaker、速率限制/rate limit、A/B测试、只能路由/intelligent routing、金丝雀释放/canary releases)也可以包含在sidecars中。
【Istio提供给微服务架构】
1.流量管理/Traffic Management
使用Istio的流量管理模型实质上解耦/decouple流量和基础设施扩展,让运营商通过Pilot指定流量遵循的规则,而不是哪些特定的pod / VM应该接收流量 - Pilot和智能Envoy代理负责其余部分。 因此,例如,通过Pilot指定特定服务的5%流量转到金丝雀版本/canary version,而不管金丝雀部署的大小,或根据请求的内容将流量发送到特定版本。
2.流量分离/Traffic Splitting
3.流量转移/Traffic Steering
将流量从基础设施扩展中分离,允许Istio提供存在于app代码之外的各种流量管理功能。除了用于A / B测试、金丝雀版本、缓慢回滚的动态请求路由之外,它还通过使用超时,重试和断路器来处理故障恢复,最后通过故障注入来测试跨服务的故障恢复策略的兼容性。 这些功能都是通过服务网格中部署的Envoy sidecars和代理实现的。
【Istio-服务发现和负载均衡】
Istio可以在服务网格中跨服务实例负载均衡流量。
服务注册:Istio假定存在服务注册表以跟踪应用程序中服务的pods或VMs。 它还假定服务的新实例自动注册到服务注册表,并自动删除病态的实例。 Kubernetes和Mesos等平台已经为基于容器的应用程序提供了这样的功能。 基于VM的应用程序存在大量解决方案。
服务发现:Pilot消费来自服务注册表的信息,并提供与平台无关(platform-agnostic)的服务发现接口。 网格中的Envoy实例执行服务发现并相应地动态更新其负载均衡池。
【Istio-处理失败/Handling Failures】
Envoy提供了一套开箱即用(out-of-the-box opt-in)的选择加入故障恢复/failure recovery功能,可以通过应用程序中的服务进行利用,并且可以通过Istio的流量管理规则在运行时动态配置。具体如下:
- Timeouts 超时
- 具有超时预算和重试之间的可变抖动/jitter的有界重试
- 限制并发连接数和对上游服务的请求
- 对负载均衡池的每个成员进行主动(定期)运行状况检查
- 对负载均衡池按实例应用的细粒度断路器(被动运行状况检查)
原版:
重试之间的抖动可以最大限度地减少重试对重载上游服务的影响,而超时预算可确保调用服务在可预测的时间范围内获得响应。
主动和被动运行状况检查的组合可以最大限度地减少在负载均衡池中访问不健康实例的可能性。 当与平台级运行状况检查(例如Kubernetes或Mesos支持的运行状况检查)结合使用时,应用程序可以确保可以从服务网格中快速删除不健康的pods,容器或VMs,从而最大限度地减少请求失败和对延迟的影响。这些功能共同使服务网格能够容忍故障节点并防止本地故障与其他节点级联/cascading不稳定。
【Istio-故障注入/Fault Injection】
Istio可以将特定协议/protocol-specific的故障注入到网络中,而不是杀死pods,这会延迟或破坏TCP层的数据包。理由是,无论网络级故障如何,应用层观察到的故障都是相同的,并且可以在应用层注入更有意义的故障(例如,HTTP错误代码)以实现应用程序的弹性。
可以配置要注入符合特定调价你的请求故障,并且进一步限制应该发生故障的请求概率。可以注入的两种类型故障:
- 延迟/delays:时序故障,模仿增加的网络延迟或过载的上游服务。
- 中止/aborts:模拟/ mimic上游服务失败的崩溃失败。通常以HTTP错误代码或TCP连接失败的形式出现。
【Istio-相互TLS身份验证/Mutual TLS Authentication】
Citadel的目标是在不需要更改服务代码的情况下增强微服务及其通信的安全性。它提供密钥管理系统包含自动化密钥和证书生成,分发,轮换和撤销。具体负责以下任务:
- 为每个服务提供强大身份来代表其角色,以实现跨群集和云的互通
- 确保服务到服务通信和最终用户到服务通信
Citadel的架构图,其中包括3个主要组件:身份/Identity、密钥管理/Key Management、通信安全/Communication Security
此图描述了Citadel如何用于保护作为服务帐户前端团队运行的服务前端与作为服务帐户后端团队运行的服务后端之间的服务到服务通信。 Istio支持在Kubernetes容器和VM或裸机上运行的服务。
Citadel使用秘密卷/secret volume装载将密钥/证书(keys/certs)从Istio CA传送到Kubernetes容器。 对于在VM或裸机/bare-metal上运行的服务,使用节点代理,该代理是在每个VM或裸机上运行的进程。 它在本地生成私钥和CSR(certificate signing request证书签名请求),将CSR发送到Istio CA进行签名,并将生成的证书与私钥一起发送给Envoy。