Получение IP-адресов из больших двоичных файлов nfcapd

Мне нужно получить информацию об исходных IP-адресах и IP-адресах назначения из двоичного файла nfcapd. Проблема в размере файла. Я знаю, что нежелательно открывать и читать очень большие (более 1 ГБ) файлы с помощью пакета io или os.

Вот мой взлом и черновой старт:

package main

import (
    "fmt"
    "time"
    "os"
    "github.com/tehmaze/netflow/netflow5"
    "log"
    "io"
    "bytes"
)

type Message interface {}

func main() {
    startTime := time.Now()
    getFile := os.Args[1]
    processFile(getFile)
    endTime := time.Since(startTime)
    log.Printf("Program executes in %s", endTime)
}

func processFile(fileName string) {
    file, err := os.Open(fileName)
    // Check if file is not empty. If it is, then exit from program
    if err != nil {
        fmt.Println(err)
        os.Exit(1)
    }

    // Useful to close file after getting information about it
    defer file.Close()
    Read(file)
}

func Read(r io.Reader) (Message, error) {
    data := [2]byte{}
    if _, err := r.Read(data[:]); err != nil {
        return nil, err
    }
    buffer := bytes.NewBuffer(data[:])
    mr := io.MultiReader(buffer, r)
    return netflow5.Read(mr)
}

Я хочу разбить файл на куски с 24 потоками и обрабатывать его одновременно после чтения с помощью netflow package. Но я не представляю, как это сделать без потери данных при делении.

Пожалуйста, исправьте меня, если я что-то упустил в коде или описании. Я трачу много времени на поиск своего решения в сети и размышляю о других возможных реализациях.

Мы будем очень благодарны за любую помощь и / или совет.

Файл имеет следующие свойства (команда file -I <file_name> в терминале):

file_name: application/octet-stream; charset=binary

Вывод файла после команды nfdump -r <file_name> имеет такую ​​структуру:

Date first seen          Duration Proto      Src IP Addr:Port          Dst IP Addr:Port   Packets    Bytes Flows

Каждое свойство находится в отдельной колонке.

ОБНОВЛЕНИЕ 1: К сожалению, невозможно проанализировать файл с помощью netflow из-за разницы в структуре двоичного файла после его сохранения на диск через nfcapd. Этот ответ дал один из nfdump участников.

Единственный способ сейчас - запустить nfdump из терминала в программе go, например pynfdump.

Еще одно возможное решение в будущем - использовать gopacket.


person memu    schedule 24.10.2016    source источник
comment
Какова структура этого двоичного файла nfcapd? Действительно ли это текстовый файл с разумно структурированными строками? Ваша проблема в том, что вы не знаете, как эффективно читать файл, или вам также нужна помощь с синтаксическим анализом IP-адресов?   -  person HenryTK    schedule 24.10.2016
comment
Я нашел пример выходного файла в GitHub Gist: ngistfile_file_file.html " / asachs / bfbfebdb39b33a5ded61 / raw / Я предполагаю, что вы имеете дело с очень большой версией этого.   -  person HenryTK    schedule 24.10.2016
comment
@HenryTK Я добавил дополнительную информацию о файле. Я сейчас не знаю, как эффективно читать файлы и разбирать IP-адреса. Я новичок в Голанге.   -  person memu    schedule 24.10.2016
comment
зачем вы создаете горутину для чтения файла go Read(file) ?? Что ж, я предупреждаю вас, что ваша программа точно ничего не будет делать, функция main () завершится и все.   -  person Yandry Pozo    schedule 24.10.2016
comment
@YandryPozo извини. Это была опечатка   -  person memu    schedule 24.10.2016
comment
Я не понимаю предпосылки, что нежелательно открывать и читать очень большие (более 1 ГБ) файлы с пакетом io или os. Это именно те пакеты, которые вам нужно использовать для эффективного чтения файла, возможно, с добавление bufio тоже.   -  person JimB    schedule 24.10.2016
comment
@JimB Я сделал предположение после прочтения stackoverflow.com/questions/1821811/   -  person memu    schedule 25.10.2016
comment
Я не уверен, как вы делаете это предположение, поскольку вы вообще не можете прочитать файл (ну, по крайней мере, непросто) без использования пакетов os и io. Я не могу понять, каково ваше намерение с функцией чтения, поскольку то, что вы делаете, не имеет смысла, т.е. почему вы читаете первые 2 байта дважды? Вы будете ограничены вводом-выводом на чтение файла, и если вы собираетесь обрабатывать все части одновременно, вам нужно в первую очередь загрузить их все в память. Просто прочтите файл полностью.   -  person JimB    schedule 25.10.2016
comment
@JimB Предположение касалось bufio и других пакетов, которые я не могу использовать для чтения всего файла сразу. Это всего лишь черновой старт. У меня нет опыта работы с параллельным программированием, особенно с Golang. Мой вопрос заключался в том, чтобы узнать, как одновременно обрабатывать очень большие файлы, чтобы читать IP-адреса и использовать их.   -  person memu    schedule 25.10.2016


