【万字长文、多图】微服务架构学习笔记

593 阅读21分钟

这是一份是我在极客时间学习《微服务架构核心20讲》时做的笔记。

大纲

1.什么是微服务架构?
2.架构师如何权衡微服务的利弊?
3.康威法则和微服务给架构师怎样的启示
4.企业应该在什么时候开始考虑引入微服务
5.怎么的组织架构更适合微服务?
6.如何理解阿里巴巴提出的微服务中台战略
7.如何给出一个清晰简洁的服务分层方式?
8.微服务总体技术架构是怎样设计的
9.微服务最经典的三种服务发现机制
10.微服务 API 服务网关(一)“原理”
11.微服务 API 服务网关(二)“开源网关 Zuul”
12.跟 Netflix 学习微服务路由发现体系
13.集中式配置中心的作用和原理
14.微服务通讯方式 RPC vs. REST
15.微服务架构需要考虑哪些治理环节
16.微服务监控系统分层和监控架构
17.微服务的调用链监控该如何选择
18.微服务的容错限流是如何工作的
19.Docker 容器部署技术 & 持续交付流水线
20.容器集群调度和基于容器的发布体系

什么是微服务架构?

  1. 微服务主张将单体应用拆成小的独立服务
  2. 微服务运行在独立的进程中,以进程的方式来横向扩展。(Java 运行在 Tomcat 中,NodeJS,容器等)
  3. 轻量级的通信机制(HTTP)
  4. 基于业务能力(SOA)来构建
  5. 独立部署,每个团队维护自己的部署
  6. 无集中式的管理,原来模式会有架构团队来规划标准:统一技术栈、统一存储方式。而微服务主张每个团队根据自己的的业务需要选择自己对擅长的、最能解决当前技术问题的技术栈,甚至采用不用的存储方式。

Netflix - 微服务定义:Loosely coupled (松耦合), service oriented architecture (面向服务架构 - SOA) with bounded context(有界上下文或局部状态)。

架构师如何权衡微服务的利弊?

微服务优势:

  1. 强模块化边界,从类方式 -> 组件(类库)-> 以服务的方式做模块化(每个团队独立的开发和维护自己的服务,开发完其他团队可以直接调用这个服务,而不需要像 jar 包一样去分享)
  2. 可独立部署,不要引入其他团队来一起部署
  3. 技术多样性,分散式治理。不是越多越好(技术复杂性)

微服务带来的挑战:

  1. 分布式复杂性,单块应用由一个团队就能搞定。微服务化变成分布式系统,会涉及到几十、上百个服务,服务之间相互沟通合作使得系统会变得非常复杂,一般的开发人员或团队都不能清晰的了解整个系统如何工作的
  2. 最终一致性,每个团队有自己的数据存贮,例如:A 团队有订单数据、B 团队也有订单数据,当A 团队改变订单数据时,需要同步到有类似概念的团队,这就涉及到数据一致性的问题
  3. 运维复杂性,运维的是一个分布式系统,对监控、容量规划、可靠性、稳定性提出了非常大的挑战
  4. 测试复杂性,需要多个团队联合做集成测试

康威法则和微服务给架构师怎样的启示

康威法则:

“Organizations which design systems ... are constrained to produce designs which are copies of the communication structures of these organizations.”

设计系统的组织,其产生的设计和架构,等价组织的组织架构。

初期团队规模、业务量不大、系统比较简单,主要尝试业务模式能不能起来。随着业务增长、团队规模变大(从一个团队扩大到多个团队),这时候如果系统架构仍然是单块应用就会和多团队产生不匹配的情况(违反了康威法则,即单块应用架构没有反应组织架构)就会出现矛盾、协调成本变高、交付效率变低。

微服务是一种解决手段,将单块应用拆分成若干个微服务(图:组织内部有 3 个团队,把单块架构拆分成 S1、S2、S3 3 个服务,每个团队负责维护自己的服务。符合康威法则)

扩展:每个架构师都应该研究下康威定律

企业应该在什么时候开始考虑引入微服务

初期业务复杂性不高,开发的应用系统主要是验证商务模式。这个时候建议采用单块应用。不推荐微服务,因为微服务前期有基础设施要求,使得生产力变低。

