分布式架构
分布式架构的冰与火
使用分布式系统的原因
- 增大系统容量,单台机器已经不能满足越来越大的业务量,需要垂直或者水平拆分系统
- 增加系统可用,通过分布式架构来冗余系统来消除单点故障
结合整体开发流程梳理。
架构,技术选型,开发,测试和运维,部署和运维,性能,扩展性,新人接手,系统管理这几个方面来比较。
分布式系统的难点在于系统设计、管理和运维。
微服务的出现使得开发速度变得更快,部署快,隔离性高,系统的扩展度也好,但是在集成测试和服务管理方面就比较麻烦了,所以需要一套PaaS的平台和Kubernetes提供的各式各样的部署和调用方式。
分布式系统需要注意的问题
问题一: 异构系统不标准的问题
- 软件和应用协议不标准
- 通讯协议不标准
- 数据格式不标准
- 开发和运维的过程和方法不标准
问题二:系统架构中的服务依赖性问题
- 非关键服务被关键服务依赖,会导致非关键的服务也变成关键服务
- 服务依赖链中,出现木板效应,整个SLA由最查的那个服务决定
- 业务隔离之后,也要做到数据库隔离
问题三:故障发生的概率更大
- 单体应用出现故障的影响面大,分布式系统中,故障的影响面会隔离,但是出故障的频率会增加
- 出现故障不可怕,故障恢复的时间过长才可怕
- 出现故障不可怕,故障影响面过大才可怕
- 定义关键指标,而不是添加各种监控指标
- 设计时要防止失败的发生,如何减轻故障,自动化恢复故障
问题四:多层架构和运维复杂度增加
- 基础层是我们的机器、网络、和存储设备。
- 平台层就是我们的中间件、Tomcat、MySQL、Redis、Kafka之类的软件
- 应用层就是我们的业务软件、比如各种功能的服务
- 接入层就是接入用户请求的网关、负载均衡、或者是CDN、DNS这样的东西
问题 - 任何一层的问题都会导致整体的问题
- 没有统一的视图和管理,导致运维被割裂开来,造成更大的复杂度。
- 分工不是问题,问题是分工后的协作是否统一和规范。
分布式架构的技术栈
构建分布式系统的目的就是增加系统容量,提高系统的可用性,转换成技术方面,也就是完成下面两件事。
- 大流量处理。通过集群技术把大规模并发请求的负载分散到不同的机器上
- 关键业务保护。提高后台服务的可用性,把故障隔离起来阻止多米诺骨牌效应。如果流量过大,需要对业务降级,以保护关键业务流转。
说白了就两件事:提高吞吐量,服务更多的并发和流量,二是为了系统的稳定性和可用性。
提高架构的性能
- 缓存系统。可以有效的提高系统的访问能力。从前端浏览器、网络、后端服务、数据库、文件系统、硬盘、CPU,全部都有缓存,这是提高快速访问的最有效手段。分布式下的缓存,需要一个缓存集群,需要一个Proxy来做缓存的分片和路由。
- 负载均衡系统。水平扩展的关键技术。可以用多台机器来共同分担一部分流量请求。
- 异步调用。异步系统主要通过消息队列来对请求做排队处理,这样可以把前端的请求的峰值给削平了,增加系统的吞吐量,实时性就差了,同时消息也会丢失,要对消息进行持久化,这会造成有状态的结点,从而增加了服务调度的难度。
- 数据分区和数据镜像。数据分区是把数据按照一定的方式分成多个区。不同的数据区来分担不同的流量。这需要一个数据路由的中间件,会导致跨库的Join和跨库的事务非常复杂。数据镜像是把一个数据库镜像复制多分一样的数据,这样就不需要需要路由中间件了,可以在任意节点读写,内部会自行同步数据。数据镜像中最大的问题就是数据一致性的问题了。
提高架构的稳定性
- 服务拆分。主要有两个目的:一个为了隔离故障,而是为了重用模块。但是服务拆分之后会引入服务依赖的问题。
- 服务冗余。为了去除单点故障,支持服务的弹性伸缩,以及故障迁移。
- 限流降级。当系统是在扛不住的时候,只能通过限流或者功能降级的方式来停掉一部分服务,或是拒绝一部分用户,以确保整个架构不会挂掉。这些技术属于保护措施。
- 高可用架构。通常从冗余架构的角度来保障可用性。比如多租户隔离、灾备多活,数据复制集群。
- 高可用运维。DevOps中的CI(持续集成)和CD(持续部署)。一个良好的运维应该是一条很流畅的软件发布管线,其中做了足够的自动化测试,可以做灰度发布,线上系统的自动化控制。
分布式系统的关键技术
- 服务治理。把服务间的依赖关系、服务调用链、关键服务,并对这个服务进行性能和可用性方面的调整。
- 架构软件管理。服务之间有依赖,而且有兼容性问题,所以整体服务所形成的架构需要有架构版本管理、整体架构的生命周期管理,以及对服务的编排、聚合、事务处理等服务调度功能功能。
- DevOps。分布式系统可以更为快速的更新服务,但是对于服务的测试和部署都会是挑战。所以,还需要DevOps的全流程,其中包括环境构建、持续集成、持续部署等。
- 自动化运维。 有了DevOps后,我们就可以对服务进行自动伸缩、故障迁移、状态管理等一系列自动化运维技术了。
- 资源调度管理。应用层的自动化运维需要基础层的调度支持,也就是云计算IaaS 层的计算、存储、网络等资源的调度、隔离和管理。
- 整体的架构监控。如果没有一个好的监控系统,那么自动化运维和资源调度管理只可能是一个泡影,因为监控系统是你的眼睛。没有眼睛,数据就无法高效运维。所以说,监控是非常重要的部分。这里的监控对三层系统进行监控(应用层、中间件层、基础层)
- 流量控制。最后是我们的流量控制,负载均衡、服务路由、熔断、降级、限流等和流量相关的调度,包括灰度发布之类的
分布式系统最大的坑就是系统庞大,投入的人力物力巨大
分布式系统的纲
- 全栈系统监控
- 服务、资源调度
- 流量调度
- 状态、数据调度
- 开发和运维的自动化
全栈监控
全栈监控是类似于眼睛的东西,没有它,我们不知道系统发生了什么,将无法管理或是运维整个分布式系统。
这个监控要完成的功能为:
- 全栈监控
- 关联分析
- 跨系统调用串联
- 实时报警和自动处置
- 系统性能分析
多层体系的监控
所谓全栈监控,其实就是三层监控。
- 基础层:监控主机和底层资源。比如CPU、内存、网络吞吐、硬盘I/O,硬盘使用等
- 中间层:中间件层的监控。比如:Nginx、Redis、ActiveMQ、Kafka、MySQl、Tomcat等。
- 应用层:监控应用层的使用。比如:HTTP访问的吞吐量、响应时间、返回码,调用链路分析,性能瓶颈,用户端的监控
-
监控的标准化。 - 日志数据的结构化
- 监控数据格式标准化
- 统一的监控平台
- 统一的日志分析
什么才是好的监控系统
很多监控系统做的不好,主要是因为这两大原因
- 监控数据是隔离开的
- 监控的数据项太多
一个好的监控系统要有几个特征
- 关注整体应用的SLA 主要为用户服务的API来监控整个系统
- 关联指标聚合。 把服务的具体实例和主机关联起来
- 快速故障定位。做一个无侵入式的用户请求跟踪的trace监控,监控到所有请求的调用链
一个好的监控系统主要是为下面两个场景设计的。
体检 - 容量管理。提供全局运行数据的展示让工程师团队知道是否需要增加机器或者其他资源
- 性能管理。通过查看大盘,找到系统瓶颈,针对性的优化系统和响应代码
急诊 - 定位问题。快读的找到问题的发生点
- 性能分析。当出现非预期的流量提升时,可以快速的找到系统的瓶颈、并帮助开发人员深入代码
如何做出一个好的监控系统
- 服务调用链跟踪。 Google Dapper系统,对应开源的是Zipkin
- 服务调用时长分布
- 服务的TOP N视图
- 数据库操作关联
- 服务资源跟踪
服务调度
服务治理上的一些关键技术。
- 服务关键程度
- 服务依赖关系
- 服务发现
- 整个架构的版本管理
- 服务应用生命周期全管理
服务关键程度和服务的依赖关系
- 服务的关键程度,主要通过对业务的理解梳理出服务的关键程度。
- 做到服务无依赖很困难,只能尽量的降低依赖的深度和广度,从而让管理更简单。
- 微服务是服务依赖的最优解,服务依赖是允许有依赖环的。
- 服务依赖环的解决方案是依赖倒置??
- 服务依赖关系可以通过Zipkin服务跟踪系统
服务状态和生命周期的管理
- 需要一个服务注册中心,服务中心需要知道几件事
- 整个架构有多少种服务?
- 这些服务的版本是什么样的?
- 每个服务的实例数有多少个?他们的状态是什么样子的?
- 每个服务的状态是什么样的?是在部署中,运行中,故障中,升级中,还是在回滚中,伸缩中,或者是下线中。。。
- 服务的几个状态
- Provision,代表在供应一个新的服务
- Ready,表示启动成功了;
- Run,表示通过了服务健康检查
- Update,表示在升级中
- Rollback,表示在回滚中。
- Scale,表示在伸缩中
- Destroy 表示在销毁中
- Failed 表示失败状态
整个架构的版本管理
- 服务的软件版本
- 服务的运行环境-环境变量、CPU、内存、可以运行的节点、文件系统等
- 服务运行的最大最小实例数
对服务的变更,要根据这个清单记录下来
资源/服务调度
服务和资源的调度有点像操作系统。操作系统一方面把用户进程在硬件资源上调度,另一方面提供进程间的通信方式,让不同进程一起协同工作
服务状态的维持和拟合
服务状态指的是服务的运行状态。
服务运行时的状态是很关键的。服务运行过程中,状态也是会有变化的
- 不可预期的变化 。服务运行因为故障或者其他原因导致一些服务挂掉,好的集群管理会把挂掉的摘除,重启几个新的实例。
- 预期的变化。发布新版本、伸缩、回滚,集群管理器把服务从一个状态变成另外一个状态的过程中,玩命的不断的拟合
在分布式管理系统中,从一个状态到另外一个状态,需要对集群进行一系列操作。比如在伸缩的时候Scale。 - 先扩展几个节点
- 再往上部署服务
- 然后启动服务
- 检查服务的健康状态
- 最后扩展出来的服务加入到服务发现中
服务的弹性收缩和故障转移
- 底层资源的伸缩
- 服务的自动化部署
- 服务的健康检查
- 服务发现的注册
- 服务流量的调度
某个实例出问题之后,我们需要自动恢复它。对于服务来说,有两种模式,一种是宠物模式、一种是奶牛模式。 - 所谓宠物模式,就是一定要旧货
- 而奶牛模式,就是重新生成一个实例
两种模式中涉及到了 - 服务的健康监控
- 宠物模式下服务的重启和服务的监控报警
- 奶牛模式下 服务的资源申请,服务的自动化部署,服务发现的注册,以及服务的流量调度。
服务的工作流和编排
一个好的操作系统可以通过一定的机制把一堆独立工作的进程给协同起来。分布式的服务调度中叫 编排
流量与数据调度
流量调度的主要功能
- 依据系统运行情况,自动的进行流量调度,在无需人工干预的情况下,提升系统的稳定性
- 在应对爆品等突发事件的时候,在弹性计算扩缩容的较长事件窗口内或底层资源消耗殆尽的情况下,保持系统的平稳运行
流量调度完成以下几方面的内容
- 服务流控。服务发现、服务路由、服务降级、服务熔断、服务保护等。
- 流量控制。负债均衡、流量分配、流量控制、异地灾备等
- 流量管理。协议转换、请求校验、数据缓存、数据计算。
所有这些都是一个API Gateway应该做的事
流量调度的关键技术
作为一个API Gateway来说,因为要调度流量,首先要抗住流量,比较轻的业务逻辑。
- 高性能
- 抗流量 就是集群技术
- 业务逻辑
- 服务化
状态数据调度
服务调度最难办的就是有状态的服务了
分布式事务一致性的问题
- 要想数据有高可用性,就得写多份数据
- 写多份的问题会导致数据一致性的问题
- 数据一致性的问题又会引发性能问题
解决副本间一致性问题时,有一些技术方案
- M-S 方案
- M-M方案
- 两阶段和三阶段提交方案
- Paxos方案
数据节点的分布式方案
真正解决数据节点调度方案的应该是底层的数据节点
状态数据调度小结
- 对于应用层上的分布式事务一致性,只有两阶段提交这样的方式
- 底层存储可以解决这个问题的方式是通过Paxos、Raft或是NWR这样的算法和模型来解决。
- 状态数据是由分布式存储系统来解决的,这样会更加完美。
数据调度是在IaaS层解决的问题,而不是在Pass层解决的问题。
Pass平台的本质
软件工程的能力主要体现在:
第一 ,提高服务的SLA
第二,能力和资源重用或复用
第三,过程的自动化
Pass平台的本质
- 服务化是PaaS的本质。
- 分布式是PaaS的根本性质
- 自动化是PaaS的灵魂