Ответы (1)


IO почти всегда будет ограничивающим фактором при синтаксическом анализе файла, и, если не требуется больших вычислений, последовательное чтение одного файла будет самым быстрым способом его обработки.

Оберните файл в bufio.Reader и передайте его функции Read:

file, err := os.Open(fileName)
if err != nil {
    log.Fatal((err)
}
defer file.Close()

packet, err := netflow5.Read(bufio.NewReader(file))

После анализа вы можете разделить записи, если вам нужно обрабатывать куски отдельно.

person JimB    schedule 25.10.2016
comment
Как вы думаете, этот двоичный файл невозможно прочитать с помощью netflow. В связи с этим if statement: github.com/tehmaze/netflow/blob /master/netflow5/packet.go#L62 Невозможно прочитать файл целиком. Моя цель - прочитать его отдельно, чтобы отправлять потоки в данные Unmarshall. - person memu; 26.10.2016
comment
@memu: если пакет netflow не анализирует его, вам нужно что-то, что будет. Вы не можете разделить части двоичного файла без элементарного анализа. Рабочий процесс остался прежним: заверните файл в bufio.Reader и прочтите его последовательно. - person JimB; 26.10.2016
comment
Что вы имеете в виду под серийным чтением? Читает ли он кусками массива байтов? Если да, то какой размер мне выбрать? - person memu; 26.10.2016
comment
@memu: я имею в виду прочитать файл один раз от начала до конца, не пытаясь добавить ненужный параллелизм. Суть использования буферизованного ввода-вывода заключается в том, что размер не имеет значения, вы читаете нужный размер. - person JimB; 26.10.2016
comment
Я хочу очень быстро читать и обрабатывать файл. Что еще я должен применить, кроме параллелизма? - person memu; 26.10.2016
comment
@memu, опять же, в общем, параллелизм не позволит вам читать файл быстрее, когда вы ограничены вводом-выводом. Попытка прочитать несколько частей файла одновременно вызывает больше случайных операций ввода-вывода, что может значительно снизить пропускную способность. Параллелизм - это не параллелизм, и он не может волшебным образом сделать непараллельные вещи быстрее. Если требуются значительные вычисления для применения к независимым, изолированным структурам данных, считываемым из файла, тогда это конкретное вычисление может выиграть от параллелизма, но анализ файл не тот. - person JimB; 26.10.2016
comment
Но что вы думаете об этом ответе ?: stackoverflow.com/a/27217975/5907708 - person memu; 26.10.2016
comment
@memu: при чтении файла в этом ответе параллелизма нет. Сканер читает по одной строке за раз; затем отправляет копию каждой строки для одновременной обработки. Это именно то, что я описал в своем последнем комментарии: файл читается последовательно, а вычисления выполняются одновременно. Вы можете использовать тот же шаблон, но вам нужно написать эквивалент scanner.Scan для двоичного формата вашего файла (и обратите внимание, что при этом вы можете обнаружить, что для ваших дополнительных усилий ускорение незначительно или совсем отсутствует) - person JimB; 26.10.2016