简介
这个思想 和 分层那些事儿 很不一样,但又互为补充。
什么是服务化
那么,什么是“服务化”呢?服务化就像企业当中将相同岗位的人员划分到同一个部门管理,以此来收敛特定的工作入口,再进行二次分配,以提高人员利用率和劳动成果的复用度。服务化的本质是“分治”,而“分治”的前提是先要拆,然后才谈得上如何治。这时,高内聚、低耦合的思想在拆分过程中起到了一个非常重要的作用,因为这可以尽可能地降低拆分后不同组件间进行协作的复杂度。所以重要的是“怎么拆“,还有如何循序渐进地拆,而这个过程中你究竟是采用了何种服务化模式(比如 SOA、ESB、微服务等)并不是关键。 划重点:
- 服务化的价值:收敛特定的工作入口,再进行二次分配,以提高人员利用率和劳动成果的复用度
- 服务化的本质是“分治”
- “分治”的前提是先要拆,然后才谈得上如何治
- 怎么拆很重要,而服务化模式并不是关键
- 具体怎么拆?高内聚、低耦合的思想在拆分过程中起到了一个非常重要的作用
拆分,通过梳理、归类,将不同的紧密相关的部分收敛到一个独立的逻辑体中,这个逻辑体可以是函数、类以及命名空间
彼之砒霜,吾之蜜糖
假设,你要将一个总计 10000 名员工的企业按“职能型”拆分成 20 个部门,得到的结果是每个部门 500 人。这时,如果工作是流水线式的上下游关系。一个部门完工了再交给下一个部门。那么这时候是高内聚、低耦合的。因为一个工种只与另一个工种产生了关联,并且仅有一次。但如果工作需要频繁的由不同职能的人员同时进行,会导致同一个部门可能与多个部门产生联系。那么,这时是低内聚、高耦合的。因为一个工种需要和其他多个工种产生关联并且远不止一次。
可见,高内聚、低耦合 ,也是什么情况怎么说的。
提炼服务
大部分中间件都具备这样一个价值:为了在软件系统的迭代过程中,避免将精力过多地花费在某个子功能下众多差异不大的选项中。在现实中,这点更多时候出现在技术层面的中间件里。因为与业务相比,技术层面“稳定”多了,所以做标准化更有价值,更能获得长期收益。但“稳定”是相对的,哪怕单纯在业务层面也存在相对稳定的部分。
比如,你可以想象一下“盛饭”的场景,在大多数情况下其中相对稳定的是什么,不稳定的是什么。想完之后看下面的示例。
...
基类:人
继承基类的子类:男人、女人
基类:碗
继承基类的子类:大碗、小碗、汤碗
基类:勺子
继承基类的子类:铁勺、陶瓷勺、塑料勺
function 盛饭(参数 人,参数 碗,参数 勺子){
do 人拿起碗
do 人拿起勺子
do 人用勺子舀起饭
do 人把勺子放到碗的上方并倒下
}
...
从这个示例里我们发现,不稳定的部分都已经成为变量了,那么剩下的这个方法体起到的作用和前面提到的中间件是一样的,它标准化,标准化了盛饭的过程。所以识别相对稳定的部分是什么,如何把它们提炼出来,并且围绕这些点进行标准化,才是我们需要掌握的能力。而锻炼这个能力和需要这个能力的地方同样并不局限于分布式系统。
一个例子
笔者曾接到一个需求,产品希望一批特定的用户 和普通的用户看到不一样的数据。这批特定用户不确定,每次由数据团队提供用户列表。起初在实现上,我们在系统中加入了一个读取hdfs文件的模块,其加载hdfs 文件数据转换为一个bloomfilter,然后上层业务根据请求做一个判断就可以了。
后来我们发现
- 产品越来越欲求不满,他们希望这个文件可以定期自动更新,可以支持不同的格式
- 在其他的业务上也有类似的需求
于是我们萌生一个想法,定义一个专门的基础服务
- 用户指定hdfs 文件(或别的文件),指定更新机制
- 服务对外提供一个查询接口,
boolean contains(uid,hdfsId)
这样,类似于定时刷新、文件格式变动这类事情就可以放在专门的系统中,不用担心它们对业务系统产生影响,也算是“高内聚、低耦合”在架构设计上的体现。