如何避免单点风险:基于实践经验分享服务拆分原则的一些思考

  • 缘起:系统崩了

  • 具体情况:1%的请求影响了剩余90%的请求

  • 架构演进:拆分热点服务【进程级隔离】

  • 复盘

  • 总结

  • 拆服务的经典实践

 


不能变形的变形金刚也叫变形金刚?

缘起
系统崩溃了?别惊慌!这里有快速恢复的方法!
分析发现,网站崩时服务X被流量打垮,继而依赖服务X的其它服务开始互相“踩踏”,最终崩溃。
网站崩时,服务X的QPS过高,实际达到了业务gateway服务的2倍~~

 

出故障时的系统结构概览:

 


一个请求的生命周期

具体情况:1%的请求影响了剩余90%的请求

 

相同时段之前崩掉服务的情况:

 

业务gateway的流量为什么会远小于服务x的流量是不是合理?

 

业务服务与基础数据服务耦合在一块是不是合理的??

 


接口响应时长, 也从毫秒级, 快速退化到秒级

 

图片

一个查Redis缓存的请求耗时7708ms

图片

org.springframework.web.servlet.FrameworkServlet.doGet(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response)

解决方案:拆分热点服务【进程级隔离】+水平扩容+k8s HPA

https://www.processon.com/view/6447cd7e8e188d4a087d3d1e

架构升级后服务的效果:
1、架构更合理了
2、接口响应时间更短

 

 

复盘
1、这是谁的问题?
这是服务的稳定性的问题。

2、有什么问题?
一个服务崩了,导致整个业务系统崩了。

3、解决的思路是什么?
把整个业务系统依赖的基础拆出来。

总结
一个基础服务不可用,导致整个业务系统不可用。
然后,通过把这个基础服务拆成一个单独的服务,来解决这个问题。

 

思考
服务拆分的原则是什么?

在分享关于服务拆分的思考之前,让我们先来谈一些相关的概念吧。

什么是架构?

软件架构是指软件系统的顶层结构,而架构设计的目的是为了解决软件复杂度,是为了使软件项目更加可靠、高效和可扩展,以便于持续迭代。
架构的思考来源于对生命周期的识别,以及对生命周期的拆分。如果没有生命周期拆分的思考,就不能算架构。什么是微服务架构?
微服务架构是一种架构模式,它提倡将单一应用程序划分成一组小的服务,服务之间互相协调、互相配合,为用户提供最终价值。微服务架构的本质是分布式系统。
来看看Martin Fowler大佬的理解:

 


上述英文的三个关键词分别是:small、lightweight、automated,这基本上浓缩了微服务的精华,也是微服务和SOA的本质区别所在。

微服务拆分的目的是什么?服务拆分的目的是将庞大复杂的系统拆分成小而简单的服务,以便更好地应对持续迭代的需求。
这样做的好处在于,各个服务可以独立运行,降低了彼此的耦合度,使得后续的开发、部署、测试和维护等工作更加容易进行,从而提高了系统的可靠性、可扩展性和可维护性。因此,服务拆分不仅是为了简化系统,也有助于让系统更好地适应未来的变化

微服务拆分的原则:化大而复杂为小而简单。

进行服务化拆分,把一个大而复杂的问题化解为多个小而简单的问题,服务之间通过契约来约定依赖,做到服务独立发布和演进。
微服务到底有多微,是个仁者见仁,智者见智的问题,最重要的是团队觉得是合适的。但注意,要达成“团队觉得合适”的结论,至少还应该遵循以下两个基本前提:

  • 业务独立性

首先,应该保证微服务是具有业务独立性的单元,并不能只是为了微而微。关于如何判断业务的独立性,也有不同的考量。譬如可以将某一个领域的模型作为独立的业务单元,譬如 订单、商品、财务、售后等;也可以将某业务行为作为独立的业务单元,譬如发送邮件、不同数据库之间的业务数据同步等。

  • 团队自主性

其次,考虑到团队的沟通及协作成本,一般不建议超过10个人。当团队超过10个人,在沟通、协作上的所耗费的成本会显著增加。当团队成员超过10个人的时候,可以考虑继续再划分子团队,让不同的子团队承担独立的工作。

