Модераторы: xvr

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Большой бинарный файл (2Гб), Нужно очень быстро дёргать из него инфу 
:(
    Опции темы
Fabio
  Дата 12.9.2011, 21:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 29
Регистрация: 9.11.2007

Репутация: нет
Всего: нет



Всех приветствую.

Суть вопроса: есть дампы сетевого трафика (типа netflow), которые генерятся биллингом UTM5, у меня они по 2Гб. Их формат известен. Поставил себе задачу рисовать графики потребления трафика в личном кабинете абонента - за час, за сутки и за месяц. Соль в том, что при тупом последовательном чтении бинарной структуры из этого файла будет затрачиваться слишком много времени.
Как можно ускорить данную процедуру? Примеры кода не обязательно, хотя бы ссылки на алгоритмы подобных операций, теоретические размышления, всё сгодится!

PS
Код ещё не писал, да и вообще под никсами пока не кодил, но не в этом суть. Я хочу сделать на C программулину, что-то типа посредника, которая будет быстро искать данные в этих файлах, основываясь на id лицевого счёта абонента и временного диапазона, интерполировать их под временные оси графиков и отдавать, например, через stdout, подготовленные данные вызывающему её php-сценарию.

Это сообщение отредактировал(а) Fabio - 12.9.2011, 21:40
PM   Вверх
newbee
Дата 12.9.2011, 21:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бревно
**


Профиль
Группа: Участник
Сообщений: 703
Регистрация: 24.8.2011

Репутация: нет
Всего: 19



mmap для отображения файла в память, кеш для однажды отрендеренных графиков.


--------------------
You're face to face
With man who sold the world
PM   Вверх
Fabio
Дата 12.9.2011, 22:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 29
Регистрация: 9.11.2007

Репутация: нет
Всего: нет



Немного осложняется тем, что на сервере всего 2 Гб оперативки и занято в среднем 1,3 Гб + своп на 1Гб и в нём со временем становится занято 300 Мбайт непонятно чего. Так что проецировать придётся не весь файл, а где-то по 100Мбайт.

Кэш не катит, т.к. графики рисуются от текущего момента - это обязательное условие моего ТЗ. Скорее нужно будет придумать механизм защиты от DDoS-а юзеров, особенно тех, которые будут в браузере долбасить F5. Думаю предусмотреть в программе что-нибудь вроде мьютекса (можно даже семафор, если допустить возможность параллельной работы нескольких программ) и если он занят, то программка будет завершать свою работу, возвращая сценарию код ошибки, а сценарий в свою очередь скажет юзеру, типа "система занята, повторите запрос позже".

Это сообщение отредактировал(а) Fabio - 12.9.2011, 22:32
PM   Вверх
maxim1000
Дата 12.9.2011, 22:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник
Сообщений: 3334
Регистрация: 11.1.2003
Где: Киев

Репутация: нет
Всего: 110



предобработка, которая уменьшит количество информации

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

при запросе клиента используем эти данные

для большей конкретики нужно знать, какие даные и как часто они меняются...


--------------------
qqq
PM WWW   Вверх
Fabio
Дата 12.9.2011, 22:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 29
Регистрация: 9.11.2007

Репутация: нет
Всего: нет



maxim1000, не непрокатит, т.к. данные в файле - последовательность структур определённого размера (никогда не меняющегося), в каждой структуре поля различных числовых типов. У файла отсутствует заголовок, т.е. тупо raw бинарник. А уже по этим полям и надо производить поиск данных - фильтрацию. Проблемка в том, что временные метки ставятся не через определённый промежуток, а как "попало" (набежало в коллектор N байт, биллинг сделал штамп и отправил на запись в файл - это очень условно, по правде там буфера, что-бы винт не мучать). Этот момент и не позволит подготавливать каким-либо образом эти данные. Грубо говоря они уже подготовлены )))

UPD
Формат привожу с форума биллинга
Код

