微服务架构组件分析,看这篇就够了

一、如何发布和引用服务

服务描述:服务调用首先解决的问题就是服务如何对外描述。 经常使用的服务描述方式包括 RESTful API、XML 配置以及 IDL 文件三种。node

RESTful API正则表达式

主要被用做 HTTP 或者 HTTPS 协议的接口定义,即便在非微服务架构体系下,也被普遍采用算法

优点:数据库

HTTP 协议自己是一个公开的协议,对于服务消费者来讲几乎没有学习成本,因此比较适合用做跨业务平台之间的服务协议。编程

劣势: -性能相对比较低后端

XML 配置缓存

通常是私有 RPC 框架会选择 XML 配置这种方式来描述接口,由于私有 RPC 协议的性能比 HTTP 协议高,因此在对性能要求比较高的场景下,采用 XML 配置比较合适。这种方式的服务发布和引用主要分三个步骤:服务器

服务提供者定义接口,并实现接口网络

服务提供者进程启动时,经过加载 server.xml 配置文件将接口暴露出去。数据结构

服务消费者进程启动时,经过加载 client.xml 配置文件引入要调用的接口。

优点:

私有 RPC 协议的性能比 HTTP 协议高,因此在对性能要求比较高的场景下,采用 XML 配置方式比较合适 劣势:

对业务代码侵入性比较高

XML 配置有变动的时候,服务消费者和服务提供者都要更新(建议:公司内部联系比较紧密的业务之间采用)

IDL 文件

IDL 就是接口描述语言(interface description language)的缩写,经过一种中立的方式来描接口,使得在不一样的平台上运行的对象和不一样语言编写的程序能够相互通讯交流。经常使用的 IDL:一个是 Facebook 开源的 Thrift 协议,另外一个是 Google 开源的 gRPC 协议。不管是 Thrift 协议仍是 gRPC 协议,他们的工做原来都是相似的。

优点:

用做跨语言平台的服务之间的调用

劣势:

在描述接口定义时,IDL 文件须要对接口返回值进行详细定义。若是接口返回值的字段比较多,而且常常变化时,采用 IDL 文件方式的接口定义就不太合适了。

一方面会形成 IDL 文件过大难以维护

另外一方面只要 IDL 文件中定义的接口返回值有变动,都须要同步全部的服务消费者都更新,管理成本过高了。

总结

具体采用哪一种服务描述方式是根据实际状况决定,一般状况下, 若是只是企业内部之间的服务调用,而且都是 Java 语言的话,选择 XML 配置方式是最简单的。若是企业内部存在多个服务,而且服务采用的是不一样语言平台,建议使用 IDL 文件方式进行描述服务。若是还存在对外开放服务调用的情形的话,使用 RESTful API 方式则更加通用。

clipboard.png

二、 如何注册和发现服务

注册中心原理

在微服务架构下, 主要有三种角色:服务提供者(RPC Server)、服务消费者(RPC Client)和服务注册中心(Registry),三者的交互关系如图

clipboard.png

RPC Server 提供服务,在启动时,根据服务发布文件 server.xml 中配置的信息,向 Registry 注册服务,把 Registry 返回的服务节点列表缓存在本地内存中,并于 RPC Server 创建链接。

RPC Client 调用服务,在启动时,根据服务引用文件 client.xml 中配置的信息,向 Registry 订阅服务,把 Registry 返回的服务节点列表缓存在本地内存中,并于 RPC Client 创建链接。

当 RPC Server 节点发生变动时,Registry 会同步变动,RPC Client 感知后会刷新本地内存中缓存的服务节点列表。

RPC Client 从本地缓存的服务节点列表中,基于负载均衡算法选择一台 RPC Server 发起调用。

注册中心实现方式

注册中心API

服务注册接口:服务提供者经过调用注册接口来完成服务注册

服务反注册接口:服务提供者经过调用服务反注册接口来完成服务注销

