2017-10-06 97 views
0

我使用IP地址传入数据流。我想在将数据放入我的数据库之前将IP翻译为经度和纬度。使用IP地址流式传输数据的node-maxmind用法

这就是我正在做的,但它造成了一些问题。我也尝试把forObject放在for循环之外。奇怪的是,它使用了大量的内存。我知道这是阻止代码,但它应该是快速的。虽然我看到内存问题,因为数据对象来自流连续不断,每个数据对象是巨大的。

for (var i ==0; i < data.length; i++){ 
     if (data.client_ip !== null) { 
      var locationLookup = maxmind.openSync('./GeoIP2-City.mmdb'); 
      var ip = data.client_ip; 
      var maxmindObj = locationLookup.get(ip); 
      locationObject.country = maxmindObj.country.names.en; 
      locationObject.latitude = maxmindObj.location.latitude; 
      locationObject.longitude = maxmindObj.location.longitude; 
      } 
} 

再次试图把maxmind.openSync( './ GeoIP2-City.mmdb');外部循环引起内存的巨大增加。

另一种选择是使用非阻塞代码

maxmind.open('/path/to/GeoLite2-City.mmdb', (err, cityLookup) => { 
    var city = cityLookup.get('66.6.44.4'); 
}); 

但我不认为这是一个很好的DEA把这个循环中。

我该如何处理?我得到的数据对象的每一分钟

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

回答

1

我不知道为什么你认为阅读对于循环的每个迭代的数据库文件将是快速(“堵代码”不等于“快速代码” ),一次读取数据库文件然后在data上循环会更好。

maxmind.openSync()将读取整个数据库到内存中,这是在README提到:

小心同步版本!由于mmdb文件相当大 (城市数据库大约为100Mb)fs.readFileSync在将文件读入缓冲区的过程中将整个程序块整个处理为 。

如果您没有内存可用,唯一的其他选择是异步打开文件。再次,不在循环内,但在其外面:

maxmind.open("./GeoIP2-City.mmdb", (err, locationLookup) => { 
    for (var i = 0; i < data.length; i++) { 
    if (data.client_ip !== null) { 
     var ip = data.client_ip; 
     var maxmindObj = locationLookup.get(ip); 
     locationObject.country = maxmindObj.country.names.en; 
     locationObject.latitude = maxmindObj.location.latitude; 
     locationObject.longitude = maxmindObj.location.longitude; 
    } 
    } 
}); 
+0

我明白你在暗示什么。对我来说这个问题是我有多次调用这个函数。我以非常高的速度获取数据对象(每分钟数据流)。每次接收到数据对象时,我都会解析循环中的所有字段,包括IP。这意味着每次都会打开该文件。有没有其他的方式来查询maxmind而不使用该文件? maxmind.openSync()会将整个数据库读入内存。我的实例有100mb,但问题是当我使用pm2运行它时,内存不断增加。不确定GC是否运行清理 –

+0

无论您选择哪种解决方案,您都应该打开/读取数据库一次。如果该函数被调用了很多,并且想要异步打开该数据库文件,则应该在函数之外打开它。这取决于您的应用程序结构是什么最佳解决方案。 – robertklep

+0

好的。非常感谢。让我做一些试验和测试。监视内存等,并回到你的结果 –

0

我唯一担心的是随着时间的推移,我将这个函数调用了很多次。每次我的消费者从kakfa读取jsonObject(每分钟发生一次)。有没有更好的方法来优化。所以我每分钟都会调用这个函数。我怎样才能更好地进一步优化这个

function processData(jsonObject) { 
    maxmind.open('./GeoIP2-City.mmdb', function(err, locationLookup) { 
     if (err) { 
      logger.error('something went wrong on maxmind fetch', err); 
     } 
     for (var i = 0; i < jsonObject.length; i++) { ...} 
}) 
} 
+1

我不建议在每次调用函数时打开该文件:打开一次,当您的应用程序启动时,并传递'locationLookup'。 – robertklep

+0

听起来不错。现在做出改变并运行良好。感谢您的帮助和反馈。这非常有帮助。 –