Назад | Перейти на главную страницу

отслеживать трафик в масштабе миллисекунды

У меня есть несколько серверов Linux под управлением Ubuntu 14.04, и я превратил их в кластер Spark. На этом этапе я хочу измерить сетевой поток между серверами в миллисекундах, чтобы выполнить некоторые задачи вывода и анализа в исследовательских целях. Я безуспешно пробовал следующее:

1) Я неоднократно вызываю "iptables -nvx -L" из сценария и беру его вывод, содержащий нужную мне информацию (количество пакетов и байтов). Однако его вызов занимает больше 1 мс, как я реализовал как в Python (с использованием модуля подпроцесса), так и в скриптах Bash.

Python:

args = ['iptables', '-nvx', '-L', 'Журнал']

raw_traffic = sp.Popen ('iptables -nvx -L Log', shell = True, stdout = sp.PIPE) .stdout

(Для выполнения приведенного выше кода требуется 1,2 мс)

Баш:

start_time = $ (дата +% s% N)

std_output = $ (iptables -nvx -L Журнал)

echo "(($ (дата +% s% N) - $ start_time) / 1000000)" | bc -l

с выходом:

$ sudo sh foo.sh

1,17057700000000000000

2) Я пытался попросить iptables регистрировать каждый пакет с IP-адресов серверов. Он определенно служит цели, поскольку измеряет все до мельчайших деталей. Однако это замедляет трафик и создает большие накладные расходы. Каналы между серверами имеют пропускную способность 10 Гбит / с, поэтому на полной скорости генерируется около 1 млн строк журналов в секунду для каждого IP-адреса, а это невозможно. На данный момент мне нужна информация о миллисекундных пакетах и ​​байтах между серверами.

Есть ли обходные пути мониторинга в масштабе 1 мс? Я полагаю, это должно быть выполнено с помощью iptables, возможно, с некоторыми хаками. Любые предложения более чем приветствуются. Заранее спасибо!

Вы действительно можете это сделать, но вам нужно будет использовать цель iptables NF_LOG и написать программу, которая специально удовлетворяет ваши потребности.

NF_LOG будет отправлять пакеты принимающему приложению, которое (учитывая, насколько быстро вам удается делать то, что вы делаете) будет считать пакеты на уровне за миллисекунду.

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

Проблема, однако, в том, что такой программы приема не существует - вам нужно ее написать.

Сделав что-то с NF_LOG раньше и ваше заявление о том, что LOG замедляет трафик, я подозреваю, что это запись пакетов на диск, которая, вероятно, сеет.

Я все еще подозреваю, что миллион пакетов в секунду - это еще высокая планка.

Другой альтернативой (которая не в реальном времени) является использование tcpdump для захвата пакетов и последующего последующего использования программы для чтения файла pcap и выполнения соответствующих расчетов в миллисекундах.

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

Я не пробовал, но сетевой фильтр библиотека libnetfilter_log выглядит многообещающе. iptables по сути интерфейс командной строки netfilter и netfilter - это фильтр пакетов в ядре Linux. Так что это будет ваша прямая библиотека для фильтра пакетов. Звучит эффективно.

http://www.netfilter.org/projects/libnetfilter_log/index.html

Что такое libnetfilter_log?

libnetfilter_log - это библиотека пользовательского пространства, обеспечивающая интерфейс для пакетов, которые были зарегистрированы фильтром пакетов ядра. Это часть системы, которая не рекомендует старое ведение журнала пакетов на основе syslog / dmesg. Эта библиотека ранее была известна как libnfnetlink_log.

Основные особенности

получение пакетов, подлежащих регистрации, от подсистемы ядра nfnetlink_log

Вот пример кода (пример скопирован с сайта netfilter / неплохо, правда?)

