您还未登录! 登录 | 注册 | 帮助  

您的位置: 首页 > 软件开发专栏 > 开发技术 > 正文

从一个微服务应用的成功落地,谈企业需要什么样的微服务治理

发表于:2022-04-28 作者:阿里巴巴中间件 来源:阿里巴巴中间件

作者 |  阿里云微服务团队

一、从一个典型的案例谈起

1.微服务开发不简单

随着微服务技术的发展,微服务(MicroServices) 的概念早已深入人心,越来越多的公司开始使⽤微服务架构来开发业务应用。

如果采⽤得当,微服务架构可以带来⾮常⼤的优势。微服务架构的最大的好处是它可以提升开发效率和系统整体的稳定性:

  • 开发和部署相对简单:单个微服务的功能可以更快地更改,因为可以独立部署,影响范围更小,启动和调试单个微服务的时间成本相比于单体应用也大大减少。
  • 横向扩展简单:根据业务的高峰低谷周期快速的横向扩展非常简单,因为单个微服务通常很小,可以随着系统整体负载的变化更快地启动和停止。
  • 架构升级灵活:单个微服务的内部架构可以迅速升级,因为微服务之间是松散耦合的,只面向定义好的通讯接口进行编程。这使开发团队能够基于自身的技术背景和偏好灵活选择,而不会直接影响其他应用程序、服务或团队。
  • 更好的容错性:微服务之间可以实现更好的故障隔离,单个服务内的内存泄露等故障不容易影响其他服务,相比单体应用⼀个组件故障会拖垮整个系统。

但是微服务在实施过程中,也很容易遇到一些难点。如果微服务治理得不恰当,反而有可能适得其反,不仅不能享受到微服务架构带来的好处,反而会因为微服务带来的系统复杂性,造成开发、运维部署的复杂度增加,进而影响开发迭代的速度,甚至影响系统的整体稳定性。

我们总结了⼀些微服务开发实施过程中常见的问题:

  • 服务之间使用远程调用进行通讯,这比进程内的直接调用复杂很多。由于通讯链路的复杂性,可能会出现很多不确定的问题,会出现远程调用不可用或者延迟较高的情况,开发⼈员需要能够处理这些偶发问题,避免影响业务。
  • 随着业务的发展,微服务之间的拓扑图开始变得复杂,排查问题变得困难,搭建完整的开发测试环境成本也越来越大。
  • 当功能涉及到多个微服务模块时,迭代时需要谨慎地协调多个开发团队的迭代排期,才能保证迭代能够按时交付,达到敏捷开发的效果。

2.⼀个微服务成功落地的典型案例

观察了阿里云众多客户之后,我们总结了⼀个微服务成功落地的典型案例,某公司借助于微服务架构的红利,实现了业务快速增长:主要会分析在业务发展的不同阶段,该公司在微服务实施过程遇到的问题,以及如何通过微服务治理来解决这些问题,从而享受到了微服务带来的开发效率和业务稳定性提升的红利,进而促进业务快速发展。

(1)业务孵化期

初创公司在刚起步时,虽然业务量比较小、业务模式比较简单,但是为了在后续的快速发展中能够快速迭代,同时公司的人才储备也满足微服务开发的条件,于是在初创期就选择了使用微服务架构进行业务开发。

在技术选型方面,如果公司创始员工是技术出身,那么会比较倾向于使用自己擅长的微服务框架,如创始人是 Dubbo 的 contributor ,或者是 Spring Cloud 社区的大咖或者 Spring Cloud Alibaba 的contributor,又或者是 Service Mesh 社区的大咖,⼀般都会选用自己所擅长的微服务框架类型。还有一种选择是选用市面上最流行的微服务框架,如 Java 体系,会选择 Spring Cloud 和 Dubbo。在目前的招聘市场上也容易招聘到熟悉相关领域的人,从初学者到专家级的候选人都能很容易招聘到。

选定了技术选型后,基于开源的框架,很容易就能开发好最初的业务应用系统,跑通业务流程。这⼀阶段组件也很简单。简单的两三个应用,用户系统、业务系统、支持系统,再加上注册中心、数据库、缓存,就可以开发完全部的应用。