随着应用变得成功、用户变多、系统复杂性变得越来越高,如果仍然使用单块应用就会违背康威法则,使得生产力会随着系统复杂性而降低,这时候就要考虑使用微服务。

考虑使用微服务的点(图中交叉点),个人经验:团队接近百人研发时应该考虑采用微服务架构。

如何选择?

  1. 开始就走微服务架构
  2. 单块优先

不推荐方案 1:因为一开始的时候对问题领域并不是很理解,很难把控怎么来拆分这个服务、划分服务边界。另外有可能花了很多精力开发一套微服务,但是这个应用并不被客户接受(应用没有被市场验证,可能会失败)

推荐: 单块优先,随着业务推进,架构师会对业务领域有越来越清晰的了解,这个时候如果单块应用不能满足业务发展需求了,研发效率开始下降(到了交叉点)。需要将某些功能点拆分出来,后续陆陆续续随着业务团队变大可以将其他功能点陆续拆分出来,最后变成一个微服务架构

怎么的组织架构更适合微服务?

横坐标: 业务价值流交付过程(研发 -> 上线 -> 运维)

纵坐标: 业务能力,不同的业务线(业务团队)

传统企业: 团队划分是严格按照职能的(独立职能部门),当有项目来的时候会从每个团队抽调一些人来组成交付团队,当项目完成后这些人会回到各自的职能团队。

这个团队的劣质:

  1. 沟通成本比较大(团队沟通)
  2. 反馈慢、周期长

基于微服务跨职能的组织模式:每个团队跨职能既有产品专家、用户体验专家、研发、测试专家,整个形成一个端到端的闭环。这些人围绕在微服务周围进行开发、测试和交付、不会因为项目结束而解散。

DBA、运维也以产品的方式来交付平台产品(将计算、网络存储、持续交付的能力封装在一个平台内),对外提供 API 来支持不同的业务线快速的交付、迭代。

端到端控制权: 团队内部人要负责:架构、设计、开发、评审、测试、发布、运行和支持。

团队规模:根据亚马逊的两个披萨原则 – 12个人左右(2 个披萨能搞定) 谁开发、谁就要去构建、去负责运行

微服务架构本质上是组织架构的重组 – Netflix 前架构师 Andrew

如何理解阿里巴巴提出的微服务中台战略

现代技术体系分四层:

  1. IaaS层:基础设施即服务:计算、存储、网络、监控等由基础运维团队来负责,提供底层基础设施
  2. PaaS层:平台即服务:应用监控、持续交付、服务框架、后台服务(大数据、AI)
  3. 核心业务层:
  4. 应用层
  5. 渠道(第三方接入)

阿里巴巴提出大中台(技术中台 + 业务中台),小前台战略(前端业务更小、更灵活,能根据市场的变化、业务的需求不断的演化)从而赋能业务的持续创新,产生各种业务模式、快速响应市场需求。

PaaS 是微服务基础设施层,核心业务层是公司的核心领域能力把它微服务化、抽象化沉淀下来的核心能力,这层能力依赖下一层的 PaaS 云平台、大数据及AI,同时向上支撑不同的业务线去交付业务应用。

如何给出一个清晰简洁的服务分层方式?

分成两层(不同公司有自己的分层,有的三、四层,有的只有一层:统称服务或微服务)

  1. 基础服务:支撑性服务,如电商网站的商品服务、用户服务、购物车服务。都比较基础性、原子性
  2. 聚合服务:由于有不同的外部接入端,会对服务做适当的适配、聚合和裁剪的工作

微服务总体技术架构是怎样设计的

  1. 接入层:外部、内部流量接入
  2. 网关层:流量接入后进入网关层,网关层在微服务体系中占有非常重要的地位,主要做反向路由、限流熔断、安全等跨横切面的功能
  3. 业务服务层:分为聚合层和基础层
  4. 支撑服务:微服务需要支撑体系来支撑它,例如:服务的注册发现、集中化配置、容错限流、认证授权、日志聚合、监控告警、后台服务(MQ、缓存、Job、数据访问)
  5. 平台服务层:发布系统、集群资源调度、镜像治理、IAM(权限管控)
  6. 基础设施:主要有运维团队维护