# 1-4 Device ID        
# 5-8 Src IP            
# 9-12 Dst IP          
# 13-20 Next Hop IP    
# 17-18 In interface ID 
# 19-20 Out interface ID 
# 21-24 Packets        
# 25-28 Bytes          
# 29-32 Start Time      
# 33-36 End Time        
# 37-38 Src Port        
# 39-40 Dest Port      
# 41 Pad                
# 42 TCP Flag ID        
# 43 Protocol ID        
# 44 ToS                
# 45-46 Src AS          
# 47-48 Dest AS        
# 49 Src Mask Bits      
# 50 Dest Mask Bits    
# 51-52 Pad            
# 53-56 ???            
# 57-60 UTM account_id 
# 61-64 ???            
# 65-68 UTM tclass      
# 69-72 UTM timestamp  
# 73-76 ???
Цифры - смещения в байтах, гдето у меня была уже оформленная структура на C, но не смог найти. Меня будут интересовать в плане поиска данные Start Time, End Time и account_id.
Как будет быстрее работать? - сначала выбрать в память все структуры с нужным account_id и уже в них отбирать по времени или учитывать сразу все условия при обходе спроецированного участка?

Это сообщение отредактировал(а) Fabio - 12.9.2011, 22:52
PM   Вверх
Fabio
Дата 12.9.2011, 22:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 29
Регистрация: 9.11.2007

Репутация: нет
Всего: нет



Нашёл структуру, выдернута из одной сервисной OpenSource утилитки стороннего разработчика.
Код

struct record_t {
  uint32_t fw_id;       /* UTM firewall ID */
  /* Netflow v5 */
  uint32_t src_addr;    /* Source IP address */
  uint32_t dst_addr;    /* Destination IP address */
  uint32_t next_hop;    /* Next hop IP address */
  uint16_t i_ifx;       /* Source interface index */
  uint16_t o_ifx;       /* Destination interface index */
  uint32_t packets;     /* Number of packets in a flow */
  uint32_t octets;      /* Number of octets in a flow */
  uint32_t first;       /* System uptime at start of a flow */
  uint32_t last;        /* System uptime at end of a flow */
  uint16_t s_port;      /* Source port */
  uint16_t d_port;      /* Destination port */
  uint8_t pad1;         /* Pad to word boundary */
  uint8_t flags;        /* Cumulative OR of tcp flags */
  uint8_t prot;         /* IP protocol */
  uint8_t tos;          /* IP type of service */
  uint16_t src_as;      /* Src peer/origin Autonomous System */
  uint16_t dst_as;      /* Dst peer/origin Autonomous System */
  uint8_t src_mask;     /* Source route's mask bits */
  uint8_t dst_mask;     /* Destination route's mask bits */
  uint16_t pad2;        /* Pad to word boundary */
  /* */
  uint32_t slink_id;    /* UTM service link ID */
  uint32_t account_id;  /* UTM Account ID */
  uint32_t account_ip;  /* UTM User IP */
  uint32_t tclass;      /* UTM traffic class */
  uint32_t timestamp;   /* UTM timestamp */
  uint32_t router_ip;   /* UTM netflow router IP */
} __attribute__((__packed__));


Цитата
... и как часто они меняются...
биллинг сбрасывает в конец файла порции данных с промежутком в несколько минут (можно уточнить), когда набегает 2Гб, то файл оставляют покоиться на винте. Сразуже создаётся новый файл с именем вида iptraffic_raw_<unix_current_timestamp>.utm и процедура повторяется. Каждый файл вмещает в себя от 1,5 до 3-х суток трафика, в зависимости от загрузки сети. Кстати я ещё не выяснил, в каком режиме биллинг открывает этот файл, а то может в монопольном, тогда все мытарства коту под хвост.

Это сообщение отредактировал(а) Fabio - 13.9.2011, 00:06
PM   Вверх
shara
Дата 13.9.2011, 10:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 344
Регистрация: 29.6.2004
Где: печенье?

Репутация: нет
Всего: 2




Цитата(Fabio @  12.9.2011,  21:40 Найти цитируемый пост)
maxim1000, не непрокатит, т.к. данные в файле - последовательность структур определённого размера

Почему не прокатит? Если данные заполняются в структуру, а потом эта структура последовательно, одна за одной, укладываются в файл. Нужные тебе метки всегда будут находится по какому-то кратному смещению относительно начала... дергай нужные тебе байты да скалдывай их в файлик поменьше. Но все равно, тебе прийдется прошуршать шуршать 2Гб инфы в поисках всего пары полей - а это не целесообразно ибо как долго и ресурсоемко.. да и хранить такие объемы на диске.. ну хз  smile 