对于一个生产级别的系统来说,在将整套系统部署上线之前,还需要建设监控报警系统。监控报警系统能够帮助我们实时监控机器和应用的状态。我们可以配置预设的报警规则,在出现机器资源不足,业务出现异常报错时这些情况时主动报警,提醒我们尽快处理系统中的风险和异常。保留问题的现场,并帮助我们快速地定位和排查问题也同样重要,阿里云应用实时监控服务 ARMS 和日志服务 SLS 能够在这些场景提供很大的帮助。

采用 ARMS + SLS 完成监控报警系统建设之后,将业务系统部署上线,完成第一次成功上线,业务开始正常运行起来了。

但是业务的开发和运营从来都不是⼀帆风顺的,在这个过程中,肯定也会遇到很多问题,我们先总结⼀下这个阶段常见的问题及应对方案:

1) 因为代码本身逻辑出错导致业务异常:这时可以通过 SLS 查询日志,结合 ARMS 分析错误堆栈找到根因,修改完代码后,重新发布来修复问题。

2) 遇到性能瓶颈:则直接扩容操作,如水平扩容应用,或者升级数据库。

3) 发布新版本影响到用户:因为用户数和请求数都不算多,很容易就可以找到业务低峰期,在业务低峰期进行发布。

4)如何确保新版本的正确性:因为业务场景不复杂,内部测试就能覆盖所有的场景,测试通过就可以直接上线。那如何识别自身的业务是否处于这个阶段呢?有⼀系列典型的特征:应用不超过 4 个,应用节点总数不超过 10 个,最高峰时候的 QPS 不超过 10。

(2)业务快速发展期

度过初创期之后,公司的业务很受用户和市场的欢迎,注册的用户越来越多,用户使用的时长和功能点也越来越多,日活数越来越大,甚至市场中还出现了其他竞争者开始抄袭公司的业务,一些巨头还亲自下场参与竞争。公司业务发展得非常顺利,这也意味着系统进入了快速发展时期。

市场发展很迅速,注册用户数、日活这些数据也是节节攀升,所有统计报表的数字都是一片向好。但是带来的挑战也越来越大,这个时期也是最危险的时期:在业务快速发展中,既要保证好已有业务的稳定性,又要快速地迭代新功能,还要克服团队招聘节奏跟不上业务发展的问题。

这个阶段典型的特征是应用个数在 5 到 50 个,QPS 在 10 到 1000。这个时期经常会遇到的问题概括起来就是两个:稳定性问题和开发效率问题。

稳定性的问题:用户数多起来之后,系统的稳定性就显得比较重要,无论是用户在某段时间遇到异常报错增多,还是某⼀个功能点持续性地报错,再大到系统有⼀段时间完全不可用,这些都会影响产品在用户中的口碑,最后这种完全不可用的场景,甚至还可能成为微博等社交网络上的舆论热点。

开发效率的问题:随着用户的增多,相应的需求也越来越多,业务场景也越来越复杂,在这个时候测试可不是内部测试就能覆盖所有的场景,需要加大在测试上的投入。虽然功能需求越来越多,但是迭代的速度却要求越来越快,因为市场中已经出现了竞争者,如果他们抄得快,新功能也上得快,业务有可能会竞争不过,特别是当巨头亲自下场的时候,更需要跑得更快,开发节奏要快,测试节奏要快,发版节奏也要快。

那么如何去解决这两个场景的痛点呢,这时候可以要借助微服务治理的能力来解决。

1)开发测试提效

a.【开发环境隔离】传统的多套开发环境,需要使用多套的物理环境,才能实现多套环境各自独立互不干扰,但是多套物理环境的隔离的机器成本是很高的,基本上不⼤能接受。但通过全链路灰度这种逻辑隔离的方式实现开发环境隔离,可以在不增加成本的情况下增加多套开发测试环境,助你实现敏捷开发。

