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

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

1年前
388158
  • 背景:系统崩了
  • 具体情况:1%的请求影响了剩余90%的请求
  • 架构演进:拆分热点服务【进程级隔离】
  • 复盘
  • 总结
  • 拆服务的经典实践

背景
系统崩溃了?别惊慌!这里有快速恢复的方法!

分析发现崩时服务X被几个慢接口拖垮继而踩踏,且X的QPS过高,是业务gateway的2倍

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

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

当前流量流转概览

业务gateway的流量远小于服务x的流量???

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


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

请求等待了7707ms


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

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


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

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

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

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

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

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

在分享对拆分的思考之前,先聊几个概念热热场。

什么是架构?

软件架构是指软件系统的顶层结构,而架构设计的目的是为了解决软件复杂度。架构的思考来源于对生命周期的识别,以及对生命周期的拆分。如果没有生命周期拆分的思考,就不能算架构。

什么是微服务架构?
微服务架构是一种架构模式,它提倡将单一应用程序划分成一组小的服务,服务之间互相协调、互相配合,为用户提供最终价值。微服务架构的本质是分布式系统。
来看看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
《从零开始学架构 照着做,你也能成为架构师》
《微服务 架构与实践》
《聊聊“架构”》

 

点赞收藏
bit01
请先登录,查看5条精彩评论吧
快去登录吧,你将获得
  • 浏览更多精彩评论
  • 和开发者讨论交流,共同进步

为你推荐

API性能调优
8
5