Page 154 - 《软件学报》2020年第11期
P. 154
3470 Journal of Software 软件学报 Vol.31, No.11, November 2020
强的聚类特性.遍历社区结构树的每一层,计算对应划分方案 P x 的模块度,作为推荐方案的一个指标参数
Score Modularity (P x ).整个数据表图的聚类划分过程如图 7 和算法 1 所示(图 7 展示了实验系统 JeeSite 中 22 张数据
表的真实聚类过程对应的社区结构树和模块度计算结果,每个数字代表一张数据表,一个方框中的所有表对应
于一个服务,其中的虚线标明了模块度最高的拆分方案).
算法 1. 数据表图聚类算法.
输入:数据表图的邻接矩阵 M.
输出:数据表图的社区结构树和每一层对应的模块度.
1: function Cluster(M)
2: 根据邻接矩阵 M 构建图 G,G.v 为图的点集,G.e 为图的边集
3: maxModularity //记录最大模块度
4: maxBetweenness //记录最大边介数
5: Map〈Modularity,Partition〉 partitionMap //保存模块度和对应的划分结果
6: while G.e≠∅
7: for edge in G.e
8: 计算 edge 的边介数 edge.betweenness
9: maxBetweenness=Max{maxBetweenness,edge.betweenness}
10: end for
11: for edge in G.e
12: if edge.betweenness==maxBetweenness
13: remove edge from G.e //删除边介数等于最大边介数的边
14: end if
15: end for
16: 获取图 G 当前的划分结果 P current
17: 计算 P current 的模块度 Score Modularity (P current )
18: maxModularity=Max{maxModularity,Score Modularity (P current) }
19: partitionMap.put(curModularity,curPartition)
20: end while
21: return partitionMap
2.2.4 计算拆分开销
给定一个数据表划分方案 P i ,可以依据原单体系统的静态代码结构,从 SQL 语句、方法、类这 3 个层面自
底向上进行拆分开销的计算.如果一条 SQL 语句操作的若干个数据表归属于两个及以上不同的微服务,则该条
SQL 语句需要进行拆分.一条 SQL 的拆分代价定义为μ 1 ,需要拆分的 SQL 总数定义为 V SQL (P i ).同理,如果一个方
法包含的 SQL 语句需要拆分或者该方法包含了两条属于不同微服务的 SQL 语句,那么它也需要进行拆分,对应
的拆分代价定义为μ 2 ,需要拆分的方法总数定义为 V Method (P i ).最后,除非一个类中所有方法都属于同一个微服
务,否则需要进行类的拆分,拆分代价定义为μ 3 ,需要拆分的类的总数定义为 V Class (P i ).拆分总开销 Cost(P i )通过
式(16)计算.
Cost(P i )=μ 1 ⋅V SQL (P i )+μ 2 ⋅V Method (P i )+μ 3 ⋅V Class (P i ) (16)
其中,μ 1 =1,μ 2 =0.5,μ 3 =0.1.
假设数据表图划分过程共产生了 K 种不同粒度的划分方案,给每个方案的拆分开销按式(17)打分.
Max{Cost (),P i = 1,..., }K − Cost ()P
Score = i i (17)
( ),i =
( ),i =
K −
Cost () i P Max{Cost P 1,..., } Min{Cost P 1,..., }
K
i i
由于最终的推荐方案倾向于减小拆分开销,所以将所有方案拆分开销的最大值与最小值之差作为分母,将