2015-12-04 5 views
0

Я запускаю цикл for для создания всех возможных IPv4-адресов, а затем просматриваю их в файле mmmb maxmind. Проблема в том, что цикл for слишком быстр, поиск maxmind относительно медленный, и, следовательно, процессы замедляются, и в конечном итоге моя система зависает после нескольких итераций на 400 тыс. Если бы я читал из какого-то потока, я бы приостановил поток после прочтения каждого IP-адреса 10 000 и возобновил бы только тогда, когда все они были просмотрены из файла mmdb. Но как я могу получить такой контроль для цикла for?Node.js: Как приостановить/возобновить цикл for

connectToMaxMindDatabases().then(function (done){ 
    for(var i=0; i<256; i++){ 
     for(var j=0; j<256; j++){ 
      for(var k=0; k<256; k++){ 
       for(var l=0; l<256; l++){ 
        count++; 
        if(count % 1000 == 0){ 
         console.log("count", count); 
        } 
        var newIP = getIPV4([i,j,k,l]) 
        ispDB.getGeoDataAsync(newIP).then(function (result){ 
         if(result){ 
          console.log(count, newIP, result); 
          // process.exit(); 
         } 
        }); 
       } 
      } 
     } 
    }  
}) 


function getIPV4(bytes){ 
    return bytes.join(".") 
} 
+2

Обратите внимание, что Node.js имеет неблокирующую философию, поэтому я думаю, что остановка цикла, возможно, не является хорошим выбором. Может быть, какая-то очередь? –

+0

Знаете ли вы об ошибке в вашем примере кода, потому что 'getGeoDataAsync' является асинхронным, к моменту его возврата возвращается' count' будет увеличиваться на непредсказуемую сумму? Не уверен, что это имеет отношение к вашей логике, но это определенно то, что вы упускаете из виду. – marekful

+0

@marekful Я понимаю вашу точку зрения. Однако это не вызывает никаких проблем, так как мне нужно обработать все IP-адреса. Если вместо цикла for это был файл, это не вызвало бы никаких проблем, так как я бы приостановил поток после чтения, скажем, каждые 1k записей и возобновлялся только тогда, когда это число записей было обработано maxmind. Я бы сохранил для этого отдельный счетчик. Но я согласен с Адамом, приостановление цикла for будет катастрофическим. Я думаю сначала написать все перестановки в файл. –

ответ

0

Я не уверен, но process.nextTick может помочь https://nodejs.org/api/process.html#process_process_nexttick_callback_arg

Я действительно не уверен, но следующий код может быть использован:

connectToMaxMindDatabases().then(function (done){ 
    for(var i=0; i<256; i++){ 
     process.nextTick(function(){ 
      for(var j=0; j<256; j++){ 
       process.nextTick(function(){ 
        for(var k=0; k<256; k++){ 
         process.nextTick(function(){ 
          for(var l=0; l<256; l++){ 
           process.nextTick(function(){ 
            count++; 
            if(count % 1000 == 0){ 
             console.log("count", count); 
            } 
            var newIP = getIPV4([i,j,k,l]) 
            ispDB.getGeoDataAsync(newIP).then(function (result){ 
             if(result){ 
              console.log(count, newIP, result); 
              // process.exit(); 
             } 
            }); 
           } 
          } 
         }) 
        } 
       } 
      } 
     } 
    }  
}) 

По моим знания, вот что происходит: все циклы for работают синхронно, а вызов async ispDB.getGeoDataAsync (newIP) ставится в очередь, но его обратный вызов (функция .then) не может выполняться, потому что цикл события был заблокирован4 для петель.

+0

спасибо @manish. Тем не менее, теперь, когда я снова думаю, я часто буду использовать этот список, поэтому не может быть ужасной идеей хранить его в файле, а затем читать оттуда –

+1

@ mandeep_m91 похоже, что вы переопределяете свою собственную систему поиска IP ? Кроме того, я, кажется, помню, что лицензия Maxmind EULA запрещает эти виды производных работ, поэтому убедитесь, что то, что вы делаете, является законным :-) – robertklep

+0

Хорошая точка :-). Моя цель другая. –

0

Корень проблемы определенно находится в управлении ресурсами базового сервера OS/Node. Цикл for с таким количеством итераций будет зависеть от этого конкретного оборудования, в то время как он, вероятно, только заморозится позже или вообще не будет на гораздо более мощном компьютере. Решение состоит в том, чтобы сначала собрать все IP-адреса в массиве, а затем обработать их так, чтобы обрабатывать только один сегмент, дождаться окончания и перейти к следующему сегменту.

Возможное решение может быть достигнуто при таком сегментировании и Promse.each Bluebird.

Если функция возвращает итератор обещания или thenable, то результата обещания ожидается, перед продолжением следующего итерации.

var Promise = require('bluebird'), 
    _ = require('lodash'), 
    allIPs = []; 

connectToMaxMindDatabases().then(function (done){ 
    for(var i=0; i<256; i++){ 
     for(var j=0; j<256; j++){ 
      for(var k=0; k<256; k++){ 
       for(var l=0; l<256; l++){ 
        count++; 
        if(count % 1000 == 0){ 
         console.log("count", count); 
        } 
        var newIP = getIPV4([i,j,k,l]) 
        allIPs.push(newIP); 
       } 
      } 
     } 
    }  
    return allIPs; 
}) 
.then(function(allIPs) { 
    // Create an array of arrays of IPs, each inner array with 1000 IPs 
    var from = 0, to = 1000, segments = [], promises; 

    do { 
     segments.push(allIPs.slice(from, to)); 
     from += 1000; to += 1000; 
    } while(to < allIPs.lenght); 

    // Process a segment of 1000 IPs and wait before moving the next 
    // segment until this segment is fully resolved. 
    Promise.each(segments, function(segmentArr) { 
     promises = []; 
     _.forOwn(segmentArr, function(IP) { 
      promises.push(ispDB.getGeoDataAsync(IP) 
       .then(function(result) { 
        // save the result 
       }) 
      ); 
     }); 
     return Primse.all(promises); 
    }); 
}); 

Конечно, если ресурсы в вашем случае ограничены в пути allIPs массива не может даже быть произведен, поскольку он начинает замораживание до того, что, это не решит проблему, но шансы на это ресурсы, которые едят все эти getGeoDataAsync звонки, и в этом случае это должно помочь.

+0

«собирать все IP-адреса в массиве сначала» звучит как голодная идея памяти – Purefan

+1

Это правда. Итак, извлечение IP-адресов также должно быть перенесено на фазу сегментации, поэтому не все из них будут собираться сразу в сегменты. – marekful

 Смежные вопросы

  • Нет связанных вопросов^_^