心跳汇报接口:服务提供者经过调用心跳汇报接口完成节点存货状态上报

服务订阅接口:服务消费者调用服务订阅接口完成服务订阅,获取可用的服务提供者节点列表

服务变动查询接口:服务消费者经过调用服务变动查询接口,获取最新的可用服务节点列表

服务查询接口:查询注册中心当前住了哪些服务信息

服务修改接口:修改注册中心某一服务的信息

集群部署

注册中心通常都是采用集群部署来保证高可用性,并经过分布式一致性协议来确保集群中不一样节点之间的数据保持一致。

Zookeeper 的工做原理:

每一个 Server 在内存中存储了一份数据,Client 的读请求能够请求任意一个 Server

Zookeeper 启动时,将从实例中选举一个 leader(Paxos 协议)

Leader 负责处理数据更新等操做(ZAB 协议)

一个更新操做方式,Zookeeper 保证了高可用性以及数据一致性

clipboard.png

目录存储

ZooKeeper做为注册中心存储服务信息通常采用层次化的目录结构:

每一个目录在 ZooKeeper 中叫做 znode,而且其有一个惟一的路径标识

znode 能够包含数据和子 znode。

znode 中的数据能够有多个版本,好比某一个 znode 下存有多个数据版本,那么查询这个路径下的数据需带上版本信息。

clipboard.png

服务健康状态检测

注册中心除了要支持最基本的服务注册和服务订阅功能之外,还必须具有对服务提供者节点的健康状态检测功能,这样才能保证注册中内心保存的服务节点都是可用的。

基于 ZooKeeper 客户端和服务端的长链接和会话超时控制机制,来实现服务健康状态检测的。

在 ZooKeeper 中,客户端和服务端创建链接后,会话也也随之创建,并生成一个全局惟一的 Session ID。服务端和客户端维持的是一个长链接,在 SESSION_TIMEOUT 周期内,服务端会检测与客户端的链路是否正常,具体方式是经过客户端定时向服务端发送心跳消息(ping 消息),服务器重置下次 SESSION_TIMEOUT 时间。若是超过 SESSION_TIMEOUT,ZooKeeper 就会认为这个 Session 就已经结束了,ZooKeeper 就会认为这个服务节点已经不可用,将会从注册中心中删除其信息。

服务状态变动通知

一旦注册中心探测到有服务器提供者节点新加入或者被剔除,就必须马上通知全部订阅该服务的服务消费者,刷新本地缓存的服务节点信息,确保服务调用不会请求不可用的服务提供者节点。

基于 Zookeeper 的 Watcher 机制,来实现服务状态变动通知给服务消费者的。服务消费者在调用 Zookeeper 的 getData 方式订阅服务时,还能够经过监听器 Watcher 的 process 方法获取服务的变动,而后调用 getData 方法来获取变动后的数据,刷新本地混存的服务节点信息。

白名单机制

注册中心能够提供一个白名单机制,只有添加到注册中心白名单内的 RPC Server,才可以调用注册中心的注册接口,这样的话能够避免测试环境中的节点意外跑到线上环境中去。

总结

注册中心能够说是实现服务话的关键,由于服务话以后,服务提供者和服务消费者不在同一个进程中运行,实现了解耦,这就须要一个纽带去链接服务提供者和服务消费者,而注册中心就正好承担了这一角色。此外,服务提供者能够任意伸缩即增长节点或者减小节点,经过服务健康状态检测,注册中心能够保持最新的服务节点信息,并将变化通知给订阅服务的服务消费者。

注册中心通常采用分布式集群部署,来保证高可用性,而且为了实现异地多活,有的注册中心还采用多 IDC 部署,这就对数据一致性产生了很高的要求,这些都是注册中心在实现时必需要解决的问题。

三、如何实现 RPC 远程服务调用

客户端和服务端如何创建网络链接

HTTP 通讯