00002 #include <stdio.h>
00003 #include <stdlib.h>
00004 #include <unistd.h>
00005 #include <netinet/in.h>
00006 
00007 #include <libnetfilter_log/libnetfilter_log.h>
00008 
00009 static int print_pkt(struct nflog_data *ldata)
00010 {
00011         struct nfulnl_msg_packet_hdr *ph = nflog_get_msg_packet_hdr(ldata);
00012         u_int32_t mark = nflog_get_nfmark(ldata);
00013         u_int32_t indev = nflog_get_indev(ldata);
00014         u_int32_t outdev = nflog_get_outdev(ldata);
00015         char *prefix = nflog_get_prefix(ldata);
00016         char *payload;
00017         int payload_len = nflog_get_payload(ldata, &payload);
00018         
00019         if (ph) {
00020                 printf("hw_protocol=0x%04x hook=%u ", 
00021                         ntohs(ph->hw_protocol), ph->hook);
00022         }
00023 
00024         printf("mark=%u ", mark);
00025 
00026         if (indev > 0)
00027                 printf("indev=%u ", indev);
00028 
00029         if (outdev > 0)
00030                 printf("outdev=%u ", outdev);
00031 
00032 
00033         if (prefix) {
00034                 printf("prefix=\"%s\" ", prefix);
00035         }
00036         if (payload_len >= 0)
00037                 printf("payload_len=%d ", payload_len);
00038 
00039         fputc('\n', stdout);
00040         return 0;
00041 }
00042 
00043 static int cb(struct nflog_g_handle *gh, struct nfgenmsg *nfmsg,
00044                 struct nflog_data *nfa, void *data)
00045 {
00046         print_pkt(nfa);
00047 }
00048 
00049 
00050 int main(int argc, char **argv)
00051 {
00052         struct nflog_handle *h;
00053         struct nflog_g_handle *qh;
00054         struct nflog_g_handle *qh100;
00055         int rv, fd;
00056         char buf[4096];
00057 
00058         h = nflog_open();
00059         if (!h) {
00060                 fprintf(stderr, "error during nflog_open()\n");
00061                 exit(1);
00062         }
00063 
00064         printf("unbinding existing nf_log handler for AF_INET (if any)\n");
00065         if (nflog_unbind_pf(h, AF_INET) < 0) {
00066                 fprintf(stderr, "error nflog_unbind_pf()\n");
00067                 exit(1);
00068         }
00069 
00070         printf("binding nfnetlink_log to AF_INET\n");
00071         if (nflog_bind_pf(h, AF_INET) < 0) {
00072                 fprintf(stderr, "error during nflog_bind_pf()\n");
00073                 exit(1);
00074         }
00075         printf("binding this socket to group 0\n");
00076         qh = nflog_bind_group(h, 0);
00077         if (!qh) {
00078                 fprintf(stderr, "no handle for grup 0\n");
00079                 exit(1);
00080         }
00081 
00082         printf("binding this socket to group 100\n");
00083         qh100 = nflog_bind_group(h, 100);
00084         if (!qh100) {
00085                 fprintf(stderr, "no handle for group 100\n");
00086                 exit(1);
00087         }
00088 
00089         printf("setting copy_packet mode\n");
00090         if (nflog_set_mode(qh, NFULNL_COPY_PACKET, 0xffff) < 0) {
00091                 fprintf(stderr, "can't set packet copy mode\n");
00092                 exit(1);
00093         }
00094 
00095         fd = nflog_fd(h);
00096 
00097         printf("registering callback for group 0\n");
00098         nflog_callback_register(qh, &cb, NULL);
00099 
00100         printf("going into main loop\n");
00101         while ((rv = recv(fd, buf, sizeof(buf), 0)) && rv >= 0) {
00102                 struct nlmsghdr *nlh;
00103                 printf("pkt received (len=%u)\n", rv);
00104 
00105                 /* handle messages in just-received packet */
00106                 nflog_handle_packet(h, buf, rv);
00107         }
00108 
00109         printf("unbinding from group 100\n");
00110         nflog_unbind_group(qh100);
00111         printf("unbinding from group 0\n");
00112         nflog_unbind_group(qh);
00113 
00114 #ifdef INSANE
00115         /* norally, applications SHOULD NOT issue this command,
00116          * since it detaches other programs/sockets from AF_INET, too ! */
00117         printf("unbinding from AF_INET\n");
00118         nflog_unbind_pf(h, AF_INET);
00119 #endif
00120 
00121         printf("closing handle\n");
00122         nflog_close(h);
00123 
00124         exit(0);
00125 }