b.【自动化回归测试】自动化回归测试功能,可以将多个测试用例串联成测试用例集,将上⼀条测试的返回值作为下⼀跳测试入参,串联成具体的业务场景并沉淀到自动化回归测试中,在每⼀次的发版之前都跑⼀次自动化回归来验证功能的正确性,这样就可以大大节省测试的人力成本。更进⼀步,还可以通过流量录制回放功能,将线上的真实流量录制下来,并沉淀成自动化回归用例集,在测试环境进行流量回放,更进⼀步地提升测试 case 的覆盖率。

c.【服务契约】功能越来越多,迭代越来越快,API 越来越复杂,团队之间沟通的效率越来越低,API 文档严重过期。如果自动生成服务契约,可以有效地避免文档腐化造成的开发效率低下的问题。

使用上面三点之后,可以在低成本的条件下支持多套开发测试环境,实现自动化回归测试,实现开发节奏和测试节奏的大大提效。

2)安全发布

a.【无损下线】无损下线问题的根本原因是开源的微服务体系没有确保应用提供者节点在停止服务前确保已经通知到所有消费者不再调用自己,也无法确保在处理完所有请求之后再停⽌应用。所以新发版的应用,即使业务代码没有任何问题,也可能在发布过程影响用户的体验。

b.【无损上线】无损上线问题出现的原因是因为在某些场景下服务提供者,需要经过⼀段时间才能正常地接收大流量的请求并成功返回。同时在 K8s 场景下,还需要和 K8s 中的 readiness 、滚动发布等⽣命周期紧密结合,才能确保应用发布过程中能不出现业务报错。

c.【全链路灰度】新功能上线之后,可以通过灰度规则控制哪些⽤户可以使用。这样可以先选择让内部用户使用,测试新功能的正确性。当内部用户验证通过后,再渐渐地扩大灰度范围,确保每个功能都经过充分验证后再全量开放给客户,屏蔽掉发布新功能的风险。而且当出现问题时,可以通过修改灰度规则来实现快速回滚,做到新版本发版时几乎无风险。

使用以上几点之后,可以确保新版本的发布不出问题,而且可以做到白天在大流量场景下也轻松发布,在实现白天轻松发布之后,⼀天就可以发布多次,提升发布时候的稳定性和发版的效率。

3)屏蔽偶发异常导致的风险

a.【离群实例摘除】对于这些偶发的异常问题,离群摘除功能可以智能判断应用中的服务提供者某个出现了问题,智能地在⼀段时间内屏蔽掉这个服务提供者,保证业务的正常,等这个服务提供者恢复过来之后再进行调用。可以在应用节点出现偶发异常时,智能屏蔽掉此节点,以免影响业务,等此节点恢复后再继续提供服务,从而屏蔽偶发异常导致的风险。

据统计数据显示,有将近 90% 的线上故障是由于发版过程中出现的,剩下的 10% 左右的线上问题,可能是由于⼀些偶然的原因导致的。如偶然的网络故障、机器 I/O 出现问题、或者是某台机器负载过高等。在解决了发布时候的稳定性问题和偶发异常导致的风险后,基本能够确保线上业务不会出现灾难性的问题。

在业务快速发展的生死存亡期,需要借助于这些微服务治理能力,确保业务能够又快又稳地增长,度过这段生死存亡期,成为这个领域的重要玩家。

(3)业务成熟期

当业务进入成熟期之后,业务的开发进入了新的阶段,这时候,虽然快速发展过程中的问题仍旧存在,但是会因为业务量上来之后,遇到新的问题。

低成本创新:虽然发展不像原来那么迅速,但是业务创新探索的诉求仍旧存在,由于业务规模的扩大,创新的成本也在增加。这个时候不仅是需要快速开发迭代,更大的需求是用尽可能小的成本进行创新探索测试,有时候还需要使用上 AB 测试的手段进行实验比较。

容灾多活:由于业务规模已经很大了,治理中的稳定性的诉求更加强烈,而且随着业务范围的扩大,应⽤也开始在多个地域、多个云产品中进行部署。同城容灾、异地多活这类需求也开始出现。