HTTP 通讯是基于应用层HTTP 协议的,而 HTTP 协议又是基于传输层 TCP 协议的。一次 HTTP 通讯过程就是发起一次 HTTP 调用,而一次 HTTP 调用就会创建一个 TCP 链接,经历一次下图所示的 “三次握手”的过程来创建链接。

clipboard.png

完成请求后,再经历一次“四次挥手”的过程来断开链接。

clipboard.png

Socket 通讯

Socket 通讯是基于 TCP/IP 协议的封装,创建一次Socket 链接至少须要一对套接字,其中一个运行于客户端,称为 ClientSocket ;另外一个运行于服务器端,称为 ServerSocket 。

服务器监听:ServerSocket 经过点用 bind() 函数绑定某个具体端口,而后调用 listen() 函数实时监控网络状态,等待客户端的链接请求。

客户端请求:ClientSocket 调用 connect() 函数向 ServerSocket 绑定的地址和端口发起链接请求。

服务端链接确认:当 ServerSocket 监听都或者接收到 ClientSocket 的链接请求时,调用 accept() 函数响应 ClientSocket 的请求,同客户端创建链接。

数据传输:当 ClientSocket 和 ServerSocket 创建链接后,ClientSocket 调用 send() 函数,ServerSocket 调用 receive() 函数,ServerSocket 处理完请求后,调用 send() 函数,ClientSocket 调用 receive() 函数,就能够获得返回结果。

clipboard.png

当客户端和服务端创建网络链接后,就能够起发起请求了。但网络不必定老是可靠的,常常会遇到网络闪断、链接超时、服务端宕机等各类异常,一般的处理手段有两种:

链路存活检测:客户端须要定时地发送心跳检测当心(通常经过 ping 请求) 给服务端,若是服务端连续 n 次心跳检测或者超过规定的时间没有回复消息,则认为此时链路已经失效,这个时候客户端就须要从新与服务端创建链接。

断连重试:一般有多种状况会致使链接断开,好比客户端主动关闭、服务端宕机或者网络故障等。这个时候客户端就须要与服务端从新创建链接,但通常不能马上完成重连,而是要等待固定的间隔后再发起重连,避免服务端的链接回收不及时,而客户端瞬间重连的请求太多而把服务端的链接数占满。

服务端如何处理请求

同步阻塞方式(BIO)

客户端每发一次请求,服务端就生成一个线程去处理。当客户端同时发起的请求不少事,服务端须要建立不少的线程去处理每个请求,若是达到了系统最大的线程数瓶颈,新来的请求就无法处理了。

BIO 适用于链接数比较小的业务场景,这样的话不至于系统中没有可用线程去处理请求。这种方式写的程序也比较简单直观,易于理解。

同步非阻塞(NIO)

客户端每发一次请求,服务端并非每次都建立一个新线程来处理,而是经过 I/O 多路复用技术进行处理。就是把多个 I/O 的阻塞复用到听一个 select 的阻塞上,从而使系统在单线程的状况下能够同时处理多个客户端请求。这种方式的优点是开销小,不用为每一个请求建立一个线程,能够节省系统开销。

NIO 适用于链接数比较多而且请求消耗比较轻的业务场景,好比聊天服务器。这种方式相比 BIO,相对来讲编程比较复杂。

异步非阻塞(AIO)

客户端只须要发起一个 I/O 操做而后当即返回,等 I/O 操做真正完成之后,客户端会获得 I/O 操做完成的通知,此时客户端只须要对数据进行处理就行了,不须要进行实际的 I/O 读写操做,由于真正的 I/O 读取或者写入操做已经由内核完成了。这种方式的优点是客户端无需等待,不存在阻塞等待问题。

AIO 适用于链接数比较多并且请求消耗比较重的业务场景,好比涉及 I/O 操做的相册服务器。这种方式相比另外两种,编程难难度最大,程序也不易于理解。

建议

最为稳妥的方式是使用成熟的开源方案,好比 Netty、MINA 等,它们都是通过业界大规模应用后,被充分论证是很可靠的方案。

