在刚刚过去的杭州云栖大会上,王涛讲师在企业级数据库最佳实践专场为大家带来了《云时代阿里数据库自动化管控平台》,这篇文章将详细介绍数据库自动化管控平台中基于微服务的第四代架构。
1、背景
记得有这么一句话:“一个好的系统是在不断地扩展、重构和修正的过程中建立的”。如今阿里巴巴数据库管控平台从第一代架构发展到了第四代架构,第四代是基于微服务进行构建的。而“微服务(Microservice)”这个词在过去几年一直很火,它用于描述一种程序架构设计的方式。Martin Flower大师对微服务有详细的阐述,而且作为广大程序员的设计标准。
业界Amazon等厂商都在企业内部实施微服务的体系架构,而国内也有很多企业在业务系统上实施微服务的体系架构。而运维系统呢?抱歉,至少目前来看暂时没看到,但是阿里数据库基础技术团队构建了一套基于微服务体系的数据库管控平台并且服务于生产环境。在这实践的过程中,我们也收获颇多,和大家一起分享。
2、系统演进
开源产品(第一代架构)
早在2005年,阿里数据库就有了自己的数据库运维管控平台。当时使用的是Nagios、Cacti等开源软件来搭建自己的平台。
单一应用架构(第二代架构)
伴随着MySQL时代的到来以及业务的快速发展,发现开源软件在使用后期可维护性,扩展性等都存在瓶颈。因此后面渐渐开始研发自己的系统。一个APP内部包含了三层结构(视图表述层、业务逻辑层、DAO层)来实践。从物理结构上来看,依旧是一个APP管理全局:
垂直应用架构(第三代架构)
2014年阿里推出异地多活,数据库运维的挑战也越来越大。因为DBA不仅仅要维护数据库本身,还要维护单元间的数据同步,保证各个单元数据和配置的一致性。因此我们的数据库管控系统越来越复杂。另外由于DBA的业务诉求也越来越多,需要越来越多是数据库软件本身的增值服务和企业级定制服务。因此我们的架构此时看起来有点纷繁复杂:
微服务架构(第四代系统)
为什么要推出第四代系统,第三代有什么问题?请看下面娓娓道来。
3、基于微服务架构实践
问题剖析
在“垂直应用架构”,渐渐发现在这种复杂的架构下,存在几个问题:
•系统与系统的调用越来越多,耦合度也越来越高,怎么保证全局的服务统筹管理?
•如果是一个下游系统,要访问A系统,再访问B系统,这样的调用对下游感受好吗?
•在某些极端场景下,如何做接口优先级限流?
•在机房孤岛等情况下,系统如何Work?
•......
正是基于种种问题的考虑,我们需要从全局的角度来思考和改进这些问题。
理论依据
众所周知分布式系统,一定离不开CAP原理(Consistency(一致性)、Availability(可用性)、Partition tolerance(分区容错性) )。CAP原理一般很难做到三者兼得。如图:
此外在机房孤岛的情况下,我们想让孤岛内部Work起来。因此我们想到了CAP理论的延伸品BASE理论:
•BasicallyAvailable(基本可用)
•Softstate(软状态,允许中间在某些状态下,出现状态不一致状态,实现异步)
•Eventuallyconsistent(最终一致,因为软状态是异步的,所以最终状态是一致的)
BASE思想的核心是获得高可用,允许中间状态的不一致,但是最终是一致的。很明显能够解决我们碰到的问题。
技术实践
由于架构选型和业务的诉求,我们自然过渡到了微服务的体系架构下。微服务大家自然想到了SOA,SOA架构下需要一套完整的服务注册和发现体系。因此我们对整体技术架构做了比较大的调整,每个模块都是一个独立的个体。设计的架构图,如下:
在技术实践的过程中,我们着重关注下面几点:
高可用
作为一个运维管控系统,高可用是我们考察的主要方向。由于是一个微服务模式,因此服务的注册发现中心尤为重要,我们选择了Eureka。Eureka官方文档中关于高可用架构介绍图,如下:
说明几点:
•EurekaServer节点之间无依赖,在孤岛状态下依旧可服务,在CAP里重点强调AP。传统的服务发现注册如Dubbo都是基于Zookeeper,Zookeeper在机房孤岛场景下,无法满足系统自身的高可用;
•在每个机房都部署各自的Eureka Server,机房之间通过Eureka自身的Replicate进行同步,这样做的用途主要有2个:1)保证数据全局一致性;2)在机房孤岛的时候,随着心跳的更新,这个Server只有本机房的服务注册列表,依旧保持系统自身可用性。这样的设计非常符合BASE理论,有没有?
•ApplicationServer连接任意一个Eureka Server,当出现Eureka Server不可用的时候,它再选择其他Eureka Server进行连接;由于Eureka Server确保每个机房都部署,因此在何种状态下,Application都能连接上一个Server;
•上面说的都是Eureka集群的高可用,关于Server自身的,一个是hearbeat,另外一个是数据,这点和ZooKeeper,数据库持久化不同,它全内存的,这点很大不同。官方文档这样解释“ifit all crashes the data will be rebuilt by the service registration heartbeat.As the first startup happens.“;但是仔细想想也有道理,这里留给大家自己品味;
•ApplicationServer其实就是Client,主要是几点:1)本地缓存;2)定时发送心跳并更新;3)毕竟是一个服务注册发现,真正服务之间调用的时候不需要经过Eureka;
API网关
传统的Spring MVC是单一架构,没办法很好的前后端分离,容易留下安全风险。 基于微服务架构,通过API网关对外暴露接口,可以真正的做到了前后端分离。
另外一方面,我们在安全方面做了复杂的验证,基于AccessKey,请求参数,Timestamp组合计算一个签名。签名随着时间、参数而不同,防止参数被篡改亦或请求过期等问题发生。
由于是运维管控系统,可能有N多的机器,N多脚本等来访问API网关,因此还做了流控,保证核心服务的可用性。
服务方式多样性
作为一个管控系统,必然底层有Java、GO、Python、C/C++、Shell等各种语言。因此我们在设计的时候留了两个通道:
•支持RPC,Java应用之间可以通过RPC调用,保证性能;
•支持REST,这样做的目的主要为了兼容非Java应用,每个微服务不单独做REST兼容,全部通过API网关来做处理,减少开发工作量。有时候Python等语言又会作为一个服务提供者,而Eureka支持REST格式,这样我们能够把Python等服务提供者也能容纳进来。
微服务划分原则
作为微服务,有时候很怕开发人员过度设计,拆出N个微服务,使得系统过于臃肿。因此我们从产品功能层面上做了划分:
•基础模块:运维操作、CMDB服务、备份恢复、告警、监控、高可用等作为基础模块;
•数据库功能增值服务,如:数据轨迹、数据库优化、数据库压测等;
•数据库企业增值服务,如:异地多活管控、一键建站、钉钉微应用等;
在这3个层面进行服务切分,上面提到的模块是最小的原子,不允许再做拆分,防止服务过于臃肿。
开发部署简单
由于每个微应用使用Spring Boot进行开发,避免了Spring繁琐的配置,因此打包出来的JAR包指定Active Profile即可使用。另外由于我们应用已经Docker化,就更简单了。
架构完整度
微服务经常需要提到的服务降级、变更管理、健康检查、限流、监控等。我们也有一套完整的体系。服务升降级都是通过Eureka进行管理;变更管理则是两块,Agent变更我们通过阿里数据库团队自研的FStack进行灰度和发布,应用发布则直接使用阿里的AONE进行管理;健康检查,监控我们更多依赖阿里巴巴自己的监控系统;限流,断路由等我们则是在API网关上进行实现。因此综合来看,我们整个微服务是一个体系,而不是单纯的微服务应用。
4、总结
一个系统是需要不断的迭代和发展,才能不断的成长。另外微服务也不是万能药,需要从业务和技术两个层面进行思考,才能设计出适合自己企业的系统。
作者:CatherinePlans
链接:https://www.jianshu.com/p/18e3e5acdefc