问题定位:出现任何问题都必须彻查。虽然出现问题时,业务恢复仍旧排查第⼀位,但是业务恢复之后的问题根因定位也是不能少的,因为如果不彻查,难免后续出现同样的问题。

风险预案:紧急预案、风险预防也变得非常重要,需要提前做好业务的保护和降级的埋点演练,在遇到绝大多数可预见问题可以紧急修复,出现不可控问题时,可以通过预案手段执行预案,确保整体业务的可控性。

从这个典型的案例中,我们可以看到,微服务的成功落地和业务的快速发展,离不开微服务治理的支持。在业务发展的不同阶段,会遇到不同的微服务问题,需要借助于治理的能力,为业务的又快又稳发展保驾护航。

二、微服务治理在云原生场景下的挑战

1.企业上云的四个阶段

随着云原生时代的到来,越来越多的应用生在云上,长在云上,且随着越来越多的企业开始上云,云原生也是企业落地微服务的最佳伴侣。我们分析了阿里云典型客户的实践经历,业务上云通常划分为 4 个阶段:云上部署、云原生部署、微服务化、服务治理。

(1)云上部署

这⼀阶段我们解决的问题,如何把传统业务,原来是跑在自建 IDC 机房的业务,能够原封不动地迁移到云上。通常云厂商提供了丰富的计算、存储、网络等资源可供选择,以虚拟化技术,神龙裸金属服务为代表的硬件可以满足企业客户上云搬迁的丰富需求,这⼀阶段关注的焦点是资源,对于业务并无任何的改造,只需要从本地原样搬迁到云上即可。

(2)云原生部署

云原生是释放云计算价值的最短路径,以容器技术为代表,云原生提供了强大的调度、弹性等能力,极大地降低了上云的成本。这⼀阶段我们关注的目标主要是业务进行云原生化改造,随着 Kubernetes 作为容器编排市场的事实标准,我们需要把业务从原来的的虚拟机部署方式改造成容器化方式,部署并运行在 K8s 之上,最大限度享受到云原生带来的技术红利。这⼀阶段核心关注目标以容器为核心。

(3)微服务化

当我们的业务规模逐步扩大,传统单体应用很难进⼀步支撑业务的发展,业务的迭代速度已经无法满足业务的增长,此时我们就需要进行微服务化的改造,降低业务的耦合度,提升开发迭代的效率,让开发更加敏捷。这⼀阶段我们聚焦以应用为核心。

(4)服务治理

当微服务的规模也越来越大的时候,如果对微服务不加以规范和整治,很容易出现问题。例如,每个微服务都有独立的团队来维护,他们之间如果依赖没有整理清楚,可能会出现架构上循环依赖等问题。从我们的数据观察来看,当微服务的节点数超过数十个的情况下,我们通常就需要引入服务治理,通常需要关注的是开发、测试、线上运维,安全等多方面考虑,这⼀阶段我们聚焦以业务为核心,核心目标是进⼀步提高开发效率,提高线上业务的稳定性。

2.微服务治理在云原生下的挑战

随着企业微服务化进程的逐深入,微服务的云原生化逐步进⼊深水区,在这个微服务深化的过程中,我们逐步会面临⼀系列的挑战,总的而言,我们将这些挑战分为三个大的层面,分别是效率、稳定和成本。我们进行微服务化,本身的使命是让业务的迭代更加高效,但当我们的微服务数量逐步增多,链路越来越长,如果不进行进⼀步的治理,那么引发的效率问题可能会大于微服务架构本身带来的架构红利。在微服务实施的不同阶段,遇到的问题也不尽相同。目前阿里巴巴内部的微服务节点数量是在百万级别,在这个过程我们也积累了非常多的治理经验。

(1)在效率上面临的挑战