数据传输采用什么协议

不管是开放的仍是私有的协议,都必须定义一个“契约”,以便服务消费和服务提供者之间可以达成共识。服务消费者按照契约,对传输的数据进行编码,而后经过网络传输过去;服务提供者从网络上接收到数据后,按照契约,对传输的数据进行解码,而后处理请求,再把处理后的结果进行编码,经过网络传输返回给服务消费者;服务消费者再对返回的结果进行解码,最终获得服务提供者处理后的返回值。

HTTP 协议

消息头

Server 表明是服务端服务器类型

Content-Length 表明返回数据的长度

Content-Type 表明返回数据的类型

消息体

具体的返回结果

clipboard.png

数据该如何序列化和反序列化

通常数据在网络中进行传输,都要先在发送方一段对数据进行编码,通过网络传输到达另外一段后,再对数据进行解码,这个过程就是序列化和反序列化

经常使用的序列化方式分为两类:文本类如 XML/JSON 等,二进制类如 PB/Thrift 等,而具体采用哪一种序列化方式,主要取决于三个方面的因素。

支持数据结构类型的丰富度。数据结构种类支持的越多越好,这样的话对于使用者来讲在编程时更加友好,有些序列化框架如 Hessian 2.0 还支持复杂的数据结构好比 Map、List等。

跨语言支持。

性能。主要看两点,一个是序列化后的压缩比,一个是序列化的速度。以经常使用的 PB 序列化和 JSON 序列化协议为例来对比分析,PB 序列化的压缩比和速度都要比 JSON 序列化高不少,因此对性能和存储空间要求比较高的系统选用 PB 序列化更合;而 JSON 序列化虽然性能要差一些,但可读性更好,因此对性能和存储空间要求比较高的系统选用 PB 序列化更合适对外部提供服务。

总结

通讯框架:它主要解决客户端和服务端如何创建链接、管理链接以及服务端如何处理请求的问题。

通讯协议:它主要解决客户端和服务端采用哪些数据传输协议的问题。

序列化和反序列化:它主要解决客户端和服务端采用哪一种数据编码的问题。

这三部分就组成了一个完成的RPC 调用框架,通讯框架提供了基础的通讯能力,通讯协议描述了通讯契约,而序列化和反序列化则用于数据的编/解码。一个通讯框架能够适配多种通讯协议,也能够采用多种序列化和反序列化的格式,好比服务话框架 不只支持 Dubbo 协议,还支持 RMI 协议、HTTP 协议等,并且还支持多种序列化和反序列化格式,好比 JSON、Hession 2.0 以及 Java 序列化等。

  1. 如何监控微服务调用

在谈论监控微服务监控调用前,首先要搞清楚三个问题:监控的对象是什么?具体监控哪些指标?从哪些维度进行监控?

监控对象

用户端监控:一般是指业务直接对用户提供的功能的监控。

接口监控:一般是指业务提供的功能因此来的具体 RPC 接口监控。

资源监控:一般是指某个接口依赖的资源的监控。(eg:Redis 来存储关注列表,对 Redis 的监控就属于资源监控。)

基础监控:一般是指对服务器自己的健康情况的监控。(eg: CPU、MEM、I/O、网卡带宽等)

监控指标

请求量

实时请求量(QPS Queries Per Second):即每秒查询次数来衡量,反映了服务调用的实时变化状况

统计请求量(PV Page View):即一段时间内用户的访问量来衡量,eg:一天的 PV 表明了服务一天的请求量,一般用来统计报表