微服务最经典的三种服务发现机制

  1. 传统基于LB (负载均衡)的模式
  2. 进程内LB 模式
  3. 主机独立LB 模式

方式一:服务提供商上线后会向运维申请一个域名,然后运维配置负载均衡器。当用户访问域名时会域名解析到负载均衡器,负载均衡器进而指向到后台服务器(多份)

优点:普遍的做法、比较简单;消费者接入的成本比较低 缺点:服务的配置、域名的配置都需要运维的介入;集中的LB 可能会是一个单点,如果集中式LB 挂掉会影响到整个服务无法访问;性能损失,当消费者调用后台服务时必须穿透LB ,会有性能开销。

方式二:将LB 功能移动到应用的进程内,服务提供商会自动通过注册方式注册到服务注册表,并定期发送心跳。服务消费通过客户端(带有服务发现和负载均衡功能)LB 调用后台服务,并且LB会定期同步服务注册表中的服务信息。

优点: 没有集中式的LB,性能会好,不存在单点问题

缺点: 在多语言环境中,必须为每一个消费者去开发有这样一个客户端,升级成本和多语言支持成本会高些

方式三:在前面两种方式基础上做了一个折中,将LB功能以一个独立进程的方式部署在一台独立的主机上(既不是集中式LB,也不是在进程内客户端的LB),其他和方式二类似。

微服务API 服务网关(一)“原理”

公司内部一般会有很多微服务:购物车、库存、订单等,这些微服务是每个团队各自独立维护的,但我们不希望外部用户访问的时候知道这些细节。这时候就可以通过网关来屏蔽这些细节,让客户看到的企业内部这些服务的时候像是一个服务。

屏蔽内部细节,暴露统一接口

为什么在接入网关前有一层负载均衡?是想让网关是无状态的(无状态网关好处:可以部署很多,不会有单点,即使挂了一台其他网关还在,这对整个系统的稳定性和可用性非常重要)。

网关基本功能:

  1. 反向路由,将外部的请求转换成内部具体服务的调用。与Nginx的反向代理功能相同
  2. API 组合(这部分也可由聚合服务负责)
  3. 协议转换,RESTful API 或 gRPC
  4. 认证安全,恶意访问(爬虫,黑客等)
  5. 限流熔断,突发流量(双十一、促销等)以免造成内部服务器瘫
  6. 日志监控,对所有流量做访问的审计,对日志做分析

对请求的身份验证、授权、限流熔断、日志监控等的处理函数称为边缘函数

微服务API服务网关(二)“开源网关Zuul”

Zuul过滤器:

  1. Pre routing filters(前置路由过滤器):如日志处理
  2. Routing filters(路由过滤器):目的找到目标服务并进行调
  3. Post routing filters(后置路由过滤器):响应回来经过后置路由过滤器会到客户端,在后置路由过滤器中可以做事后处理:日志、统计和审计等

(过滤器上传加载机制)

(Request Context 实现在各个阶段过滤器中分享相关信息。)

跟 Netflix 学习微服务路由发现体系

Netflix 两个核心组件:

  1. 服务注册中心 – Eureka
  2. 网关 – Zuul

内部微服务两层逻辑划分:

  1. 基础服务 – Netflix称:中间层服务
  2. 聚合服务 – Netflix 称:Edge service(边界服务)

内部服务通过内部服务注册中心 Eureka 注册、发现。

  1. 基础服务注册服务到服务中心
  2. 聚合服务调用基础服务时,通过注册中心做服务发现,拉取路由表
  3. 网关同步服务注册中心的路由表,当服务请求进来时网关根据路由表找到后台对应的聚合服务进行调用

服务注册中心还可以做服务治理,例如对服务调用的安全管控。

集中式配置中心的作用和原理

传统的做法在配置文件中做配置,并且每个团队有各自的做法,这种做法的隐患:

  1. 配置不标准,格式不统一
  2. 上线后如遇重大事故,去响应并调整配置、去修改配置并重新发布,时间周期会比较长
  3. 配置文件的修改无法审计、追溯

哪些需要集中配置:

  • 链接字符串 - 数据库链接字符串、缓存链接字符串、消息队列连接字符串动态调整参数 - 超时时间、限流阈值
  • 业务开关 – 地域性功能、促销时开放的功能