在效率方面需要追求的目标是,在开发、线上运维、SDK 升级等方面更加高效。

  • 在开发阶段,我们需要考虑的是,业务应用上云之后,如何让本地开发的应用,很好的部署云上的业务进行联调?通常我们的微服务不可能在本地完整的部署⼀整套系统,所以本地开发的应用只是整个微服务链路的⼀小部分,这包括我们的流量需要能够轻松的从云上,引导到本地,便于我们做开发调试,或者我们在本地能够很方便的调用云上部署的微服务进行联调。这在微服务上云之后,比原来在自身机房进行开发联调更加困难。
  • 在线上运维方面,我们通常需要频繁的对微服务进行变更,这些变更通常就会引发⼀系列的问题,例如在白天高峰期做发布,通常都会导致业务流量出现损失,我们的研发人员不得不选择在晚上业务低峰期做变更,这大大降低了研发人员的幸福指数,因为他们不得不面临熬夜加班的困境。如果能在白天大流量高峰期也能进行流量无损的变更,那么这对于研发⼈员来说将是大大提升研发效率的事情。
  • 微服务框架通常会引入服务治理的逻辑,而这些逻辑通常会以 SDK 的方式被业务代码所依赖,而这些逻辑的变更和升级,都需要每⼀个微服务业务通过修改代码的方式来实现,这样的变更造成了非常大的升级成本。以阿里巴巴为例,阿里内部⼀个中间件 SDK 的升级,如果要在整个集团铺开,通常需要消耗的时间以年为单位进行统计,这里面也会消耗每个微服务应用的研发、测试等庞大的资源,效率非常低下,如果能够以无侵入的方式实现中间件 SDK 的升级,那么将会是⼀件非常高效的事情。
  • 进入云原生体系之后,以 K8s 为主的云原生体系强调集群之间的灵活调度型,以 POD 为单位任意的调度资源,在被调度后 POD 的 IP 也将相应地发⽣变化,传统的服务治理体系,通常以 IP 为维度进行治理策略的配置,例如黑白名单策略等,但是当进入云原生场景后,这些传统的治理策略都会面临失效的问题,因为 POD ⼀旦被重新调度,原来的治理策略都将不再使用,如何能让服务治理体系更加适应云原生体系,也是我们要面临的⼀大挑战。

(2)在稳定上面临的挑战

稳定大于⼀切,在微服务上云之后,业务高可用是我们必须要解决的问题,因此通常会在同⼀个地域的多个可用区内进行部署,在多可用区部署的情况下,跨可用区的延时就是不可忽视的问题,我们需要思考的是业务流量需要能够尽量在同⼀个可用区内进⾏流转,同时也需要考虑的是如果⼀个可⽤区出现问题,业务流量能够尽可能快的流转到正常的可用区,这就对我们的微服务框架的路由能力提出了挑战。

当然,我们的业务不仅需要在同⼀个地域里保证高可用,也需要考虑⼀个地域出问题的时候,保证业务的高可用,这时我们就需要考虑业务实现同城双活,甚至是异地多活,这对我们来说也是一大挑战。

第三,微服务之间的调用也需要更加的安全可信,近期层出不穷的安全漏洞,⼀定程度上也反映出当前上云阶段在安全方便暴露出的问题还是非常多,每次安全漏洞出现之后,中间件 SDK 的升级也是困扰业务多年的问题;同时,⼀些敏感的数据,即使在数据库层做了非常多的权限管控,由于微服务被授予了数据访问的较高权限,如果微服务的调用被恶意攻击,也可能会造成敏感数据的泄露。微服务之间的调用需要更加可靠可信。

(3)在成本上面临的挑战

首先,在成本方面,业务上云遇到的最⼤问题就是如果最低成本的把业务迁移上云,对于⼀个在线业务,如果要进行停机迁移,那么迁移的成本会显得非常高,对于客户的体验也会收到影响,要在不中断业务的情况下,实现平滑迁移上云,还是有非常大的挑战的。

其次,当我们在业务面临极速增长的流量时,迫切的需要快速的弹性,补充更多的资源以承载业务的高峰,当我们进入业务低峰的时候,又希望能够缩小容量,节省资源,因此云产品提供的快速灵活的弹性机制,是微服务上云之后⼀项急需的能力。