响应时间:大多数状况下,能够用一段时间内全部调用的平均耗时来反应请求的响应时间。但它只表明了请求的平均快慢状况,有时候咱们更关心慢请求的数量。为此须要把响应时间划分为多个区间,好比0~10ms、10ms~50ms、50ms~100ms、100ms~500ms、500ms 以上这五个区间,其中 500ms 以上这个区间内的请求数就表明了慢请求量,正常状况下,这个区间内的请求数应该接近于 0;在出现问题时,这个区间内的请求数应该接近于 0;在出现问题时,这个区间内的请求数会大幅增长,可能平均耗时并不能反映出这一变化。除此以外,还能够从P90、P9五、P9九、P999 角度来监控请求的响应时间在 500ms 之内,它表明了请求的服务质量,即 SLA。

错误率:一般用一段时间内调用失败的次数占调用总次数的比率来衡量,好比对于接口的错误率通常用接口返回错误码为 503 的比率来表示。

监控维度

全局维度:从总体角度监控对象的请求量、平均耗时以及错误率,全局维度的监控通常是为了让你对监控对象的调用状况有个总体了解。

分机房维度:为了业务高可用,服务部署不止一个机房,由于不一样机房地域的不一样,同一个监控对象的各类指标可能会相差很大。

单机维度:同一个机房内部,可能因为采购年份和批次不的不一样,各类指标也不同。

时间维度:同一个监控对象,在天天的同一时刻各类指标一般也不会同样,这种差别要么是由业务变动致使,要么是运营活动致使。为了了解监控对象各类指标的变化,一般须要与一天前、一周前、一个月前,甚至三个月前比较。

核心维度:业务上通常会依据重要性成都对监控对象进行分级,最简单的是分红核心业务和非核心业务。核心业务和非核心业务在部署上必须隔离,分开监控,这样才能对核心业务作重点保障。

对于一个微服务来讲,必需要明确监控哪些对象、哪些指标,而且还要从不一样的维度进行监控,才能掌握微服务的调用状况。

监控系统原理

数据采集:收集到每一次调用的详细信息,包括调用的响应时间、调用是否成功、调用的发起者和接收者分别是谁,这个过程叫作数据采集。

数据传输:采集到数据以后,要把数据经过必定的方式传输给数据处理中心进行处理,这个过程叫作数据出传输。

数据处理:数据传输过来后,数据处理中心再按照服务的维度进行聚合,计算出不一样服务的请求量、响应时间以及错误率等信息并存储起来,这个过程叫作数据处理。

数据展现:经过接口或者 DashBoard 的形式对外展现服务的调用状况,这个过程叫作数据展现。

数据采集

服务主动上报

代理收集:这种处理方式经过服务调用后把调用的详细信息记录到本地日志文件中,而后再经过代理去解析本地日志文件,而后再上报服务的调用信息。

无论是哪一种方式,首先要考虑的问题就是采样率,也就是采集数据的频率。通常来讲,采样率越高,监控的实时性就越高,精确度也越高。但采样对系统自己的性能也会有必定的影响,尤为是采集后的数据须要写到本地磁盘的时候,太高的采样率会致使系统写入的 I/O 太高,进而会影响到正常的服务调用。因此合理的采样率是数据采集的关键,最好是能够动态控制采样率,在系统比较空闲的时候加大采样率,追求监控的实时性与精确度;在系统负载比较高的时候减小采样率,追求监控的可用性与系统的稳定性。

数据传输

UDP传输:这种处理方式是数据处理单元提供服务器的请求地址,数据采集后经过 UDP 协议与服务器创建链接,而后把数据发送过去。

Kafka传输:这种处理方式是数据采集后发送都指定的 Topic,而后数据处理单元再订阅对应的 Topic,就能够从 Kafka 消息队列中读取对应的数据。

不管哪一种传输方式,数据格式十分重要,尤为是对带宽敏感以及解析性能要求比较高的场景,通常数据传输时采用的数据格式有两种:

二进制协议,最经常使用的就是 PB 对象

文本协议,最经常使用的就是 JSON 字符串

数据处理

接口维度聚合:把实时收到的数据按照调用的节点维度聚合在一块儿,这样就能够获得每一个接口的实时请求、平均耗时等信息。