配置中心可以简单的认为是一个服务器,开发、运营人员可以通过界面对配置中心进行配置,我们的服务连到配置中心后可以实时更新配置服务器中修改的配置。

更新的方式主要有两种:

  1. 服务主动拉取配置 – Pull(弊端:有延迟)
  2. 服务时刻连在Config Serve上,Config Server 有变更时会Push到每个服务上(弊端:网络等原因没能Push到某个服务上)

携程开源的配置中心 – Apollo

Apollo 配置中心(左侧)是一个服务器,研发或运营人员可以在服务端进行配置的修改,Apollo配置中心带有客户端(支持Java、.Net),客户端有一个缓存机制 – 配置更新后会拉取到客户端的内存缓存中,为了防止内存缓存的丢失客户端还会定期将内存缓存同步到本地文件缓存中,这样的设计可以使得如果配置中心挂掉或应用程序重启后还能通过读取本地文件缓存。

服务的更新结合了配置推送 + 定时拉取,以保证高可用

微服务通讯方式 RPC vs. REST

  1. 耦合性:RPC - 服务端和客户端必须以特定的消息格式进行通讯
  2. 消息协议:RPC – 二进制:thrift、protobuf等,性能比较高;REST – 文本XML、JSON。payload会比二进制大
  3. 通讯协议:RPC – TCP协议;REST – HTPP/HTTP2
  4. 性能:RPC – 高,REST – 基于文本消息协议和HTTP,差于RPC
  5. 接口契约IDL:RPC – thrift、protobuf IDL;REST – Swagger
  6. 客户端:RPC – 强类型客户端,一般自动生成、多语言支持;REST – 一般HTTP客户端可访问,可自动生成强类型客户端、多语言
  7. 案例:RPC - Dubbo(阿里巴巴)、Motan(新浪微博)、Tars(腾讯)等;REST – SpringMVC/Boot、Jax-rs等
  8. 开发者友好:RPC - 客户端比较方便,但二进制消息不可读;REST – 文本协议消息可读
  9. 对外开放:RPC – 对外一般需要转换REST;REST – 直接对外开放

微服务架构需要考虑哪些治理环节

  1. 服务注册发现
  2. 负载均衡、路由(灰度发布、蓝绿部署 – 软路由能力)
  3. 日志监控 – 问题排查
  4. Metrics – 对服务的调用量、延迟等监控
  5. 调用链埋点 – 微服务有错综复杂的依赖关系,如果没有好的调用链监控开发人员很容易迷失在这些服务中,出问题很难定位
  6. 限流熔断
  7. 安全 & 访问控制:黑名单、限制
  8. REST/RPC
  9. 序列化XML/JSON/二进制
  10. 代码生成 – 大规模开发比较推崇一种契约驱动的开发方法,开发人员先定义契约然后用代码生成的方式自动生成客户端和服务器端,这个在大规模开发中生成的代码比较规整
  11. 统一异常处理 – 异常标准化
  12. 文档 – 方便开发人员接入
  13. 配置集成
  14. 后台服务集成 – DB、MQ、Cache

微服务治理就将这些环节沉淀下来变成框架或平台的一部分;开发人员专注于业务逻辑的实现,在实现业务逻辑的过程中不需要考虑这个外围的治理能力。

这些治理环节沉在框架里,由框架团队或平台团队来集中管控。

完善的监控体系能实时了解微服务的健康情况对整个系统的可靠性和稳定性是非常重要的。

主要分为5 个层次发监控:

  1. 基础设施监控(由运维团队负责,网络和交换机)- 网络流量、丢包、错包和连接数等
  2. 系统层监控(物理机、虚拟机、OS) - CPU、内存、磁盘等
  3. 应用层监控 – URL访问性能(技术、延迟)、服务、数据库SQL、Cache可用性(性能、命中率)、响应时间、QPS等
  4. 应用层监控 – 登录注册、下单、支付等
  5. 端用户体验监控 – 性能、返回码、城市地区、运行商、操作系统等

5 个关键监控面:

  • 日志监控
  • Metrics监控
  • 健康检查
  • 调用链监控
  • 告警系统

主流监控架构:

在主机或服务进程内安装Agent,Agent负责收集机器和应用中的日志和Metrics发送到我们的监控系统。

