博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
微服务架构下的服务关联图
阅读量:7042 次
发布时间:2019-06-28

本文共 8914 字,大约阅读时间需要 29 分钟。

hot3.png

在微服务架构下,服务之间的关系是非常复杂的,是一个典型的有向有环图,在一个中等规模的项目中,一般会有100多个服务,而大型项目中,则会有数百个服务。

假设我们有如下6个服务:

0f976c30b78c9690cef68609c150fd0f9a3.jpg

每个服务都指定了自己依赖的服务:

AaaSvc:

e0b46105b93ef4136fff6cba3f456041f35.jpg

BbbSvc:

0cd5ade65f10aa1724c894532a77de84a93.jpg

CccSvc:

52ee7c226cb5fd609115e21f7dd434490c1.jpg

DddSvc:

6d9f779eeb1230b2855f4d5675e53afecad.jpg

EeeSvc:

457bf384a99a43b7719a98219d8f0273a6b.jpg

FffSvc:

ceb9104e1b9efa5b1c9274bc0aca278d217.jpg

我们如何把如上6个服务中跟服务AaaSvc相关的服务可视化呢?如下图所示:

8bd778d2f49f17a33e31a38fba800498ac7.jpg

要完成这样的服务关联图,需要如下几个步骤:

1、遍历指定项目下的所有服务,构造两个map,serviceToServiceMap 和 reverseServiceToServiceMap,存储所有服务的直接依赖和反向直接依赖。

public static void runService(String projectId,                            Map
> serviceToServiceMap, Map
> reverseServiceToServiceMap){ if(! (serviceToServiceMap instanceof ConcurrentHashMap) ){ throw new RuntimeException("参数serviceToServiceMap必须是ConcurrentHashMap的实例"); } if(! (reverseServiceToServiceMap instanceof ConcurrentHashMap) ){ throw new RuntimeException("参数reverseServiceToServiceMap必须是ConcurrentHashMap的实例"); } MetaServiceRepository metaServiceRepository = SpringContextUtils.getBean("metaServiceRepository"); List
services = metaServiceRepository.findByProjectId(projectId); services.parallelStream().filter(item->!item.getName().contains("Deprecate")).forEach(item->{ List
dependencyServices = item.constructDependencyServices(); String key = item.getName()+"("+item.getDescription()+")"; if(dependencyServices != null){ dependencyServices.parallelStream().filter(dep->!dep.getName().contains("Deprecate")).forEach(dependencyService->{ String value = dependencyService.getName()+"("+dependencyService.getDescription()+")"; serviceToServiceMap.putIfAbsent(key, Collections.newSetFromMap(new ConcurrentHashMap<>())); serviceToServiceMap.get(key).add(value); reverseServiceToServiceMap.putIfAbsent(value, Collections.newSetFromMap(new ConcurrentHashMap<>())); reverseServiceToServiceMap.get(value).add(key); }); } }); }

2、以服务AaaSvc为入口,利用直接依赖和反向直接依赖,构造服务依赖图和反向服务依赖图。

String name = metaService.getName()+"("+metaService.getDescription()+")";Set
set = serviceToServiceMap.get(name);ServiceDependencyGraph serviceDependencyGraph = new ServiceDependencyGraph(new HashMap<>(), name, set, serviceToServiceMap);set = reverseServiceToServiceMap.get(name);ServiceDependencyGraph reverseServiceDependencyGraph = new ServiceDependencyGraph(new HashMap<>(), name, set, reverseServiceToServiceMap);
import org.apache.commons.collections4.CollectionUtils;import java.util.ArrayList;import java.util.List;import java.util.Map;import java.util.Set;import java.util.concurrent.atomic.AtomicInteger;/** * 服务依赖图 * @date 2017-09-2 * @author 杨尚川 */public class ServiceDependencyGraph {    private String name;    private List
children = new ArrayList<>(); public ServiceDependencyGraph(Map
stopServiceNames, String name, Set
set, Map
> serviceToServiceMap){ this.name = name; if(CollectionUtils.isNotEmpty(set)) { for (String item : set) { String key = name+"_"+item; stopServiceNames.putIfAbsent(key, new AtomicInteger()); stopServiceNames.get(key).incrementAndGet(); if(stopServiceNames.get(key).get()<10) { Set
sub = serviceToServiceMap.get(item); ServiceDependencyGraph serviceDependencyGraph = new ServiceDependencyGraph(stopServiceNames, item, sub, serviceToServiceMap); children.add(serviceDependencyGraph); } } } } public String getName() { return name; } public void setName(String name) { this.name = name; } public List
getChildren() { return children; }}

3、利用服务依赖图和反向服务依赖图,构造带有点和边描述信息的JSON结构:

List
> nodes = new ArrayList<>();addNode(serviceDependencyGraph, nodes);addNode(reverseServiceDependencyGraph, nodes);List
> edges = new ArrayList<>();addEdge(reverseServiceToServiceMap, serviceDependencyGraph, edges, false);addEdge(reverseServiceToServiceMap, reverseServiceDependencyGraph, edges, true);Map
graph = new HashMap<>();graph.put("edges", edges);graph.put("nodes", nodes);
private void addNode(String node, List
> nodes){ for(Map
item : nodes){ if(node.equals(item.get("id"))){ return; } } Map
nodeMap = new HashMap<>(); nodeMap.put("id", node); nodeMap.put("name", node); nodes.add(nodeMap);}private void addNode(ServiceDependencyGraph serviceDependencyGraph, List
> nodes){ if(serviceDependencyGraph == null){ return; } String node = serviceDependencyGraph.getName(); addNode(node, nodes); if(serviceDependencyGraph.getChildren() != null){ serviceDependencyGraph.getChildren().forEach(item->addNode(item, nodes)); }}private void addEdge(Map
> reverseServiceToServiceMap, ServiceDependencyGraph serviceDependencyGraph, List
> edges, boolean reverse){ if(serviceDependencyGraph == null){ return; } String source = serviceDependencyGraph.getName(); serviceDependencyGraph.getChildren().forEach(target -> { boolean duplicate = false; Map
map = new HashMap<>(); if(reverse){ String id = target.getName()+"-->"+source; for(Map
item : edges){ if(id.equals(item.get("id"))){ duplicate = true; } } map.put("id", id); map.put("target", source); map.put("source", target.getName()); map.put("directed", true); map.put("source_score", reverseServiceToServiceMap.get(target.getName()) == null ? 0 : reverseServiceToServiceMap.get(target.getName()).size()); map.put("target_score", reverseServiceToServiceMap.get(source) == null ? 0 : reverseServiceToServiceMap.get(source).size()); }else { String id = source+"-->"+target.getName(); for(Map
item : edges){ if(id.equals(item.get("id"))){ duplicate = true; } } map.put("id", id); map.put("source", source); map.put("target", target.getName()); map.put("directed", true); map.put("source_score", reverseServiceToServiceMap.get(source) == null ? 0 : reverseServiceToServiceMap.get(source).size()); map.put("target_score", reverseServiceToServiceMap.get(target.getName()) == null ? 0 : reverseServiceToServiceMap.get(target.getName()).size()); } if(!duplicate) { edges.add(map); } addEdge(reverseServiceToServiceMap, target, edges, reverse); });}

生成的JSON结构如下所示:

{    "nodes":[        {            "globalWeight":4,            "name":"AaaSvc(服务Aaa)"        },        {            "globalWeight":4,            "name":"CccSvc(服务Ccc)"        },        {            "globalWeight":5,            "name":"DddSvc(服务Ddd)"        },        {            "globalWeight":4,            "name":"EeeSvc(服务Eee)"        },        {            "globalWeight":4,            "name":"FffSvc(服务Fff)"        },        {            "globalWeight":3,            "name":"BbbSvc(服务Bbb)"        }    ],    "edges":[        {            "distance":8,            "source":0,            "target":1        },        {            "distance":8,            "source":1,            "target":0        },        {            "distance":9,            "source":0,            "target":2        },        {            "distance":9,            "source":2,            "target":3        },        {            "distance":9,            "source":3,            "target":2        },        {            "distance":9,            "source":2,            "target":4        },        {            "distance":8,            "source":4,            "target":3        },        {            "distance":8,            "source":3,            "target":4        },        {            "distance":9,            "source":4,            "target":2        },        {            "distance":7,            "source":0,            "target":5        },        {            "distance":7,            "source":5,            "target":1        },        {            "distance":7,            "source":1,            "target":5        }    ]}

4、使用d3-force对如上的JSON进行展示:

    
测试项目_testDemo -- 服务Aaa_AaaSvc -- 服务关联图

测试项目_testDemo -- 服务Aaa_AaaSvc -- 服务关联图

重力调节 最短边长 边长放大倍数 最短半径 半径放大倍数 箭头大小

最终运行的效果如下:

7fa4d61151add93130eba39a0ae62f702fb.jpg

 

 

转载于:https://my.oschina.net/apdplat/blog/2218945

你可能感兴趣的文章
java swing awt初级入门
查看>>
Ubuntu闪电入门第一弹
查看>>
swift语言--输入输出参数
查看>>
php小代码(1)
查看>>
Java面试宝典(5)算法
查看>>
android suport respository和Android Support Library
查看>>
ubuntu16.04 配置DOCKER_OPS
查看>>
Cisco技术区常用配置实例整理(1)
查看>>
DirectionGUI
查看>>
Android用户体验毁在框架设计?
查看>>
JavaScript中一些常用API使用方法简析
查看>>
Android Google Map API使用的八个步骤
查看>>
ISA server 限制访问和开放内部资源及系统维护
查看>>
javascript计算前1!+2!+...+n!的阶乘和
查看>>
SCOM2012–Part3 如何监控群集
查看>>
我的友情链接
查看>>
Ruby+watir 自动化测试
查看>>
我的Python学习记录-python初次接触
查看>>
太骄傲
查看>>
邮件群发为外贸企业赢得国际市场
查看>>