У меня есть несколько серверов 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 }