Я бы попытался получить доступ к памяти процесса которые сии файлы генерит и выдергивать из него нужные поля структуры, ну к примеру в момент когда он ее (структуру) забрасывает на диск.  и спокойно себе вести небольшой лог файл в котором аккуратно будут лежать 
Цитата(Fabio @  12.9.2011,  21:40 Найти цитируемый пост)
данные Start Time, End Time и account_id
  smile 



--------------------
   с точки зрения аэродинамики шмель не может летать  
PM MAIL   Вверх
Fabio
Дата 13.9.2011, 10:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 29
Регистрация: 9.11.2007

Репутация: нет
Всего: нет



Цитата

... да и хранить такие объемы на диске ...
Ну видите-ли, ФСБ и отделу К в частности наплевать на это, надо держать детальку за последние 3! года и в случае запроса от них по конкретному ip и времени надо выдавать им .csv файлик. Но это уже другая тема.


Это сообщение отредактировал(а) Fabio - 13.9.2011, 11:24
PM   Вверх
shara
Дата 13.9.2011, 12:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 344
Регистрация: 29.6.2004
Где: печенье?

Репутация: нет
Всего: 2



Fabio, так храните два файла.
   Один с полной версией всей "хистори"
и Второй, который будет содержать только ту инфу, что нужна для отчета. 

Всяко с маленьким файлом удобней работать. 


З.Ы. 
Магический алгоритм  smile  халявного и быстрого поиска в 2гб файлах Вам вряд-ли кто предложит  smile 
Еего все равно прийдется либо индексировать как-то, либо разбивать на части.. либо...  в общем насколько у вас фантазии хватит.

З.З.Ы.
Так что скажете насчет 
Цитата(shara @  13.9.2011,  09:27 Найти цитируемый пост)
 получить доступ к памяти процесса которые сии файлы генерит и выдергивать из него нужные поля структуры
 ??



--------------------
   с точки зрения аэродинамики шмель не может летать  
PM MAIL   Вверх
Fabio
Дата 13.9.2011, 12:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 29
Регистрация: 9.11.2007

Репутация: нет
Всего: нет



Цитата

Так что скажете насчет
процесс этот зовут utm5_core, его трогать ни в коем случае не стоит. Могу объяснить почему, но неохот - это очевидно.
На счёт двух копий - нет смысла, там же ужимать нечего! Да и реализовать это не представляется возможным. В биллинге есть событие ротации этого лога трафика, можно по нему перегонять данные (не учитывая лишние поля в структуре, но всё равно придётся перегонять ВСЁ), но тут мы получим ... а ничего не получим, нахрен пользователю/админу смотреть данные на 1,5 - 3-е суток назад, когда нужно посмотреть сейчас  smile .
Нужен интерактив.
PM   Вверх
fish9370
Дата 13.9.2011, 14:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 663
Регистрация: 15.4.2007
Где: Москва

Репутация: 2
Всего: 1



то о  чем вы здесь говорите называется агрегацией, да в любом случае агрегация приводит к усреднению значений, т.е. нельзя точно сказать что происходило в какой-то конкретный момент времени.. но это весьма полезно поскольку, объем трафика огромен, и делать поиск по 2гб не разумно долго.. файл UTM вероятнее всего открывает в режиме "a", т.е. для записи в конец, а это значит, что его можно открыть другим процессом и в реальном времени производить агрегацию, т.е. суммировать трафик и усреднять значение, записывая в новый файл..

насчет эффективности, полагаю этот метод вполне себе эфективен, т.к. врядли UTM делает после каждого цикла записи flush, чем сбрасывает грязные буферы.. 

вообще вопрос агрегации, для биллингов не нов, все так или иначе умеют это делать, может стоит порыться в настройках UTM?

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

Это сообщение отредактировал(а) fish9370 - 13.9.2011, 14:21


--------------------
undefined
PM MAIL WWW ICQ   Вверх
Fabio
Дата 13.9.2011, 14:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 29
Регистрация: 9.11.2007

Репутация: нет
Всего: нет



Цитата

может стоит порыться в настройках UTM?
Ну конечно там всё присутствует, за исключением вывода информации в необходимом графическом представлении для удобного визуального восприятия человеком. Есть детализированные отчёты по трафику с развитой системой фильтров. Но это всё неудобно для анализа потребления абонентом трафика, например, хочется видеть, когда абонент качал торренты или он просто сёрфил веб. Интересно знать, какой тип трафика преобладает у абонента: tcp или udp, какой средний размер пакетов идёт от абонента. Это всё можно получить из данных логов трафика и визуализировать, привязав к каждому абоненту... теоретически. Ну а то, что показывает биллинг в своих отчётах - ни куда не годится, для человека анализ табличных данных, как мёртвому припарка  smile .
Цитата

