微服务前面零散地进行了一些框架和概念层面的学习,现在是开始相对完整地开始课程学习,极客时间上买的课程,听和学的过程做一些摘要和笔记。
服务调用首先要解决的问题就是服务如何对外描述。比如服务名、调用这个服务需要提供哪些信息、返回的结果是什么格式的、如何解析等问题。常用的服务描述方式包括 RESTful API、XML 配置以及 IDL 文件三种。
服务描述方式 使用场景 缺点
RESTFUL API 跨语言平台,组织内外皆可 使用了HTP作为通信协议,相比TCP协议,性能较差
XML配置 Java平台,一般用作组织内部 不支持跨语言平台
IDL文件 跨语言平台,组织内外皆可 修改或者除PB字段不能向前兼容
有了服务的接口描述,下一步要解决的问题就是服务的发布和订阅,就是说你提供了一个服务,如何让外部想调用你的服务的人知道。这个时候就需要一个类似注册中心的角色,服务提供者将自己提供的服务以及地址登记到注册中心,服务消费者则从注册中心查询所需要调用的服务的地址,然后发起请求。
注册中心的工作流程:
1)监控的对象
监控的对象可以分为四个层次,从上到下可以归纳为:
2)监控指标:
3)监控维度:
4)监控系统原理:
我们对服务调用进行监控,首先要能收集到每一次调用的详细信息,包括调用的响应时间,调用是否成功,调用的发起者和接受者分别是谁,这个过程叫做数据收集。采集到数据后,要把数据通过一定的方式传输给数据处理中心进行处理,这个过程叫做数据传输。数据传输过来后,数据处理中心再按照服务的维度进行聚合,计算出不同服务的请求量,响应时间以及错误率等信息并存储起来,这个过程叫做数据处理。最后再通过接口或者Dashboard的形式对外展示服务的调用情况,这个过程叫做数据展示。
可见,监控系统主要包括四个环节:数据采集,数据传输,数据处理和数据展示。
a.数据采集
b.数据传输
最常用的方式:
数据的格式:
c.数据处理
数据处理是对采集的数据进行聚合并存储。数据聚合通常有两个维度:
聚合后的数据需要持久化到数据库中存储,所选用的数据库一般分为两种:
d.数据展示
曲线图,饼状图,格子图等
1)服务追踪的作用
第一,优化系统瓶颈。
第二,优化链路调用。
第三,生成网络拓扑。
第四,透明传输数据。
2)服务追踪系统原理
它的核心理念就是调用链:通过一个全局唯一的 ID 将分布在各个服务节点上的同一次请求串联起来,从而还原原有的调用关系,可以追踪系统问题、分析调用数据并统计各种系统指标。
traceId 是用于串联某一次请求在系统中经过的所有路径,spanId 是用于区分系统不同服务之间调用的先后关系,而 annotation 是用于业务自定义一些自己感兴趣的数据,在上传 traceId 和 spanId 这些基本信息之外,添加一些自己感兴趣的信息。
服务追踪系统架构图,可以分为三层。
单体应用改造为微服务架构后,服务调用由本地调用变成远程调用,服务消费者 A 需要通过注册中心去查询服务提供者 B 的地址,然后发起调用,一次服务调用,服务提供者、注册中心、网络这三者都可能会有问题,此时服务消费者应该如何处理才能确保调用成功呢?这就是服务治理要解决的问题。
1)节点管理
两种节点管理手段。1. 注册中心主动摘除机制 2. 服务消费者摘除机制(将存活探测机制用在服务消费者这一端更合理,如果服务消费者调用服务提供者节点失败,就将这个节点从内存中保存的可用服务提供者节点列表中移除。)
2)负载均衡
常用的负载均衡算法主要包括以下几种。1. 随机算法;2 轮询算法 3. 最少活跃调用算法 4. 一致性 Hash 算法
如果后端服务节点的配置没有差异,同等调用量下性能也没有差异的话,选择随机或者轮询算法比较合适;如果后端服务节点存在比较明显的配置和性能差异,选择最少活跃调用算法比较合适。
3)服务路由
需要制定路由规则主要有两个原因:1. 业务存在灰度发布的需求 2. 多机房就近访问的需求
一般有两种配置方式。1. 静态配置 服务消费者本地存放服务调用的路由规则,在服务调用期间,路由规则不会发生改变,
2. 动态配置 这种方式下,路由规则是存在注册中心的,服务消费者定期去请求注册中心来保持同步
4)服务容错
服务调用并不总是一定成功的,对于服务调用失败的情况,需要有手段自动恢复,来保证调用成功。
常用的手段主要有以下几种。
FailOver 失败自动切换。失败后自动选择服务列表中下一个继续。一般适合服务调用是读请求的场景
FailBack 失败通知。就是服务消费者调用失败或者超时后,不再重试,而是根据失败的详细信息,来决定后续的执行策略。比如对于非幂等的调用场景,如果调用失败后,不能简单地重试,而是应该查询服务端的状态,看调用到底是否实际生效,如果已经生效了就不能再重试了;如果没有生效可以再发起一次调用。
FailCache 失败缓存。就是服务消费者调用失败或者超时后,不立即发起重试,而是隔一段时间后再次尝试发起调用。比如后端服务可能一段时间内都有问题,如果立即发起重试,可能会加剧问题,反而不利于后端服务的恢复。如果隔一段时间待后端节点恢复后,再次发起调用效果会更好。
FailFast 快速失败。就是服务消费者调用一次失败后,不再重试。实际在业务执行时,一般非核心业务的调用,会采用快速失败策略,调用失败后一般就记录下失败日志就返回了。
服务容错不同策略的使用场景是不同的,一般情况下对于幂等的调用(我理解为读操作),可以选择 FailOver 或者 FailCache,非幂等的调用(我理解为写操作)可以选择 FailBack 或者 FailFast。
微服务的架构主要包括服务描述、服务发现、服务调用、服务监控、服务追踪以及服务治理这几个基本组件。
1)服务发布与引用:服务发布与引用的三种常用方式:RESTful API、XML 配置以及 IDL 文件,其中 Dubbo 框架主要是使用 XML 配置方式。
其中“dubbo:service”开头的配置项声明了服务提供者要发布的接口,“dubbo:protocol”开头的配置项声明了服务提供者要发布的接口的协议以及端口号。
其中“dubbo:reference”开头的配置项声明了服务消费者要引用的服务
2)服务注册与发现:
“dubbo://registry”开头的配置项声明了注册中心的地址
服务消费者发现服务的过程,其中“dubbo://registry”开头的配置项声明了注册中心的地址
3)服务调用
基于扩展点自适应机制,客户端和服务端之间的调用会通过 Netty 4 框架来建立连接,并且服务端采用 NIO 方式来处理客户端的请求。
Dubbo 的数据传输采用协议:Dubbo 不仅支持私有的 Dubbo 协议,还支持其他协议比如 Hessian、RMI、HTTP、Web Service、Thrift 等。
至于数据序列化和反序列方面,Dubbo 同样也支持多种序列化格式,比如 Dubbo、Hession 2.0、JSON、Java、Kryo 以及 FST 等,可以通过在 XML 配置中添加下面的配置项。
4)服务监控
服务监控主要包括四个流程:数据采集、数据传输、数据处理和数据展示,其中服务框架的作用是进行埋点数据采集,然后上报给监控系统。
在 Dubbo 框架中,无论是服务提供者还是服务消费者,在执行服务调用的时候,都会经过 Filter 调用链拦截,来完成一些特定功能,比如监控数据埋点就是通过在 Filter 调用链上装备了 MonitoFilter 来实现的。
5)服务治理
服务治理手段包括节点管理、负载均衡、服务路由、服务容错等,下面这张图给出了 Dubbo 框架服务治理的具体实现。
微服务架构各个组件是如何串联起来组成一个完整的微服务框架的,以 Dubbo 框架下一次服务调用的过程为例,先来看下客户端发起调用的过程。
首先根据接口定义,通过 Proxy 层封装好的透明化接口代理,发起调用。
然后在通过 Registry 层封装好的服务发现功能,获取所有可用的服务提供者节点列表。
再根据 Cluster 层的负载均衡算法从可用的服务节点列表中选取一个节点发起服务调用,如果调用失败,根据 Cluster 层提供的服务容错手段进行处理。
同时通过 Filter 层拦截调用,实现客户端的监控统计。
最后在 Protocol 层,封装成 Dubbo RPC 请求,发给服务端节点。
这样的话,客户端的请求就从一个本地调用转化成一个远程 RPC 调用,经过服务调用框架的处理,通过网络传输到达服务端。其中服务调用框架包括通信协框架 Transporter、通信协议 Codec、序列化 Serialization 三层处理。
服务端从网络中接收到请求后的处理过程是这样的:
首先在 Protocol 层,把网络上的请求解析成 Dubbo RPC 请求。
然后通过 Filter 拦截调用,实现服务端的监控统计。
最后通过 Proxy 层的处理,把 Dubbo RPC 请求转化为接口的具体实现,执行调用。