之前讲解了什么是微服务:微服务的核心在于服务治理,微服务架构是将复杂臃肿的单体应用进行细粒度的服务化拆分,每个拆分出来的服务各自独立打包部署,并交由小团队进行开发和运维,从而极大地提高了应用交付的效率。
什么时候进行服务化拆分?拆分单体应用有哪些标准呢?
什么时候进行服务化拆分?
比如做社交 App,初期为了快速上线,验证可行性,可以只开发首页信息流、评论等基本功能。产品上线后,经过一段时间的运营,用户开始逐步增多,可行性验证通过,下一阶段就需要进一步增加更多的新特性来吸引更多的目标用户,比如再给这个社交 App 添加个人主页显示、消息通知等功能。
这个时候就需要大规模地扩张开发人员,以支撑多个功能的开发。如果这个时候继续采用单体应用架构,多个功能模块混杂在一起开发、测试和部署的话,就会导致不同功能之间相互影响,一次打包部署需要所有的功能都测试 OK 才能上线。而且,多个功能模块混部在一起,对线上服务的稳定性也是个巨大的挑战。
再例举一个 58 到家的例子,随着业务越来越复杂,数据量越来越大,并发量越来越大,15 年的时候,58 到家的架构碰到了种种问题:
- 垂直业务扩展,家政、丽人、速运、平台,一些相似的业务代码拷贝越来越严重
- 数据量、并发量提升,底层架构复杂性不断向上游扩散,所有调用方都需要关注缓存、分库、存储引擎等,效率逐步降低
- jar 包耦合,多个系统依赖一个公用的 jar 包,一个业务升级导致兼容性问题,影响其他业务
- 数据库耦合,多个业务公用一个数据库,相互耦合,相互影响
- SQL 质量低,业务相互耦合,一个业务编写了一个低质量的 SQL,导致其他业务受影响
这个时候 58 到家开始进行服务化拆分,找到通用痛点,抽象出通用数据访问与子业务,然后将它们下沉成微服务。
一般来说,一旦单体应用同时进行开发的人员超过 10 人,就会遇到上面的问题,这个时候就该考虑进行服务化拆分了。
服务化拆分的两种姿势
那么服务化拆分具体该如何实施呢?一个最有效的手段就是将不同的功能模块服务化,独立部署和运维。以前面提到的社交 App 为例,可以认为首页信息流是一个服务,评论是一个服务,消息通知是一个服务,个人主页也是一个服务。
这种服务化拆分方式是纵向拆分,是从业务维度进行拆分。标准是按照业务的关联程度来决定,关联比较密切的业务适合拆分为一个微服务,而功能相对比较独立的业务适合单独拆分为一个微服务。
还有一种服务化拆分方式是横向拆分,是从公共且独立功能维度拆分。标准是按照是否有公共的被多个其他服务调用,且依赖的资源独立不与其他业务耦合。
以前面的社交 App 为例,无论是首页信息流、评论、消息箱还是个人主页,都需要显示用户的昵称。如果把用户的昵称功能单独部署成一个独立的服务,那么有什么变更我只需要上线这个服务即可,其他服务不受影响,开发和上线成本就大大降低了。
服务化拆分的前置条件
一般情况下,业务系统引入新技术就必然会带来架构的复杂度提升,在具体决策前,先要认识到新架构会带来哪些新的问题,这些问题你和你的团队是否能够解决?如何解决?是自己投入人力建设,还是采用业界开源方案?
下面几个问题,是从单体应用迁移到微服务架构时必将面临也必须解决的。
-
服务如何定义:对于单体应用来说,不同功能模块之前相互交互时,通常是以类库的方式来提供各个模块的功能。对于微服务来说,每个服务都运行在各自的进程之中,通过接口向外界传达信息。无论采用哪种通讯协议,是 HTTP 还是 RPC,服务之间的调用都通过接口描述来约定,约定内容包括接口名、接口参数以及接口返回值。
-
服务如何发布和订阅:单体应用由于部署在同一个 WAR 包里,接口之间的调用属于进程内的调用。而拆分为微服务独立部署后,就需要一个能够记录每个服务提供者的地址以供服务调用者查询,也就是注册中心(如 Zookeeper、Eureka、Consul 等)。
-
服务如何监控:对于一个服务,需要一种通用的监控方案,能够覆盖业务埋点、数据收集、数据处理,最后到数据展示的全链路功能。
-
服务如何治理:拆分为微服务后,服务的数量变多,依赖关系变复杂。比如一个服务的性能有问题时,依赖的服务也会受影响。可以设定一个调用性能阈值,如果一段时间内一直超过阈值,那么依赖服务的调用可以直接返回,也就是熔断。
-
故障如何定位:拆分为微服务后,一次用户调用可能依赖多个服务,每个服务又部署在不同的节点上,如果用户调用出现问题,需要一种解决方案能够将一次用户请求进行标记,并在多个依赖的服务系统中继续传递,以便串联所有路径,从而进行故障定位。
针对上述问题,必须有可行的解决方案之后,才能进行服务化拆分。
总结
无论是纵向拆分还是横向拆分,都是将单体应用庞杂的功能进行拆分,抽离成单独的服务部署。
但并不是功能拆分的越细越好,过度的拆分反而会让服务数量膨胀变得难以管理,因此找到符合自己业务现状和团队人员技术水平的拆分粒度才是可取的。
参考