так же хочу напомнить, что помимо нетфлоу, можно считать трафик по апдейтам радиуса, это тоже общепринятый метод.. но там скорее всего без агрегации тоже не обойтись..
Радиус сервер вообще никак не поможет в данном вопросе  smile

Добавлено @ 14:42
Самой хорошей на данный момент идеей является поднятие ещё одного стороннего коллктора, например, nfdump. Ограничить объём логов трафика до 30 суток (что-бы место на ХДД не расходовал). Сенсором трафика у меня является модуль iptables ipt_NETFLOW, он позволит отсылать данные двум коллекторам: биллингу и nfdump. Для nfdump существует perl визуализатор nfsen. Но опять-же - это всё рубит на корню идею с графиками в личных кабинетах, т.к. теряется связь между account_id и непосредственно трафиком. IP адреса в нашей сети динамические.

PS
Да, и этим размышлениям не место в программистском форуме, последний абзац лучше смотрелся-бы на наге...

Это сообщение отредактировал(а) Fabio - 13.9.2011, 14:45
PM   Вверх
bsa
Дата 13.9.2011, 18:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 16
Всего: 196



Fabio, думаю стоит возвратиться обратно к "тупой обработке файла". Итак:
1. файл бинарный
2. файл содержит N=2GB/sizeof(DataStruct) записей
3. размер записи фиксированный

Что делаем:
1. открываем файл, ммапим в ОЗУ (эта операция не тербует от тебя наличия такого количества свободной памяти - ОС сама прозрачно будет подгружать нужные части, главное, чтобы размер области был кратен размеру страницы памяти, обычно, 4096 байт) и читаем первую и последнюю метку времени, если необходимое нам время не лежит где-то между ними, то открываем предыдущий/следующий файл
2. необходимая метка лежит где-то между первой и последней, выбираем примерный номер подходящей нам записи на основании ее смещения относительно начала (i = (end - beg)/(met - beg))
3. используем полученный номер как первую итерацию в бинарном поиске метки близкой к искомой (т.е. совсем не обязательно, что ты найдешь то что хотел, но с отклонением в несколько сек - запросто)
4. начинаешь последовательный перебор записей по полю account_id до конца файла, информацию из подходящих записей выводишь в stdout.

P.S.: логично использовать для доступа к отображенной области типизированный указатель на const DataStruct

Это сообщение отредактировал(а) bsa - 13.9.2011, 18:21
PM   Вверх
Fabio
Дата 13.9.2011, 18:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 29
Регистрация: 9.11.2007

Репутация: нет
Всего: нет



bsa, большое спасибо! Истина где то рядом (с).

UPD
Ооох чую жесть будет, когда начну пробовать, тамже придётся осваивать gdb, а без отладки никуда... Сервак-то консольный, с доступом только по ssh  smile 

Это сообщение отредактировал(а) Fabio - 13.9.2011, 18:56
PM   Вверх
newbee
Дата 13.9.2011, 21:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бревно
**


Профиль
Группа: Участник
Сообщений: 703
Регистрация: 24.8.2011

Репутация: нет
Всего: 19



Fabio, настоящие мужчины знают, что пишут, и не пользуются отладчиками! Попробуй, и ты сможешь.

Добавлено через 40 секунд
Я вот сколько под линуксы ни писала, ни разу gdb не запускала smile


--------------------
You're face to face
With man who sold the world
PM   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С/С++: Программирование под Unix/Linux"
xvr
  • Проставьте несколько ключевых слов темы, чтобы её можно было легче найти.
  • Не забывайте пользоваться кнопкой "Код".
  • Вопросы мобильной разработки тут
  • Телепатов на форуме нет! Задавайте чёткий, конкретный и полный вопрос. Указывайте полностью ошибки компилятора и компоновщика.
  • Новое сообщение должно иметь прямое отношение к разделу форума. Флуд, флейм, оффтопик запрещены.
  • Категорически запрещается обсуждение вареза, "кряков", взлома программ и т.д.

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, xvr.

 
 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Программирование под Unix/Linux | Следующая тема »


 




[ Время генерации скрипта: 0.0905 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.