一个 java 工程, 可能依赖多个其他的 java 服务,在进行发布的时候, 需要考虑依赖关系。
例如有 a~g, x~z 两组服务, 他们的依赖关系如下:
第一组:
x <-- y // x 依赖 y
z <-- y // z 依赖 y
第二组:
a <-- b //a 依赖 b
c <-- b // c 依赖 b
b <-- e, f // b 依赖 e, f 两个服务。下面的服务关系类同, 不再写注释了。
g <-- b
a <-- e
最终排序为:
第一组:
y, [x, z] // y 是第一批次。x 和 z 都属于第二批次,xz 不分先后
第二组:
[e, f], b , [a, c, g] // e, f 属于第一批次,b 属于第二批次,a,c,g 属于第三批次
如何用 python 程序表达排序的逻辑呢?
from functools import reduce as _reduce
class CircularDependencyError(ValueError):
def __init__(self, data):
s = "Circular dependencies exist among these items: {{{}}}".format(
", ".join(
"{!r}:{!r}".format(key, value) for key, value in sorted(data.items())
)
)
super(CircularDependencyError, self).__init__(s)
self.data = data
def toposort(data):
if len(data) == 0:
return
# Copy the input so as to leave it unmodified.
data = data.copy()
# Ignore self dependencies.
for k, v in data.items():
v.discard(k)
# Find all items that don't depend on anything.
extra_items_in_deps = _reduce(set.union, data.values()) - set(data.keys())
# Add empty dependences where needed.
data.update({item: set() for item in extra_items_in_deps})
while True:
ordered = set(item for item, dep in data.items() if len(dep) == 0)
if not ordered:
break
yield ordered
data = {
item: (dep - ordered) for item, dep in data.items() if item not in ordered
}
if len(data) != 0:
raise CircularDependencyError(data)
if __name__ == "__main__":
group1 = {"A": {"B", "E"}, "C": {"B"}, "B": {"E", "F"}, "G": {"B"}}
print(list(toposort(group1)))
group2 = {"X": {"Y"}, "Z": {"Y"}}
print(list(toposort(group2)))
# 如果一开始给的数据, 是group1和2合并在一起的
# 如何把数据分成两个组, 并且分别做拓扑排序
init_data = {**group1, **group2}
print(list(toposort(init_data)))
1
joApioVVx4M4X6Rf 2020-09-23 18:32:55 +08:00
是一个树状结构的话, 直接可以遍历树,按层次启动服务。如果要是图结构,就比较麻烦了
|
2
momocraft 2020-09-23 18:36:19 +08:00
"拓扑排序"
|
3
lithbitren 2020-09-23 20:43:11 +08:00
说起来,3.9 标准库好像有拓扑排序了
|
4
Leigg 2020-09-23 21:00:55 +08:00 via Android
你这都快成环形依赖了,完全是设计问题
|
5
Leigg 2020-09-23 21:04:58 +08:00 via Android
没仔细看,排序的目的是啥呢?
|
6
jasonqiao36 OP @Leigg #5 服务发布的时候, 有依赖关系, 所以要给服务进行排序
|