用图数据结构返回服务调用关系

需求

我做的运维监控系统,服务与服务之间是有调用关系的,如果A服务调用B服务,B服务的健康状态影响A服务,这时候就需要找到影响A服务的所有服务。

代码

我想服务与服务调用就形成了一张图,但是服务调用服务不可以有环,因为依赖的是最终的服务状态。

这样我让AI生成了代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import java.util.*;

public class Graph {
private Map<String, List<String>> adjList;

public Graph() {
adjList = new HashMap<>();
}

public Map<String, List<String>> getAdjList() {
return adjList;
}

// 添加有向边
public void addEdge(String source, String target) {
adjList.computeIfAbsent(source, k -> new ArrayList<>()).add(target);
}

// 获取节点的邻居
public List<String> getNeighbors(String node) {
return adjList.getOrDefault(node, Collections.emptyList());
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
import java.util.*;

public class Visitor {
private boolean hasCycle;
private Set<String> visited;
private Set<String> recStack;
private List<String> dependencies;

public Visitor() {
hasCycle = false;
visited = new HashSet<>();
recStack = new HashSet<>();
dependencies = new ArrayList<>();
}

public boolean hasCycle() {
return hasCycle;
}

public List<String> getDependencies() {
return dependencies;
}

// 开始访问图
public void visit(Graph graph) {
for (String node : graph.getAdjList().keySet()) {
if (!visited.contains(node)) {
dfs(graph, node);
}
}
}

// 深度优先搜索
private void dfs(Graph graph, String node) {
visited.add(node);
recStack.add(node);
dependencies.add(node);

for (String neighbor : graph.getNeighbors(node)) {
if (!visited.contains(neighbor)) {
dfs(graph, neighbor);
} else if (recStack.contains(neighbor)) {
hasCycle = true;
}
}

recStack.remove(node);
}

// 传入一个节点,返回其依赖的节点
public List<String> getDependenciesForNode(Graph graph, String startNode) {
if (hasCycle) {
throw new IllegalStateException("图中存在环,无法准确计算依赖节点。");
}
visited.clear();
dependencies.clear();
dfsForNode(graph, startNode);
dependencies.remove(startNode); // 移除起始节点本身
return dependencies;
}

private void dfsForNode(Graph graph, String node) {
visited.add(node);
for (String neighbor : graph.getNeighbors(node)) {
if (!visited.contains(neighbor)) {
dependencies.add(neighbor);
dfsForNode(graph, neighbor);
}
}
}

public static void main(String[] args) {
Graph graph = new Graph();
graph.addEdge("A", "B");
graph.addEdge("B", "C");
graph.addEdge("A", "D");

Visitor visitor = new Visitor();
visitor.visit(graph);

if (!visitor.hasCycle()) {
String targetNode = "A";
List<String> dependencies = visitor.getDependenciesForNode(graph, targetNode);
System.out.println("节点 " + targetNode + " 的依赖节点: " + dependencies);
} else {
System.out.println("图中存在环,无法计算依赖节点。");
}
}

}

我先判断有没有环,如果有环就不再计算了,如果没有环获取影响startNode的节点,我在程序中查找这些服务是否完成计算,如果完成再计算startNode服务的健康状态。


用图数据结构返回服务调用关系
http://hanqichuan.com/2025/03/11/算法与数据结构/用图数据结构返回服务调用关系/
作者
韩启川
发布于
2025年3月11日
许可协议