一、没有服务化的架构和痛点
1、没有服务化的架构原型
-
没有服务化的常见互联网高可用架构图
-
用户端是浏览器或者
app
-
后端入口是高可用的
Nginx
集群,用于反向代理 -
中间核心是高可用的
web-server
集群,所有业务逻辑代码都集中于此处 -
后端存储是高可用的
DB
集群,所有业务数据都存储在此 -
web-server
层是通过DAO/ORM
等技术来访问数据库
-
2、没有服务化的架构痛点
-
【痛点一:代码到处拷贝】
最常见的业务案例:每个公司都有一个共享的用户资源中心,里面存储着客户的相关用户信息,然而,公司的产品线中的各个产品都有访问用户信息的产品需求,在没有用户服务之前,每个产品都需要自己封装获取共享用户中心信息的功能,也就是各个产品都需要重复或者复制之前产品获取用户信息的功能代码。
-
【痛点二:复杂性扩散】
上诉案例通过一段时间的运行,随着公司业务的不断壮大,系统的并发量开始上升,用户数据的访问数据库成为了瓶颈,需要加入缓存来降低数据库的读压力,于是架构中引入了缓存,由于没有统一的服务层,各个业务线都需要加入缓存逻辑,导致系统的复杂度增加。
-
用户数据的读请求
- 先读取
cache
,命中则返回 - 没有命中则读取数据库
- 保存到
cache
中再返回
- 先读取
-
用户数据的写请求
- 更新
cache
- 再写入数据库
- 更新
随着时间的推移,数据流再次海量上升。这样的场景就会被迫对用户数据库进行分库分表操作,这样以来,各个业务系统又得被迫改造和升级
-
这些复杂性是典型的 业务无关
的复杂性,业务系统要被动升级
-
【痛点三:SQL 质量没有保障,业务相互影响】
本质上
SQL
语句还是各个业务线拼装的,资深的工程师写出高质量的SQL
没啥问题,经验没有这么丰富的工程师可能会写出一些低效的SQL
,假如业务线A
写了一个全表扫描的SQL
,导致数据库的CPU
100%,影响的不只是一个业务线,而是所有的业务线都会受影响。 -
【痛点四:疯狂的 DB 耦合】
业务线不断访问用户中心数据的同时还会结合自己的业务访问自己的数据库,典型的是通过
join
关键字来对数据库进行连表操作,随着数据量的越来越大,业务线ABC
的数据库耦合度越来越大无法垂直拆分,久而久之必须使用大库或者进行一次大的版本迭代升级。 -
【痛点五:数据库复用与耦合】
如果业务量到达此处,我们还不对项目进行服务化的抽取,此时采用抽象数据库的方式是最能预先考虑和理解的方案。各个部门中商议并指派出一个团队或者一个人来对用户中心的操作进行统一的封装。然后打出成为一个
jar
包,提供给各个业务线使用,需要需求则由该作者独立维护并提升版本号。但是为之而来的就是,各个业务系统的升级,用户中心的独立模块需要迎合各个系统的业务逻辑,导致用户中心的模块不断升级,对各个系统的兼容就受到了一定的限制和考量。
二、服务化架构的演变和优点
1、演变服务化的框架原型
- 为解决上述案例的问题,引入了用户中心服务层
- 引入了
user-service
对业务线响应所用用户数据的存取,引入了用户服务层,统一对用户信息做操作。
- 引入了
2、演变服务化的框架优点
-
【优点一:方便调用方】
-
有服务层之前:业务方访问用户数据,都是通过业务系统本身的
DAO
拼装SQL
反问 -
有服务层之后:业务方通过
RPC
访问用户数据,就像调用本地函数一样的方便,屏蔽了获取用户数据的复杂逻辑,只关注业务系统本身的业务逻辑。
-
-
【优点二:高类聚,防止代码拷贝】
获取用户信息,统一交由用户服务来处理,代码只有一份,防止各个业务系统的拷贝和服用,降低业务代码的耦合度。
-
【优点三:专注性,屏蔽底层复杂度】
只有服务层需要专注关注底层的复杂性了,向上游屏蔽了细节。
-
【优点四:
SQL
质量得到保障】所有的
SQL
都是服务层提供的,业务线不能再为所欲为了。底层服务对于稳定性的要求更好的话,可以由更资深的工程师维护,而不是像原来SQL
难以收口,难以控制。 -
【优点五:数据库解耦】
底层的数据库被隔离开了,可以很方便的拆分出来,进行扩容。
-
【优点六:提供有限接口,无限性能】
服务只提供有限的通用接口,理论上服务集群能够提供无限性能,性能出现瓶颈,服务层一处集中优化。