ruby – 每秒测量出站请求数?
我有一个正在使用的网络应用程序
ActiveResource与另一台具有速率限制的服务器通信 连接.我很好奇我如何能够从我的web应用程序运行的主机上最好地监控 – 也就是说,从我的服务器上的 linux上的bash提示符,我如何测量我的机器每秒向另一台机器发出的出站请求? 我正在寻找一个带有接口,主机名的linux one-liner $awesometool –host thetargethost.com –interface eth0 –interval 5 收集统计数据 通过接口eth0,thetargethost.com的每秒请求报告 平均:23 req / sec min:12 req / sec max 39 req / sec 取5个样品 谁能指点我一个人? 解决方法
tcpdump(8)可以提供非常相似的东西;搜索TCP数据包,并将SYN标志设置为捕获
three-way handshake中发往其他对等方的第一个数据包:
$sudo tcpdump -c 10 -i eth0 "tcp[tcpflags] & (tcp-syn) != 0 and dst 192.168.0.1" tcpdump: verbose output suppressed,use -v or -vv for full protocol decode listening on eth0,link-type EN10MB (Ethernet),capture size 65535 bytes 18:26:24.800308 IP haig.59419 > 192.168.0.1.telnet: Flags [S],seq 3197302320,win 14600,options [mss 1460,sackOK,TS val 19460844 ecr 0,nop,wscale 7],length 0 ... 18:26:27.420132 IP haig.59428 > 192.168.0.1.telnet: Flags [S],seq 1238498237,TS val 19461106 ecr 0,length 0 10 packets captured 10 packets received by filter 0 packets dropped by kernel 您可以使用/usr/bin/time或内置shell的时间,或者对输出中的时间戳进行一些算术运算,以获得每秒的平均速率. (使用十个以上的数据包 – 这只是为了演示.) 更新 我写了一个小程序来运行tcpdump(8),计算数据包,并报告在指定的时间间隔内发送了多少数据包: # ./counter --host 192.168.0.1 --interface eth0 --interval 3 2 requests in 3 seconds; average 0.67 req/seq 20 requests in 3 seconds; average 6.67 req/seq 19 requests in 3 seconds; average 6.33 req/seq 19 requests in 3 seconds; average 6.33 req/seq ^C # ./counter --host 192.168.0.1 --interface eth0 --interval 5 30 requests in 5 seconds; average 6.00 req/seq 20 requests in 5 seconds; average 4.00 req/seq 1176 requests in 5 seconds; average 235.20 req/seq 1414 requests in 5 seconds; average 282.80 req/seq 0 requests in 5 seconds; average 0.00 req/seq ^C 因为它要求tcpdump(8)使用行缓冲输出,我有点害怕它可能无法超过每秒200-300个请求,至少在我的硬件上.但是没有行缓冲输出,tcpdump(8)会等到它的输出缓冲区(详见setvbuf(3))在发送任何输出之前都已满,导致极其抖动的结果. 但如果您的连接速度不是那么高,那么这可能会满足您的需求.如果您的连接速率较高,那么这个小小的黑客可能最好被忽略 – 这让我觉得可能iptables(8)可以计算流. #include <stdio.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #include <getopt.h> #include <signal.h> #include <errno.h> #include <fcntl.h> #include <sys/types.h> #define CMDLEN 1024 #define TCPDUMPLEN 4096 int show_stats; long counter; void alarm_handler(int signum) { show_stats = 1; } void install_handler(void) { struct sigaction sa; memset(&sa,sizeof(sa)); sigemptyset(&sa.sa_mask); sa.sa_handler = &alarm_handler; if (sigaction(SIGALRM,&sa,NULL) == -1) { perror("Can't install alarm handler"); exit(1); } } int count_lines(char *p,int bytes) { int counter = 0; char *i; for (i=p; i < p+bytes ; i++) { if (*i == 'n') counter++; } return counter; } int spawn_tcpdump(char *host,char *interface) { int fd[2]; pid_t child; if (pipe(fd) == -1) { perror("Can't create pipes"); exit(1); } child = fork(); if (child == -1) { perror("Can't fork(2) for tcpdump"); exit(1); } if (child == 0) { int null; int len; char syn_and_dst[CMDLEN]; len = snprintf(syn_and_dst,CMDLEN,"tcp[tcpflags] & (tcp-syn) != 0 and dst %s",host); if (len > CMDLEN) { perror("host argument too long"); exit(1); } /* child writes into pipe */ close(fd[0]); dup2(fd[1],STDOUT_FILENO); /* throw away first two lines of tcpdump output */ null = open("/dev/null",O_WRONLY); if (null == -1) { perror("Can't open /dev/null"); exit(1); } dup2(null,STDERR_FILENO); execl("/usr/sbin/tcpdump","tcpdump","-l","-n","-s 96","-i",interface,syn_and_dst,(char *) NULL); /* can't reach */ perror("Cannot execute tcpdump"); exit(1); } else { /* parent reads from pipe */ close(fd[1]); return fd[0]; } } int main(int argc,char *argv[]) { int tcpdump; char *host; char *interface; long interval; while (1) { int option_index; int c; static struct option opts[] = { {"host",required_argument,NULL,'h'},{"interface",'i'},{"interval",'n'},{0,0},}; c = getopt_long(argc,argv,"",opts,&option_index); if (c == -1) break; switch (c) { case 'h': host = strdup(optarg); break; case 'i': interface = strdup(optarg); break; case 'n': { char *endptr; interval = strtol(optarg,&endptr,10); if (!(optarg[0] != ' ' && endptr[0] == ' ')) { fprintf(stderr,"Expected integer; invalid" " input '%s'n",optarg); exit(1); } } break; default: fprintf(stderr,"Option parsing errorn"); exit(1); } } if (optind < argc) { fprintf(stderr,"unexpected arguments: "); while (optind < argc) { fprintf(stderr,"%s ",argv[optind++]); } fprintf(stderr,"n"); } tcpdump = spawn_tcpdump(host,interface); install_handler(); alarm(interval); while(1) { if (show_stats) { printf("%ld requests in %ld seconds; average %2.2f req/seqn",counter,interval,(double)counter / (double)interval); counter = 0; show_stats = 0; alarm(interval); } else { char buffer[TCPDUMPLEN]; int ret; memset(buffer,TCPDUMPLEN); ret = read(tcpdump,buffer,TCPDUMPLEN); if (ret == -1 && errno == EINTR) { /* nop */ } else if (ret == -1) { perror("read"); exit(1); } else { counter += count_lines(buffer,ret); } } } exit(0); } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |