WebRTC:匹配最近的对等节点

27

假设有一个公共IP地址(节点A),以及许多其他公共IP地址的列表(包括IPv4和IPv6地址),最简单的方法是什么,可以将节点A与最近的n个节点的IP地址匹配起来,而不必让这些节点手动相互ping来进行延迟基准测试?

我认为可以使用BGP和一些复杂的查询(也许涉及OSPF)来实现,但我希望能找到一个解决方案或库,使其像下面的理论函数调用一样容易。

// `peer` is a single IP address. `peer_list` is a list of IP addresses
// get the 5 nearest peers (ordered) to `peer` from `peer_list`
nearest_peers = get_nearest_ips(peer, peer_list, 5);

我应该只使用MaxMind的本地GeoIP数据库 + Haversine/Vincenty,还是使用带有适当缓存的库来通过BGP实现这一目标?

看起来这种代码可能存在于开源的任播路由实现中,尽管我还没有找到符合这个用例的任何内容。

解决方案或建议的库不必在node.js上工作 - 任何语言都可以。


我假设IP列表是外部IP地址。我会使用MaxMind的GeoIP数据库来获取每个IP的坐标,然后使用Haversine公式确定最短位置。可能瓶颈是来自MaxMind的响应时间(例如<400毫秒),但我还发现他们也出售GeoIP数据库以在本地主机上使用。https://www.maxmind.com/en/geoip2-databases - gogasca
@spicyramen 如果我无法在BGP中解决这个问题,那么本地MaxMind数据库就是我的备选方案。 - Eli Grey
3个回答

11

安装https://github.com/runk/node-maxmind

http://dev.maxmind.com/geoip/geoip2/geolite2/下载'GeoLite2-City.mmdb'

var maxmind = require('maxmind');
var lookup = maxmind.open('./GeoLite2-City.mmdb');

/**/
var peers = [
    '31.193.128.0', // UK
    '23.112.0.0', // USA
    '5.24.0.0', // Turkey
    '196.203.0.0', // Tunisia
    '77.243.64.0' // Malta
];

var peerLocations = {};

peers.forEach(function(peer) {

    var tmp = lookup.get(peer);

    if (!tmp || !tmp.location) {
        throw new Error('Unable to get initial peer location: ' + peer);
    }
    peerLocations[peer] = tmp.location;
});


/**/

var testIp = '84.17.64.0'; // Turkey
// 84.17.64.0   // Turkey
// 37.219.0.0   // Finland
// 5.39.0.0     // France
// 37.75.32.0   // Malta
// 5.2.96.0     // UK
// 15.0.0.0     // USA
// 41.224.0.0   // Tunisia

console.log( findClosestPeer(testIp, 3) );

function findClosestPeer(ip, len) {

    var ipData = lookup.get(ip);
    var distances = [];

    if (ipData && ipData.location) {

        Object.keys(peerLocations).forEach(function(key) {

            var peer = peerLocations[key];
            var distance = getDistanceFromLatLonInKM(ipData.location.latitude, ipData.location.longitude, 
                peer.latitude, peer.longitude);

            distances.push({ip: key, distance: distance});
        });
    }

    // 0 ... 9
    distances.sort(function(a, b) {
        return a.distance - b.distance;
    });

    return len > 1 ? distances.slice(0, len)
        : distances.shift();
}



/* https://dev59.com/bmEi5IYBdhLWcg3wb76O#21279990 */
function getDistanceFromLatLonInKM(lat1, lon1, lat2, lon2) {

    var R = 6371; // Radius of the earth in km

    var dLat = deg2rad(lat2 - lat1);  // deg2rad below
    var dLon = deg2rad(lon2 - lon1); 
    var a = 
        Math.sin(dLat/2) * Math.sin(dLat/2) +
        Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) * 
        Math.sin(dLon/2) * Math.sin(dLon/2)
    ;

    var c = 2 * Math.atan2( Math.sqrt(a), Math.sqrt(1 - a) ); 
    var d = R * c; // Distance in km

    return d;
}

function deg2rad(deg) {
    return deg * ( Math.PI / 180 );
}

7

据我所读,您的问题比您的Javascript/WebRTC用例要广泛得多。

关于这样的问题:“在P2P网络和知道所有连接对等方的中央服务器的情况下,可以使用哪种最佳度量来将它们配对?”

=> 用于配对两个任意节点的好度量是它们之间的跳数。问题在于这个值不可能计算出来(你只能猜测ISP路由器在节点之间选择哪条路径)。

那么如何近似它呢?

1. 使用地理距离作为跳跃距离的近似值

在这种情况下,您几乎完成了。使用任何“ip to latlng”服务即可完成。

2. 通过映射互联网来猜测实际跳数

我找到了一篇关于这个主题的论文,可能对您有用。您还可以挖掘一下他们的参考文献,以检索先前关于同一主题的论文:

估计任意主机对之间的跳数
摘要-建立清晰及时的互联网拓扑图是复杂的,因为基础设施规模庞大且动态。在本文中,我们描述了一种估计互联网拓扑图重要特征(任意端点对之间的跳数)的方法学。我们的目标是开发一种精确,可扩展,及时且不需要显著测量基础设施的成对跳数估计方法。我们的方法基于部署一小组地标节点,这些节点使用类似traceroute的探针相互之间建立准确的成对跳数。地标节点还配置为从被动监视的网络数据包流量中收集源IP地址和TTL值。我们开发了一种新颖的多维缩放算法,可应用于被动和主动测量来为所有观察到的源主机地址生成成对跳数估计。然后,通过BGP路由信息考虑源主机的自治系统成员身份来增强基本算法。我们使用一组合成网络拓扑研究了我们的估计算法的能力。结果表明,我们的方法可以在各种网络大小和配置,以及地标基础设施大小范围内生成高度准确的成对跳数估计。

谢谢你提供那篇论文的链接。这正是我所需要的! - Eli Grey

2
最简单的找到最近的节点的方法是向每个节点发送回声请求并测量获取响应所需的时间,就像ping一样。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接