机器维度聚合:把实时收到的数据按照调用的节点维度聚合在一块儿,这样就能够从单机维度去查看每一个接口的实时请求量、平均耗时等信息。

聚合后的数据须要持久化到数据库中存储,所选用的数据库通常分为两种:

索引数据库:好比 Elasticsearcher,以倒排索引的数据结构存书,须要查询的时候,根据索引来查询。

时序数据库:好比 OpenTSDB,以时序序列数据的方式存储,查询的时候按照时序如 1min、5min 等维度查询

数据展现

曲线图:监控变化趋势。

clipboard.png

饼状图:监控占比分布。

clipboard.png

格子图:主要坐一些细粒度的监控。

clipboard.png

总结

服务监控子啊微服务改造过程当中的重要性不言而喻,没有强大的监控能力,改形成微服务架构后,就没法掌控各个不一样服务的状况,在遇到调用失败时,若是不能快速发现系统的问题,对于业务来讲就是一场灾难。

搭建一个服务监控系统,设计数据采集、数据传输、数据处理、数据展现等多个环节,每一个环节都须要根据本身的业务特色选择合适的解决方案

若是想免费学习Java工程化、高性能及分布式、深刻浅出。微服务、Spring,MyBatis,Netty源码分析的朋友能够加个人Java进阶群:478030634,群里有阿里大牛直播讲解技术,以及Java大型互联网技术的视频免费分享给你们。

五、如何追踪微服务调用

跟踪记录一次用户请求都发起了哪些调用,通过哪些服务处理,而且记录每一次调用所涉及的详细信息,这时候若是发生调用失败,就能够经过这个日志快速定位是在哪一个环节出了问题。

服务追踪的做用

优化系统瓶颈

经过记录调用通过的每一条链路上的耗时,能够快速定位整个系统的瓶颈点在哪里。可能出现的缘由以下:

运营商网络延迟

网关系统异常

某个服务异常

缓存或者数据库异常

经过服务追踪,能够从全局视角上去观察,找出整个系统的瓶颈点所在,而后作出针对性的优化

优化链路调用

经过服务追踪能够分析调用所通过的路径,而后评估是否合理

通常业务都会在多个数据中心都部署服务,以实现异地容灾,这个时候常常会出现一种情况就是服务 A 调用了另一个数据中心的服务 B,而没有调用同处于一个数据中心的服务 B。跨数据中心的调用视距离远近都会有必定的网络延迟,像北京和广州这种几千千米距离的网络延迟可能达到了30ms以上,这对于有些业务几乎是不可接受的。经过对调用链路进行分析,能够找出跨数据中的服务调用,从而进行优化,尽可能规避这总状况出现。

生成网络拓扑

经过服务追踪系统中记录的链路信息,能够生成一张系统的网络调用拓扑图,它能够反映系统都依赖了哪些服务,以及服务之间的调用关系是什么样的,能够一目了然。除此以外,在网络拓扑图上还能够把服务调用的详细信息也标出来,也能起到服务监控的做用。

透明传输数据

除了服务追踪,业务上常常有一种需求,指望能把一些用户数据,从调用的开始一直往下传递,以便系统中的各个服务都能获取到这个信息。好比业务想作一些 A/B 测试,这时候就想经过服务追踪系统,把 A/B 测试的开关逻辑一直往下传递,通过的每一层服务都能获取到这个开关值,就可以统一进行 A/B 测试。

服务追踪原理

