微服务平台可靠性设计Word文档下载推荐.docx
- 文档编号:14757265
- 上传时间:2022-10-24
- 格式:DOCX
- 页数:23
- 大小:809.42KB
微服务平台可靠性设计Word文档下载推荐.docx
《微服务平台可靠性设计Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《微服务平台可靠性设计Word文档下载推荐.docx(23页珍藏版)》请在冰豆网上搜索。
分布式调用之后,相比于传统单体架构的本地方法调用,主要引入了如下潜在故障点:
✓序列化与反序列化:
微服务的请求和应答都需要经过序列化和反序列化,做消息的跨网络通信,由于数据结构不一致、不支持的数据类型、对方编解码错误等都会导致序列化和反序列化失败,进而导致微服务调用失败。
✓网络问题:
常见的包括网络超时、网络闪断、网络单通、网络拥塞等,都可能会导致微服务远程调用的失败。
1.1.2.大型系统微服务进程内合设
理想情况下,每个微服务都独立打包和部署,微服务之间天然就支持进程级隔离,但事实上,对于一个大规模的企业IT系统、或者大型网站,是由成百上千个微服务组成的,在实践中,微服务通常是不可能做到百分之百独立部署的,原因如下:
1.方便开发:
通常会按照业务域划分团队,同一个业务域往往包含多个微服务,由一个团队负责开发。
为了方便CI/CD,同一业务域的微服务往往打包和部署在一起,而不是每个微服务独立打包部署。
2.方便运维:
海量的微服务进程(以1000个微服务*10个进程实例为例),会增加部署、数据采集(性能KPI和日志等)、告警、问题定位等成本,如果运维自动化程度不高,很难支撑大规模的微服务独立部署。
3.提升性能:
一些业务对时延非常敏感,如果该业务链上的所有微服务调用都跨网络通信,时延往往无法满足业务要求。
通过将微服务合设在同一个进程之内,利用路由短路,把RPC调用转化成本地方法调用,可以极大的提升性能。
4.简化分布式事务处理:
分布式部署之后,会带来分布式事务问题。
有时候业务为了简化分布式事务的处理,将事务相关的微服务部署在同一个进程中,把分布式事务转换成本地事务,简化事务处理。
不同的微服务合设在同一个进程之中,就会引入一系列潜在的故障点,例如:
✓处理较慢的微服务会阻塞其它微服务
✓某个微服务故障蔓延,可能导致整个进程不可用
✓低优先级的微服务,抢占高优先级微服务的资源
1.1.3.微服务健康度
传统情况下,往往使用服务注册中心检测微服务的状态,当检测到服务提供者不可用时,会将故障的服务信息广播到集群所有节点,消费者接收到服务故障通知消息之后,根据故障信息中的服务名称、IP地址等信息,对故障节点进行隔离。
它的工作原理如下所示:
图1-3微服务状态检测
使用基于心跳或者会话的微服务状态检测,可以发现微服务所在进程宕机、网络故障等问题,但在实际业务中,微服务并非“非死即活”,它可能处于“亚健康状态”,服务调用失败率很高,但又不是全部失败。
或者微服务已经处于过负荷流控状态,业务质量受损,但是又没有全部中断。
使用简单的微服务状态检测,很难应对上述这些场景。
通过对微服务的运行质量建模,利用微服务健康度模型,根据采集的各种指标对微服务健康度实时打分,依据打分结果采取相应的可靠性对策,可以更有针对性的保障系统的可靠性。
1.1.4.同步的I/O操作
在整个微服务调用过程中,主要会涉及到三类I/O操作:
✓网络I/O操作,涉及到网络读写
✓磁盘I/O操作,主要是记录日志、话单、写本地文件等
✓数据库访问,例如Java使用JDBC驱动进行数据库操作
图1-4微服务涉及的主要I/O操作
凡是涉及到I/O操作的,如果I/O操作是同步阻塞模式,例如Java的BIO、文件File的读写操作、数据库访问的JDBC接口等,都是同步阻塞的。
只要访问的网络、磁盘或者数据库实例比较慢,都会导致调用方线程的阻塞。
由于线程是Java虚拟机比较重要的资源,当大量微服务调用线程被阻塞之后,系统的吞吐量将严重下降。
1.1.5.第三方SDKAPI调用
在微服务中,调用第三方SDKAPI,也可能会引入新的故障点,例如通过FTP客户端访问远端的FTP服务,或者使用MQ客户端访问MQ服务,如果这些客户端API的容错性设计不好,也会导致调用方的级联故障,这些故障是潜在和隐性的,在设计的时候往往容易被忽视,但它带来的风险和危害是巨大的。
1.2.微服务可靠性
软件可靠性是指在给定时间内,特定环境下软件无错运行的概率。
软件可靠性包含了以下三个要素:
1)规定的时间:
软件可靠性只是体现在其运行阶段,所以将运行时间作为规定的时间的度量。
运行时间包括软件系统运行后工作与挂起(启动但空闲)的累计时间。
由于软件运行的环境与程序路径选取的随机性,软件的失效为随机事件,所以运行时间属于随机变量。
2)规定的环境条件:
环境条件指软件的运行环境。
它涉及软件系统运行时所需的各种支持要素,如支持硬件、操作系统、其它支持软件、输入数据格式和范围以及操作规程等。
3)规定的功能:
软件可靠性还与规定的任务和功能有关。
由于要完成的任务不同,则调用的子模块就不同(即程序路径选择不同),其可靠性也就可能不同。
所以要准确度量软件系统的可靠性必须首先明确它的任务和功能。
1.2.1.关键的可靠性因素
微服务的运行质量,除了自身的可靠性因素之外,还受到其它因素的影响,包括网络、数据库访问、其它相关联的微服务运行质量等。
微服务的可靠性设计,需要考虑上述综合因素,总结如下:
图1-5微服务可靠性设计模型
2.异步I/O操作
2.1.网络I/O
2.1.1.使用同步阻塞I/O的问题
以Java为例,在JDK1.4推出JAVANIO1.0之前,基于JAVA的所有Socket通信都采用了同步阻塞模式(BIO),这种一请求一应答的通信模型简化了上层的应用开发,但是在可靠性和性能方面存在巨大的弊端:
2-1传统Java同步阻塞I/O模型
采用BIO通信模型的服务端,通常由一个独立的Acceptor线程负责监听客户端的连接,接收到客户端连接之后为客户端连接创建一个新的线程处理请求消息,处理完成之后,返回应答消息给客户端,线程销毁,这就是典型的一请求一应答模型。
该架构最大的问题就是不具备弹性伸缩能力,当并发访问量增加后,服务端的线程个数和并发访问数成线性正比,由于线程是JAVA虚拟机非常宝贵的系统资源,当线程数膨胀之后,系统的性能急剧下降,随着并发量的继续增加,可能会发生句柄溢出、线程堆栈溢出等问题,并导致服务器最终宕机。
2.1.2.使用非阻塞I/O通信
微服务进行远程通信时,通过使用非阻塞I/O,可以解决由于网络时延大、高并发接入等导致的服务端线程数膨胀或者线程被阻塞等问题。
以Java为例,从JDK1.4开始,JDK提供了一套专门的类库支持非阻塞I/O,可以在java.nio包及其子包中找到相关的类和接口。
JDK1.7之后,又提供了NIO2.0类库,支持异步I/O操作。
利用JDK的异步非阻塞I/O,可以实现一个I/O线程同时处理多个客户端链路,读写操作不会因为网络原因被阻塞,I/O线程可以高效的并发处理多个客户端链路,实现I/O多路复用,它的工作原理如下所示:
2-2Java非阻塞I/O模型
使用非阻塞I/O进行通信,以Java语言为例,建议策略如下:
1)TCP私有协议:
建议直接基于Netty开发。
2)HTTP/Restful/SOAP等:
选择支持非阻塞I/O的Web框架。
也可以选择基于Netty构建的开源应用层协议栈框架,例如支持异步Restful的RestExpress。
2.2.磁盘I/O
微服务对磁盘I/O的操作分为两类:
✓直接文件操作:
例如调用File的open、write、read等接口,进行文件操作。
✓间接文件操作:
例如调用日志类库写日志,虽然微服务并没有直接操作日志文件,但是日志类库底层还是会进行文件的读写等操作。
在实际项目中,最容易被忽视的就是日志操作。
不同的日志类库,写日志的机制不同,以Log4j1.2.X版本为例,当日志队列满之后,有多种策略:
✓同步等待,直到新的日志消息能够入队列,它会阻塞当前业务线程。
✓丢弃当前的日志消息,不会阻塞当前业务线程。
✓不入队列,由当前调用写日志的业务线程执行日志I/O操作,如果此时磁盘I/O写入速度慢,则会阻塞当前业务线程。
在实际生产环境中,我们就遇到过类似问题,在某些时段,磁盘WIO达到10+持续几秒钟-10几秒钟,然后又恢复正常。
WIO较高的时段,需要写接口日志、话单等,由于系统默认采用的是同步等待策略,结果导致通信I/O线程、微服务调度线程等都被阻塞,最终链路因为心跳超时被强制关闭、微服务被大量阻塞在消息队列中导致内存居高不小、响应超时等。
由于偶现的WIO高导致同步写日志被阻塞,继而引起通信线程、微服务调用线程级联故障,定位起来非常困难,平时CodeReview也很难被注意到。
所以,隐性的磁盘I/O操作,更需要格外关注。
要解决上面的问题,有三种策略:
✓使用非阻塞I/O,对文件进行异步读写操作。
✓业务层面封装一个异步的I/O操作,最简单的策略就是由一个独立的线程或者线程池来执行磁盘I/O操作。
✓选择支持非阻塞方式调用的I/O类库,例如使用log4j的异步日志API。
以JDK1.7为例,它提供了异步的文件I/O操作类库,基于该类库,就不需要担心磁盘I/O操作被阻塞:
2-3JDK1.7异步非阻塞文件接口
自己在上层封装异步I/O操作,也比较简单,它的优点是可以实现磁盘I/O操作与微服务之间的线程隔离,但是底层仍然使用的是同步阻塞I/O,如果此时磁盘的I/O比较高,依然会阻塞写磁盘的I/O线程。
它的原理如下所示:
2-4应用层封装的异步文件操作
将文件I/O操作封装成一个Task或者Event,投递到文件I/O线程池的消息队列中,根据投递结果,构造I/O操作相关联的Future对象给微服务调用线程。
通过向Future对象注册Listener并实现callback接口,可以实现异步回调通知,这样微服务和文件I/O操作就实现了线程隔离。
文件I/O操作耗时,并不会阻塞微服务调度线程。
当使用第三方文件I/O操作类库时,需要注意下相关API,尽量使用支持异步非阻塞接口的API,如果没有,则需要考虑是否做上层的异步封装。
2.3.数据库操作
部分数据库访问支持非阻塞方式,例如Oracle的OCI,它支持non-blocking模式和blocking模式:
阻塞方式就是当调用OCI操作时,必须等到此OCI操作完成后服务器才返回客户端相应的信息,不管是成功还是失败。
非阻塞方式是当客户端提交OCI操作给服务器后,服务器立即返回OCI_STILL_EXECUTING信息,而并不等待服务端的操作完成。
对于non-blocking方式,应用程序若收到一个OCI函数的返回值为OCI_STILL_EXECUTING时必须再次对每一个OCI函数的返回值进行判断,判断其成功与否。
可通过设置服务器属性为OCI_ATTR_NONBLOCKING_MODE来实现。
对于Java语言而言,由于JDK本身提供了数据库连接驱动相关的接口定义,JDBC驱动本身就是同步API接口,因此,Java语言的开源ORM框架也都是同步阻塞的,例如MyBatis、Hibernate等。
尽
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 微服 平台 可靠性 设计
![提示](https://static.bdocx.com/images/bang_tan.gif)