一 PaaS服务的本质
服务化是PaaS的本质。软件模块重用,运行环境和资源的重用,使用通用的软件模块或服务,通用的软件通讯协议,统一的开发和运维管理方法,最大程度的提高复用度
分布式是PaaS的根本特性。多租户隔离、高可用、服务编排是PaaS的根本特性。
自动化是PaaS的灵魂。自动化部署安装运维,自动化伸缩调度是PaaS的关键
二 PaaS平台整体架构图
1 最底层的Docker+Kubernetes,提供了
1). 使用Docker对应用程序包装(package)、实例化(instantiate)、运行(run)。
2). 以集群的方式运行、管理跨机器的容器。
3). 解决Docker跨机器容器之间的通讯问题。
4). Kubernetes的自我修复机制使得容器集群总是运行在用户期望的状态。
2 PaaS调度层(spring cloud),又称为iPass。包括服务的生命周期管理,服务监控,服务弹性伸缩,服务编排等。
3 PaaS服务能力层,又称之为aPass。包括中间件服务:缓存、队列、作业系统;数据服务:报表、AI;业务服务:二维码、用户、支付等等
4 PaaS的流量调度。包括流控、路由、降级、灰度、聚合、串联以及对高并发的管理。
5 PaaS的运营管理。认证和开放平台,软件资源库,软件接入等。
6 PaaS的运维管理。主要是DevOps等。
三 PaaS关键技术
1). 全栈监控
2). 服务调度
3). 流量与数据调度
3.1 全栈监控
一个好的监控为了两个场景而设计
体检
容量管理
提供一个全局的系统运行时数据展示,可以让其它工程师知道是否需要加机器或资源
性能管理
可以通过查看大盘,找到系统瓶颈,并能有针对性的优化
急诊
定位问题
快速的暴露并找到问题的发生点,帮助技术人员诊断问题
性能分析
当出现非预期流量提升时,快速找到系统节点
其架构可以用下图表示
多层体系监控架构图
包括三层
1)基础层:监控主机和底层资源。比如cpu、内存、网络吞吐、硬盘I/O、硬盘使用等
2)中间层: 包括nginx、Redis、MQ、MySQL、Tomcat等
3)应用层:HTTP访问的吞吐量、响应时间、返回码、调用链路分析、性能瓶颈,还包括用户端的监控等
此外,有了这些监控后,需要将数据能落实到日志系统,需要
1)日志数据格式化
2)监控数据格式标准化
3)统一的监控平台
4)统一的日志分析
一个好的监控系统技术要点
-
服务链路跟踪。从对外的API开始,到对应的服务器,最好到落地的数据库,包括所有的中间件,比如缓存、消息等。开源项目Zipkin实现了链路跟踪功能,此外Java类的服务还可以用字节码技术做到代码无侵入式。如下图所示
-
服务调用时长分布。同样的,用Zipkin就可以做到
服务TOP N视图,包含三种排名方法:a)按调用量排名 b) 按请求最耗时排名 c)按热点排名
- 数据库操作关联。我们可以很方便的通过JavaAgent字节码注入技术拿到JDBC执行数据库操作的执行时间
- 服务资源跟踪。我们服务可能运行在物理机上,也可能在虚拟机里,还可能是Docker容器中,而我们需要把这些资源关联起来(CPU,MEM,I/O,DISK,NETWORK)
而一旦有了上述数据我们就可以达到如下目标。
- 一台服务器挂掉是因为CPU或I/O过高的时候,我们马上可以知道其会影响到哪些对外服务的API
- 当一个服务过慢的时候,我们马上能看出其是否在做Java GC,或是其所在的节点是否有资源不足的情况
- 当发现一个SQL过慢的时候,我们立马知道其影响的是哪个API
- 当发现一个消息队列拥堵时,我们立马能知道会影响哪些对外服务的API
我们可以用一个图来表示
3.2 服务调度(服务治理)
这里的服务调度就是指除开流量调度外的服务治理。主要有以下几点。
- 服务关键程度
- 服务依赖关系
- 服务发现
- 架构版本管理
- 服务应用声明周期全管理
服务关键程度和服务依赖关系程度
服务关键程度要通过对业务的梳理来发现。服务依赖关系用Spring Cloud的一套方法就能够非常好的解决,但是千万不要出现循环依赖,解决方式是通过第三方的消息队列来解耦,此外还有Zipkin这个服务跟踪工具来展示这张地图。
服务状态和服务生命周期管理
我们需要一个统一的服务注册中心,来做到
- 整个架构中有多少种服务?
- 这些服务的版本是怎么样的?
- 每个服务的实例数有多少个?它们的状态是怎么样的?
- 每个服务的状态是怎么样的?是在部署中、运行中、升级中、还是在回滚,伸缩中,或是在下线中
有了这些状态,就能对生命周期进行管理了,主要有以下几个状态 - Provision,代表在供应一个新的服务
- Ready, 表示启动成功了
- Run, 表示通过了服务健康检查
- Update,表示正在升级中
- Rollback,表示正在回滚中
- Scale,表示正在伸缩中
- Destroy, 表示正在销毁中
- Failed,表示失败的状态
有了生命周期的管理,一个纷乱无比的世界就可以干干净净的管理起来了
架构版本管理
除了各个项目的版本管理外,还需要在上面再覆盖一层版本管理。比如A服务的1.2版本只能和B服务的2.2版本一起工作,如果架构中存在不兼容的情况,可以把整个架构回滚掉。所以,就需要一个架构清单,包括但不限于
- 服务的软件版本
- 服务的运行环境--环境变量、CPU、内存、可运行的结点、文件系统等
- 服务运行的最大和最小实例数
而每一次对这个清单的变更都需要记录下来,算是一个架构版本管理。而我们这个集群控制系统需要解读并执行这个清单中的变更,以操作和管理整个集群中的相关变更。
资源/服务调度
服务和资源调度有点类似操作系统。操作系统一方面把用户进程在硬件资源上进行调度,另一方面提供进程间通信方式,可以让不同进程在一起协同工作。
而服务调度有以下一些关键技术。
- 服务状态的维持和拟合
- 服务的弹性伸缩和故障迁移。
- 作业的应用调度。
- 作业的工作流编排。
- 服务编排。
服务状态的维持和拟合
服务状态包括上述服务生命周期中的状态- Provision, Ready,Run, Scale, Rollback, Update, Destory, Failed...而服务状态的变化包括预期和不预期的变化
- 一种是不预期的变化。比如,如果有服务挂掉了,或是什么原因服务不健康的状态。如果是一个好的集群管理,应该能摘除不健康的服务,同时又启动新的服务,强行维护健康服务的实例数。
- 另一种是预期的变化。比如需要发布新版本,需要伸缩,回滚。集群管理控制器就因该把集群从现有状态迁移到新的状态。这个过程叫“拟合”,举个栗子,我们需要对集群做Scale的时候,需要
a) 先扩展几个节点
b) 再往上部署服务
c) 然后启动服务
d) 再检查服务的健康情况
e) 最后把扩展出来的服务实例加入服务发现中提供服务
这个过程会比较“慢”,一方面,需要对其它操作排它;另一方面,整个过程必须努力逼近最终状态。此外,正在运行的服务也有可能出现问题,离开了我们想要的状态,而控制系统检测到后,会强行维持服务状态。
Kubernetes就是干这个的,没有这种控制系统的都不能称之为PaaS。
服务的弹性伸缩和故障迁移
有了服务状态拟合的基础工作后,我们就可以很容易的管理服务的声明周期了,具体到弹性伸缩,包括下列步骤:
- 底层资源的伸缩;
- 服务的自动化部署;
- 服务的健康检测
- 服务的发现和注册
- 服务的流量调度
而对于故障迁移,我们需要自动地恢复它,对于服务来说,有两种模式,一种是宠物模式,一种是奶牛模式
- 所谓宠物模式,就是一定要救活,对应有状态的服务。比如消息服务,redis缓存等
- 而奶牛模式,就是不救活了,重新生成一个。
对于这两种模式,会涉及到
- 服务的健康监控(APM)
- 如果宠物模式。需要服务的重新启动和服务的监控报警(如果重试不成功就需要人工介入)
- 如果是奶牛模式。需要服务的资源申请,服务的自动化部署,服务发现的注册,以及服务的流量调度。
很幸运的是Kubernetes和Docker都帮我们做掉了,只需要把传统的服务迁移上来,虽然这可能是一个艰巨的任务。
服务工作流和编排
一个好的操作系统需要能够通过一定的机制把一堆独立工作的进程给协同起来。在分布式服务调度中,这个工作就叫做"Orchestration",国内叫做"编排"
传统的SOA架构是通过ESB来完成的,其主要功能是通信路由、协议转换、服务编制和业务规则应用等。
而编排的意思是一个服务像乐队指挥一样,告诉大家该怎么交互。在微服务中,这需要一个API Gateway或一个简单的消息队列来做编排的工作,在Spring Cloud中,所有的请求都是通过Zuul网关来访问内部服务,这个和Kubernetes中的Ingress类似。