服务追踪鼻祖:Google 发布的一篇的论文Dapper, [a Large-Scale Distributed Systems Tracing Infrastructure

核心理念:经过一个全局惟一的 ID 将分布在各个服务节点上的同一次请求串联起来,从而还原原有的调用关系,能够追踪系统问题、分析调用数据并统计各类系统指标

能够说后面的诞生各类服务追踪系统都是基于 Dapper 衍生出来的,比较有名的有 Twitter 的Zipkin、阿里的鹰眼、美团的MTrace等。

讲解下服务追踪系统中几个最基本概念

clipboard.png

traceId:用于标识某一次具体的请求ID。

spanId:用于标识一次 RPC 调用在分布式请求中的位置。

annotation:用于业务自定义埋点数据,能够是业务感兴趣的上上传到后端的数据,好比一次请求的用户 UID。

traceId 是用于串联某一次请求在系统中通过的全部路径,spanId 是用于区分系统不一样服务之间调用的前后关系,而annotation 是用于业务自定义一些本身感兴趣的数据,在上传 traceId 和 spanId 这些基本信息以外,添加一些本身感兴趣的信息。

服务追踪系统实现

clipboard.png

上面是服务追踪系统架构图,一个服务追踪系统能够分三层:

数据采集层:负责数据埋点并上报

数据处理层:负责数据的存储与计算

数据展现层:负责数据的图形化展现

数据采集层

做用:在系统的各个不一样的模块中尽心埋点,采集数据并上报给数据处理层进行处理。

clipboard.png

CS(Client Send)阶段 : 客户端发起请求,并生成调用的上下文。

SR(Server Recieve)阶段 : 服务端接收请求,并生成上下文。

SS(Server Send)阶段 : 服务端返回请求,这个阶段会将服务端上下文数据上报,下面这张图能够说明上报的数据有:traceId=123456,spanId=0.1,appKey=B,method=B.method,start=103,duration=38.

CR(Client Recieve)阶段 : 客户端接收返回结果,这个阶段会将客户端上下文数据上报,上报的数据有:traceid=123456,spanId=0.1,appKey=A,method=B.method,start=103,duration=38。

clipboard.png

数据处理层

做用:把数据上报的数据按需计算,而后落地存储供查询使用

实时数据处理:要求计算效率比较高,通常要对收集的链路数据可以在秒级别完成聚合计算,以供实时查询

针对实时数据处理,通常使用 Storm 或者 Spack Streaming 来对链路数据进行实时聚合加工,存储一拜是用 OLTP 数据仓库,好比 HBase,使用 traceId 做为 RowKey,能自然地把一条调用链聚合在一块儿,提升查询效率。

离线数据处理:要求计算效率相对没那么高,通常能在小时级别完成链路数据的聚合计算便可,通常用做汇总统计。

针对离线数据处理,通常经过运行 MapReduce 或者 Spark 批处理程序来对链路数据进行离线计算,存储通常使用 Hive

数据展现

做用:将处理后的链路信息以图形化的方式展现给用户和作故障定位

调用链路图(eg:Zipkin)

服务总体状况:服务总耗时、服务调用的网络深度、每一层通过的系统,以及多少次调用。下图展现的一次调用,总耗时 209.323ms,通过了 5 个不一样系统模块,调用深度为 7 层,共发生了 2

clipboard.png

调用拓扑图(Pinpoint)

调用拓扑图是一种全局视野,在实际项目中,主要用做全局监控,用户发现系统异常的点,从而快速作出决策。好比,某一个服务忽然出现异常,那么在调用链路拓扑图中能够看出对这个服务的调用耗时都变高了,能够用红色的图样标出来,用做监控报警。

clipboard.png

总结

服务追踪可以帮助查询一次用户请求在系统中的具体执行路径,以及每一条路径下的上下游的详细状况,对于追查问题十分有用。

实现一个服务追踪系统,设计数据采集、数据处理和数据展现三个流程,有多种实现方式,具体采起某一种要根据本身的业务状况来选择。

六、微服务治理的手段有哪些

一次服务调用,服务提供者、注册中心、网络这三者均可能会有问题,此时服务消费者应该如何处理才能确保调用成功呢?这就是服务治理要解决的问题。

节点管理

服务调用失败通常是由两类缘由引发的

服务提供者自身出现问题,好比服务器宕机、进程意外退出等

网络问题,如服务提供者、注册中心、服务消费者这三者任意二者之间的网络问题

不管是服务哪一种缘由,都有两种节点管理手段:

注册中心主动摘除机制

这种机制要求服务提供者定时的主动向注册中心汇报心跳,注册中心根据服务提供者节点最近一次汇报心跳的时间与上一次汇报心跳时间作比较,若是超出必定时间,就认为服务提供者出现问题,继而把节点从服务列表中摘除,并把最近的可用服务节点列表推送给服务消费者。

服务消费者摘除机制

虽然注册中心主动摘除机制能够解决服务提供者节点异常的问题,但若是是由于注册中心与服务提供者之间的网络出现异常,最坏的状况是注册中心会把服务节点所有摘除,致使服务消费者没有可能的服务节点调用,但其实这时候提供者自己是正常的。因此,将存活探测机制用在服务消费者这一端更合理,若是服务消费者调用服务提供者节点失败,就将这个节点从内存保存的可用夫提供者节点列表一处。

负载均衡算法

经常使用的负载均衡算法主要包括如下几种:

随机算法(均匀)

轮询算法(按照固定的权重,对可用服务节点进行轮询)

最少活跃调用算法(性能理论最优)

一致性 Hash 算法(相同参数的请求老是发到同一服务节点)

服务路由

对于服务消费者而言,在内存中的可用服务节点列表中选择哪一个节点不只由负载均衡算法决定,还由路由规则决定。

所谓的路由规则,就是经过必定的规则如条件表达式或者正则表达式来限定服务节点的选择范围。

为何要指定路由规则呢?主要有两个缘由:

业务存在灰度发布的需求

好比,服务提供者作了功能变动,但但愿先只让部分人群使用,而后根据这部分人群的使用反馈,再来决定是否全量发布。

多机房就近访问的需求

跨数据中心的调用视距离远近都会有必定的网络延迟,像北京和广州这种几千千米距离的网络延迟可能达到了30ms以上,这对于有些业务几乎是不可接受的,因此就要一次服务调用尽可能选择同一个 IDC 内部节点,从而减小网络耗时开销,提升性能。这时通常能够经过 IP 段规则来控制访问,在选择服务节点时,优先选择同一 IP 段的节点。

那么路由规则该如何配置?

静态配置:服务消费者本地存放调用的路由规则,若是改变,需从新上线才能生效

动态配置:路由规则存放在配置中心,服务消费者按期去请求注册中心来保持同步,要想改变消费者的路由配置,能够经过修改注册中心的配置,服务消费者在下一个同步周期以后,就会请求注册中心更新配置,从而实现动态变动

服务容错

经常使用的手段主要有如下几种:

FailOver:失败自动切换(调用失败或者超时,能够设置重试次数)

FailBack:失败通知(调用失败或者超时,不当即发起重试,而是根据失败的详细信息,来决定后续的执行策略)

FailCache:失败缓存(调用失败或者超时,不当即发起重试,而是隔一段时间后再次尝试发起调用)

FailFirst:快速失败(调用一次失败后,再也不充实,通常非核心业务的调用,会采起快速失败策略,调用失败后通常就记录下失败日志就返回了)

通常对于幂等的调用能够选择 FailOver 或者 FailCache,非幂等的调用能够选择 Failback 或者 FailFast

若是想免费学习Java工程化、高性能及分布式、深刻浅出。微服务、Spring,MyBatis,Netty源码分析的朋友能够加个人Java进阶群:478030634,群里有阿里大牛直播讲解技术,以及Java大型互联网技术的视频免费分享给你们。

总结

节点管理是从服务节点健康状态角度来考虑,负载均衡和服务路由是从服务节点访问优先级角度来考虑,而服务容错是从调用的健康状态来考虑,可谓异曲同工。

在实际的微服务架构中,上面的服务治理手段通常都会在服务框架中默认即成,好比 阿里的 Dubbo、微博开源的服务架构 Motan等。

相关文章
相关标签/搜索