当服务比较大、收集的日志和Metrics量比较大时会加入队列(Kafka)。标准的日志监控栈 – ELK(Elasticsearch、Logstash、Kibana);Metrics会采用时间序列数据库(InfluxDB、Grafana呈现展示)

通过健康检查机制来定期对应用的健康进行自动化的检查,开源的工具有Nagios。

微服务的调用链监控该如何选择

原理: 当请求进入Web容器时会生成一个Span(图中Root Span),当继续调用Service 时又会生成一个Span(Child Span),请求进来进入Service会生成一个Span,Service调用DB或其他Service时会产生Span;Web应用在调用Cache时会产生Span。

Span是调用链形成的关键,在Span会有一些信息:Trace Id、Span Id等。Root Span比较特殊会生成Span Id和Trace Id,其他的Span会生成自己的Span Id同时为了维护调用链之间的父子关系Child Span会跟踪记录Parent Id。

在跨进程中为了使调用链持续链接,会将Trace Id和Parent Id一起带过来。

主流开源的调用链工具对比:

微服务的容错限流是如何工作的

Netflix Hystrix

熔断: 这一概念来源于电子工程中的断路器(Circuit Breaker)。在互联网系统中,当下游服务因访问压力过大而响应变慢或失败,上游服务为了保护系统整体的可用性,可以暂时切断对下游服务的调用。这种牺牲局部,保全整体的措施就叫做熔断。

如果不采取熔断措施,我们的系统会怎样呢?例子 当前系统中有A,B,C三个服务,服务A是上游,服务B是中游,服务C是下游。它们的调用链如下:

一旦下游服务 C 因某些原因变得不可用,积压了大量请求,服务B的请求线程也随之阻塞。线程资源逐渐耗尽,使得服务B也变得不可用。紧接着,服务 A 也变为不可用,整个调用链路被拖垮。

像这种调用链路的连锁故障,叫做雪崩

隔离: 是通过资源隔离减少风险的方式,源自货船为了进行防止漏水和火灾的扩散,会将货仓分隔为多个, 如下图所示。

软件系统的隔离推荐的方法是进行服务拆分,让每个小业务独立运行,即便是其中一个业务宕掉,其他服务依然可以正常运行。

限流: 提前对各个类型的请求设置最高的QPS阈值,若高于设置的阈值则对该请求直接返回,不再调用后续资源。

降级: 当服务器压力剧增的情况下,根据实际业务情况及流量,对一些服务和页面有策略的不处理或换种简单的方式处理,从而释放服务器资源以保证核心交易正常运作或高效运作。

原理: 使用Hystrix 组件后,会将调用封装在Hystrix Command内,封装以后它就具有了熔断、限流、隔离和降级功能。请求方式可以是同步、异步或反应式的,请求过来后会做电路判断:如果电路打开即断路,会走降级流程调用降级函数。

如果电路闭合即没有熔断,然后进行线程/队列资源判断(如果资源不足,就会进入降级流程),如果前两关通过就运行调用。在调用时如果运行超时也会走降级流程。执行成功(Success)获取正确的相应结果返回调用端,失败走降级流程。

在整个调用过程中,任何一个环节的相关信息(电路是否打开、线程是否占用、运行是否超时)都会以Metrics形式反馈给计算电路健康组件(Calculate Circuit Health)进而反馈给电路判断(指导下一次关闭/打开电路的判断依据)

Docker 容器部署技术 & 持续交付流水线

容器技术的优点:

  1. 环境一致性
  2. 镜像部署

流程: 开发人员提交代码到Git,通过Jenkins 完成构建、单元测试和打镜像并上传到镜像中心(Docker registry)。发布到测试环境经QA测试后升级到UAT环境,经过UAT测试后升级到生产环境(生产环境可能会通过灰度发布、蓝绿部署发布到生产环境)

蓝绿部署 + 灰度发布(通过软路由切换流量)保证服务的稳定性:

容器集群调度和基于容器的发布体系



「极客阅读 」汇聚了国内外最优质的技术博客、产品动态、公众号文章。开发者可以在极客阅读一站式的阅读到来自互联网技术大咖的文章。

「极客阅读 」官网:geeker-read.com