人们使用Neo4j来管理企业架构。如果你还没有看到该演讲由托马斯·劳伦斯来自Amadeus的,那么你应该为自己观看。但是低层网络呢?我们可以使用Neo4j来建模物理网络中的路由吗?当然我们可以,今天我会告诉你如何。
我们将保持简单,只需要路由器,交换机,接口和服务器。路由器之间将具有“ROUTE_TO”关系。该关系将路由表包含为String Array。例如:[“10.175.112.0/20”,“10.175.108.0/22”,“10.175.112.0/20”,“10.182.14.64 / 26”...]。路由器与Interfaces之间也有“TRANSLATES_TO”关系(例如VLAN)具有ip和mac地址属性。接口与具有mac和port属性的交换机之间将具有“CONNECTS_TO”关系。最后,交换机还将具有与具有mac和port属性的服务器的“CONNECTS_TO”关系。服务器,如路由器,将具有IP地址属性。也许这张图片将有助于理解这一点:
在本练习中,让我们从一个ip为“10.175.64.2”的路由器开始,看看如何通过ip为“10.175.122.10”来访问服务器。这是我们网络的一部分图片:
我们将创建一个存储过程,通过查找我们的路由器和服务器开始。然后,我们将使用Traversal API创建TraversalDescription,它将深度探索图形,使用NetworkExpander扩展,我们将在下面讨论,并评估它遍历的路径,直到找到服务器节点。假设我们找到一些路径,我们将返回它们作为结果:
@Procedure(名称 = “com.maxdemarzi.router” ,模式 = 模式。READ)
@Description(“CALL com.maxdemarzi.router(from,to) - 遍历路径”)
public Stream < PathResult > router(@Name(“from”)String from,@ Name(“to”)String to){
节点 路由器 = db。findNode(标签。路由器,“ip”,来自);
节点 服务器 = db。findNode(标签。服务器,“ip”,to);
if(router != null && server != null){
TraversalDescription td = db。遍历描述()
。depthFirst()
。expand(新的 NetworkExpander(to))
。评估(评估者。endNodeIs(评估。INCLUDE_AND_PRUNE,
评价。EXCLUDE_AND_CONTINUE,server));
返回 td。遍历(路由器)。iterator()。stream()。map(PathResult :: new);
}
返回 流。of(new PathResult(null));
}
棘手的部分是NetworkExpander,所以我们来看看吧。它的构造函数要求我们传入我们想要访问的IP地址,并将它们保存为String和IPAddress。
公共 类 NetworkExpander 实现 PathExpander < 字符串> {
private String ip ;
私有 IPAddress ipAddress ;
public NetworkExpander(String ip){
这个。ip = ip ;
这个。ipAddress = new IPAddressString(ip)。getAddress();
}
在我们的扩展器中,我们将首先通过查看ROUTES_TO关系来尝试第3层路由,并查看String Array routes属性中的任何条目是否包含我们要查找的IP地址,并选择具有较长前缀的IP地址。例如,如果我们遇到3个ROUTES_TO关系,每个关系都有一个路由表条目:
192.168。32.0 / 26 ROUTES_TO 10.1。1.1
192.168。32.0 / 24 ROUTES_TO 10.1。1.2
192.168。32.0 / 19 ROUTES_TO 10.1。1.3
......我们希望得到“192.168.32.1”,我们将所有3个关系添加到我们的无序路由中,但是在订购时,我们首先尝试将关系转到“10.1.1.1”,因为包含“192.168.32.1”在192.168.32.0/26网络(192.168.32.0到192.168.32.63)内,并且具有更长的前缀(26)。
如果我们想要“192.168.32.100”,我们将跳过第一个关系“192.168.32.0/26”,因为x.100不包括在0-63的范围内。其他两个关系是有效的,因为“192.168.32.0/24”包括192.168.32.0到192.168.32.255而“192.168.32.0/19”包括192.168.32.1到192.168.63.254,但我们先尝试“10.1.1.2”因为它有更长的前缀(24)。我来告诉你代码:
@覆盖
public Iterable < Relationship > expand(Path path,BranchState branchState){
节点 last = 路径。endNode();
ArrayList < Relationship > relationships = new ArrayList <>();
ArrayList < Pair < Integer,Relationship >> unorderedRoutes = new ArrayList <>();
//第3层最长前缀匹配
为(关系 routes_to:最后。getRelationships(关系类型。ROUTES_TO,方向。OUTGOING)){
String [] routes =(String [])routes_to。getProperty(“routes”,new String [] {});
for(String route:routes){
IPAddressString addrString = new IPAddressString(route);
如果(addrString。的getAddress()。包含(ip地址)){
无序路线。添加(对。的(addrString。getNetworkPrefixLength(),routes_to));
}
}
}
无序路线。排序(比较。comparingInt(p - > - p。第一()));
无序路线。的forEach(p - > 关系。添加(p。等()));
现在你可能会问自己,“IPAddressString和IPAddress来自哪里?” 它们来自Sean C. Foley的IPAddress库。如果您想自己动手,这个StackOverflow帖子可能是一个很好的起点。
一旦我们希望到达应该引导我们到服务器的路由器,我们就转到第2层。在这里,我们遍历TRANSLATES_TO关系,导致我们的IP地址,转换为mac地址,并继续我们的遍历。我们遵循具有相同mac地址的CONNECTS_TO关系,直到我们到达目的地。再一次,这是代码:
//如果没有第3层下一跳,请转到第2层
如果(关系。的isEmpty()){
//第2层
为(关系 translates_to:最后。getRelationships(关系类型。TRANSLATES_TO,方向。OUTGOING)){
String ip =(String)translates_to。getProperty(“ip”);
如果(IP。等于(此。IP)){
关系。add(translates_to);
}
}
String mac = “” ;
关系 lastRel = 路径。lastRelationship();
if(lastRel != null){
mac =(String)lastRel。getProperty(“mac”,“”);
}
为(关系 connects_to:最后。getRelationships(关系类型。CONNECTS_TO,方向。OUTGOING)){
串 mac_too =(字符串)connects_to。getProperty(“mac”,“”);
如果(MAC。等于(mac_too)){
关系。add(connects_to);
}
}
}
回归 关系 ;
项目存储库中的README文件包含用于构建小型网络的密码脚本。在我们构建网络之后,我们可以尝试我们的存储过程,例如:
CALL com 。maxdemarzi 。router ('10 .175.64.2' , '10 .175.122.10' )
......这将是我们的结果。
如果您看到的关系多于此,请确保转到Neo4j浏览器“设置”(单击侧面板上的齿轮),完全向下滚动,取消选中“连接结果节点”,然后重新运行存储过程。
与往常一样,代码在GitHub上,所以请随意尝试。此模型中的路由表是一个简单的字符串列表,但在更真实的场景中,每个条目可能是路由器之间的关系,优先级,权重和其他元属性会影响路由顺序,但是概念是一样的。
标签:关系,String,ip,网络,192.168,mac,Neo4j,路由,路由器 From: https://blog.51cto.com/u_16145034/6486213