微服务拆分过程中的坑

  • 微服务拆过细,过分强调“small”
  • 微服务基础设施不健全,忽略了“automated”
  • 微服务并不轻量级,规模大了后,“lightweight”不再适应


如何拆分?

对拆分依据的思考,实际上是在问:“服务的粒度如何界定”。
针对微服务拆分过细导致的问题,建议基于团队规模进行拆分,类似贝索斯在定义团队规模时提出的“两个披萨”理论(每个团队的人数不能多到两个Pizza都不够吃的地步)。
那么,以“三个火枪手”为原则的微服务拆分粒度,即一个微服务三个人负责开发。当我们在实施微服务架构时,根据团队的规模来划分微服务数量,如果业务规模继续发展,团队规模扩大,我们再将已有的微服务按这个原则拆分。
“三个火枪手”的原则主要应用于微服务设计和开发阶段,如果微服务经过一段时间发展后已经比较稳定,处于稳定期了,无需太多的开发,那么1个人维护1个微服务甚至几个微服务都可以。
拆分的思路

基于“三个火枪手”的理论,我们可以计算出拆分后合适的服务数量,但具体怎么拆分也是有技巧的,并不是快刀斩乱麻随便拆分成指定的数量就可以了。常见的拆分方式有如下几种,接下来我们一一介绍。
(1)基于业务逻辑拆分
将系统中的业务模块按照职责范围识别出来,每个单独的业务模块拆分为一个独立的服务。
(2)基于可扩展拆分
将系统中的业务模块按照稳定性进行排序,将已经成熟和改动不大的服务拆分为稳定服务,将经常变化和迭代的服务拆分为变动服务。刚开始,稳定的服务粒度可以粗一些,即使逻辑上没有强关联的服务,也可以放在同一个子系统中。例如,将“消息推送服务”和“升级服务”放在同一个子系统中。
这样拆分主要是为了提升项目快速迭代的效率,避免在开发的时候,不小心影响已有的成熟功能,引发了线上问题。
(3)基于可靠性拆分
将系统中的业务模块按照优先级排序,将可靠性要求高的核心服务和可靠性要求低的非核心服务拆分开来,然后重点保证核心服务的高可用。具体拆分的时候,核心服务可以是一个,也可以是多个,只要最终的服务数据满足“三个火枪手”的原则就可以。
这样拆分可以带来如下几个好处:

  • 避免非核心服务故障影响核心服务

  • 核心服务高可用方案可以更简单

核心服务的功能逻辑更加简单,存储的数据可能更少,用到的组件也会更少,设计高可用方案在大部分情况下要比不拆分要简单得多。

  • 能够降低高可用成本

    将核心服务拆分出来后,核心服务占用的机器、带宽等资源比不拆分要少得多。因此只针对核心服务做高可用方案,机器、带宽等成本比不拆分要节省较多。

    (4)基于性能拆分

基于性能拆分和基于性能拆分类似,将性能要求高或性能压力大的模块拆分出来,避免性能压力大的服务影响其它服务。
常见的拆分方式和具体的性能瓶颈有关,可以拆分Web服务、数据库、Cache等。
例如,电商的抢购,性能压力最大的入口的排队功能,可以将排队功能独立为一个服务。

以上几种拆分方式不是多选一,而是可以根据实际情况自由排列组合。

小结
服务拆分的目的是为了提高软件项目的可靠性、效率和可扩展性,以便更好地应对持续迭代的需求、支撑软件的增长。通过将大型应用程序拆分成小的、独立的部分,可以降低系统复杂度并提高整体质量。这种架构设计也有助于快速开发、测试和部署代码,从而提高开发团队的工作效率。
如果无法实现上述的目标,就需要重新考虑是否有必要进行服务拆分。


引用
https://martinfowler.com/articles/microservices.html
https://time.geekbang.org/column/intro/100006601?code=SWmCO2yChZKMsxvoZphPgPyr8SX0c6wLhHZBcxyOZFs%3D&source=app_share
《从零开始学架构 照着做,你也能成为架构师》
《微服务 架构与实践》
《聊聊“架构”》
https://www.bilibili.com/video/av71345202

https://mp.weixin.qq.com/s/f1sEprXHw1ciYljH5PP3yw

 

posted @ 2023-05-01 20:31  沧海一滴  阅读(74)  评论(0编辑  收藏  举报