原文地址:https://xintu.infoq.cn/article/AJj3lKQyaKVeA08Bgj9e
背景为数以亿计的用户提供优质的视频服务的爱奇艺技术产品团队,为了适应业务的快速迭代和创新,并支撑海量的用户请求,很多团队都对各自的业务系统自发地进行了微服务架构的改造。
在微服务化的过程中,各业务团队根据自身需要选择了不同的开源框架,如 Apache Dubbo/Spring Cloud 等,此外也存在一些自研性质的框架;另外为了满足对微服务应用的监控等需求,不少团队还自行维护了监控系统等基础设施。
随着实践的深入,一些问题逐渐开始暴露,这其中包括:
·部分基础设施存在重复建设,在资源浪费的同时稳定性也不易保证;
·由于使用的技术架构和 SDK 不统一,最佳实践难以在团队间快速推广;
·技术架构不统一导致在东西向流量中大量引入了业务自行维护的网关,使得链路加长,影响排障效率和响应延时。
为了解决以上问题,爱奇艺中间件团队充分听取了业务在微服务实践中的需求和问题,推出了爱奇艺的微服务标准架构。在标准架构的建设过程中,我们主要遵循了以下的一些原则:
1.架构统一:同一技术领域往往有多种技术实现,但是过多的技术框架的采用容易造成维护成本过高,缺乏专人支持等问题。在微服务标准架构的选型过程中,我们综合了各开源项目的实际情况和业界的主流技术方案,将各个领域中的技术选型进行了统一,每个领域的技术选型原则上均不超过 1 种。
2.可扩展:微服务标准架构中有不少开发 SDK 的选型,为了满足各个开发团队不同的业务需求,需要保证各个 SDK 的可扩展性,如果开源版本无法满足内部需求的,爱奇艺中间件团队都会维护统一化的内部定制版本。
3.高可用:标准架构的建设目的之一是将各个团队维护的基础设施(如注册中心、监控系统等)逐渐收拢至内部的公共平台。对相关平台的技术架构 review 及可用性维护也是我们的重要工作之一,此外我们还建设了服务成熟度体系 SMMI,会定期对核心系统及基础服务进行成熟度评估。
4.技术演进:开源软件均有其生命周期,需要充分考虑各个软件的社区维护情况,比如在熔断技术选型上,我们在标准架构中主推了 Sentinel,而不是目前已经停止维护的 Hystrix。另外标准架构也并非一个一成不变的体系,对于新技术的采纳,我们也提供了标准化的流程,确保我们的技术体系能持续迭代。
5.内部开源:在标准架构的建设过程中,在爱奇艺内部开展了内部开源的协作模式。除了基础服务部门以外,也鼓励业务团队参与到这些基础服务的维护工作中来,共同打造一个即符合业务需求,又有一定业界领先度的微服务技术体系,这样也进一步促进了相关标准架构的推广和完善。
爱奇艺微服务标准架构下图展示了爱奇艺微服务标准架构的全貌:
标准架构主要包括如下主要内容:
*统一的微服务开发 SDK:核心开发框架 Dubbo/Spring Cloud;熔断限流框架 Sentinel 等;
*统一的微服务基础设施,包括:
·注册中心:Nacos/consul;
·服务网关:基于 kong 进行二次开发的网关平台,提供鉴权、限流等功能;
· 配置中心:基于携程 Apollo 进行二次开发的平台
·指标监控:prometheus 集群托管服务;
·链路监控:全链路平台(基于 skywalking 进行定制开发);
·混沌工程:在 ChaosBlade 基础上进行二次研发,提供各类故障演练功能。
*统一的微服务平台:QDAS(QIYI Distributed Application Service,爱奇艺分布式应用服务),提供微服务应用生命周期管理、服务治理、服务市场等功能。
标准架构生态建设以下将从微服务 SDK、注册中心、监控体系、熔断限流、API 网关、微服务平台等几个微服务标准架构的核心点做一些展开的介绍。
开源 SDK 定制根据各个业务团队的需求,爱奇艺中间件团队主要对 Dubbo SDK 做了以下几方面的扩展:
1.基础设施的适配:包括注册中心、监控系统、内部的容器平台等等;
2.可用性增强:包括非健康实例隔离以及区域就近路由的机制;
3.安全性增强:支持了服务间调用的认证机制;
4.序列化:增加了对 protobuf 序列化方式的支持。
注册中心演进注册中心在微服务应用中是最重要的基础设施之一,原先在爱奇艺内部,注册中心的选型并不统一,之前在线上运行的注册中心有 ZooKeeper、eureka、consul 等。事实上,ZooKeeper、eureka 等并不是当前业界中微服务注册中心的最佳选型,以 Zookeeper 为例,其主要缺点包括:
1.无法横向扩展;
2.作为一个一致性的系统,在网络分区会产生不可用。
在调研了业界的各个方案后,我们选用了 Nacos 作为我们下一代的微服务注册中心。右下角是 Nacos 的整体介绍图,选用 Nacos 的主要原因是:
1.高性能,可以横向扩展;
2.既适用于传统为服务架构,也能适用于云原生环境,包括支持与 Istio 控制面对接;
3.提供了 Nacos-Sync 组件,可与其他注册中心进行数据同步,也使注册中心的迁移变得简便。
Nacos 高可用部署在部署 Nacos 服务时,我们充分考虑了服务部署架构方面的高可用性。目前我们的 Nacos 服务是一个大集群,实例分布在多个不同的可用区中,在每个可用区内部,我们会申请不同的 VIP,最终的内网域名是绑定在这些 VIP 上。另外其底层所使用的 MySQL 也采用了多机房部署。这样的架构可以避免单个 Nacos 实例或者单机房故障造成整个 Nacos 服务的不可用。以下是一些可能的故障场景的模拟:
1.单个 Nacos 实例故障:利用 Load Balancer 集群提供的健康检查能力自动从 VIP 中摘除;
2.某个 VIP 集群故障:利用客户端重试机制解决;
3.单个 AZ 故障:利用客户端重试机制解决;
4.MySQL 集群故障:MySQL 与注册发现过程无关,不受影响;
5.整个 Nacos 服务故障:客户端兜底机制,如服务实例缓存等。
注册中心平滑迁移方案接下来将简单介绍一下如何使用 Nacos-Sync 进行注册中心的平滑迁移。
1.首先要部署一个 Nacos-Sync 服务,从旧的注册中心向 Nacos 同步数据。Nacos-Sync 支持集群化部署,部署多个实例时,其向新注册中心的写入时幂等的,并且它原生支持 Dubbo 的注册数据格式;
2.检查数据无误后,首先升级 Consumer 端,改为从 Nacos 注册中心进行发现。这时的服务发现的数据均是由 Nacos-Sync 从旧的注册中心同步过来的;
3.再升级 Provider 端,改为向 Nacos 进行服务注册;
4.下线 Nacos-Sync 服务及旧的注册中心,整个迁移流程就结束了。
以上方案的主要优点包括:
*服务提供方和消费方的升级完全独立,可以自行进行;
*迁移涉及的应用仅需升级一次。
监控体系建设服务监控是所有业务团队都极为关注的主题。完整的微服务监控体系一般需要有以下 3 个方面组成:
1.指标监控:包括 QPS/响应延时/错误率等黄金指标、业务的自定义指标、JAVA 应用的 JVM 指标,此外还需要采集和基础环境的相关指标,包括 CPU/内存利用率等;
2.日志监控:如错误日志的数量;也可以利用 AI 技术,对日志的模式进行统计分析等;
3.链路监控:由于微服务调用关系的复杂性,调用链追踪也是非常必要的,它可以帮助业务人员更好地分析应用间的依赖关系,并能够监控各个调用关系上的核心指标。
指标监控指标监控方面,我们内部围绕着 Prometheus 建设了一套较为完整的监控和告警的标准化方案。这里面要解决几个问题:
首先是指标计算的问题,为了降低侵入性,我们在 skywalking agent 的基础上进行了二次开发,可以自动拦截 Spring MVC/Dubbo 等主流框架的调用,统计其调用次数、处理耗时、是否错误等等。
其次是指标采集的问题,Prometheus 是采用拉模式采集指标的,对于微服务场景一般是利用 Prometheus 的服务发现机制。Prometheus 默认集成了 consul、k8s 等服务发现方式,不过并未对 Nacos 注册中心直接提供支持,我们在开源的 Nacos adapter 的基础上进行了改造,使得 Prometheus 能够从 Nacos 中发现要采集的应用实例信息。
指标查看主要采用了 grafana,我们提供了一套通用化的配置模板,业务也可以根据需要自行扩展。
告警方面,我们将告警策略设置在 Prometheus 中,具体的告警会由 alert-manager 通过 adapter 发送给内部的监控告警平台。
监控 dashboard 查看、告警策略设置、订阅的入口统一设置在我们内部的全链路监控平台上,用户可以在该平台上查看进行相应的操作。
下图展示了服务监控界面:
链路追踪链路追踪的基本原理也和 google 关于 Dapper 的论文一致,应用程序通过埋点的 agent 产生调用链数据,通过日志采集或者网络直接上报的方式统一汇总至 kafka,通过我们的实时分析程序进行分析。分析结果大致可以分为三类,原始的调用链数据我们会使用 ES+HBase 进行存储,调用关系上的实时监控数据我们采用时序数据库 druid 进行存储,拓扑关系采用图数据存储。
链路追踪主要提供了一下功能:
1.调用依赖关系分析:提供了服务间依赖及接口间依赖的多个层次粒度,支持 MySQL/Redis 等各类中间件,为开发人员提供各种上下游依赖的直观展示;
2.服务间调用关系指标:提供 QPS/响应延时错误率等核心指标监控,且能在一个调用关系上同时提供客户端及服务端两个视角的监控值,便于进行问题定位;
3.程序异常分析:在调用链数据中心记录异常类型及堆栈信息并进行分析,支持展示某个应用的程序异常种类及每分钟发生次数等;
4.日志关联:将调用链与业务日志进行关联查询,便于获取程序运行的详细信息。
熔断限流方案由于微服务架构的特点,上下游依赖和网络通信都比较多,这些因素都会对应用本身产生一定的风险,比如上游系统的突发流量或者热点参数;下游系统服务不可用、延时增大、错误率升高等等。如果缺少对自身系统的保护,有可能产生雪崩的效应。为了应对这些场景,我们主要引入了 Sentinel 框架进行解决。Sentinel 的核心原理是用户可以定义各类资源(资源可以是本地的一个接口,或者远程的某个依赖),并在资源上设置各种规则(比如限流规则),在访问某个资源时,Sentinel 组件会检查这些规则是否满足,在不满足的情况下会抛出特定的异常。用户可以通过捕捉这些异常实现快速失败或者降级等业务逻辑。Sentinel 还提供了一个控制台,可以用来管理规则的参数设置以及查看实时监控等。
为了适应爱奇艺各个业务团队的需求,我们对 sentinel 框架做了一定的扩展,下面的例子即是我们实现的复杂参数限流功能。Sentinel 框架本身就自带热点参数限流的功能,不过仅支持一些简单类型的参数(如 String、int 等)。在有些情况下,限流的场景可能比较复杂,比如下图中,可能要根据第一个参数的 id 属性进行限流,这种场景原生的 sentinel 并未提供支持。针对这种情况,我们提供了一个抽象的接口,允许用户通过自己的实现从参数中提取出需要限流的资源。
为了实现规则参数的动态下发,我们将 sentinel 与内部的配置中心进行了适配。在 sentinel dashboard 上进行的参数改动,最后都会保存至配置中心,业务系统通过引入配置中心的 SDK,即可实现在不重启应用的前提下进行参数的动态调整。
在 QDAS 管理平台上,我们还利用 k8s 技术提供了 sentinel dashboard 的托管功能,省去了各业务团队在这方面的部署维护成本。
API 网关爱奇艺 API 网关底层基于开源项目 Kong 实现,旨在为开发者提供稳定、便捷、高性能、可扩展的服务入口功能,一站式管理 API 配置和生命周期,对微服务治理具有重要意义。
在 API 网关控制流架构设计中,微服务平台 API 网关模块通过内部系统集成及服务化实现,为开发者提供全部所需入口配置及管理功能,且无需代码侵入、工单申请等人工干涉,实现 API 创建即可用。API 网关支持认证、限流、访问控制等通用功能。
结构如下图所示:
QDAS在完善的微服务体系架构中,微服务治理平台也必不可少。QDAS 是一个以应用为中心的一站式平台,通过功能插件的形式,对微服务应用的开发、部署、运维各个环节进行全生命周期的支持,同时兼容 Dubbo/Spring Cloud 传统微服务框架和 Istio 服务网格架构。
QDAS 平台主要支持的功能包括:
1.应用基本信息维护
2.传统微服务治理
(1)实例列表及与 Nacos 注册中心集成的实例上下线管理;
(2)Grafana 核心指标监控大盘;
(3)Sentinel dashboard 托管;
(4)基于 Sentinel 的接口鉴权和流量配额管理(开发中);
3.应用生命周期管理
支持在各类平台(容器/虚机)上的应用部署和版本升级功能
4 服务市场
接口契约管理:包括基于 Swagger UI 的接口描述查看等。
混沌工程Netflix 最早系统化地提出了混沌工程的概念,目的是尽早的识别风险,对薄弱的地方做针对性的加强。我们也一直在注重自己的故障演练,借助一些内部的工具跟外部开源项目,逐步演化出自己的故障注入平台——小鹿乱撞。借助平台,可以编排自己的演练方案进行演练,检验服务的健壮性。
目前小鹿乱撞平台已经支持包括服务器、容器(docker)、数据库、中间件、网路设备、k8s 集群等进行故障注入,并可在演练过程中实时展示关联的监控、日志以及报警等,演练结束后自动生成演练报告。
另外,借助平台定时演练的能力,用户可以方便的实现周期性演练的效果。
未来规划对于微服务标准架构的未来规划,大概分为以下几方面的工作:
微服务技术趋势方面,云原生与 service mesh 已经是微服务技术演进的一个趋势了,如何引入 service mesh 技术,并向各个业务提供平滑过渡的解决方案,将会是我们今后工作的一个重点。
在服务治理方面,我们会进一步扩展 QDAS 平台的功能,以期建成一个对 service mesh 和传统微服务都适用的控制面。
在开发者支持方面,未来计划推出项目脚手架以及在线调试等服务,使得开发人员能更方便地进行项目开发,以及线上问题的排查等。