用lsof+sed+uniq+sort+head正则 统计出连接Kafka连接最多的IP
继之前 《Kafka线上出口流量暴涨》一文的处理中,发现这个kafka连接数有点高。按照惯例,掐指一算,估计有程序没用线程池,或者没正确使用线程池。
问题来了,我怎么知道kafka端口哪些IP的连接最多呢?
所以要找到这个问题,我们还得找出相关的连接,给它排序一下,好直观一点。
把问题拆解一下就是
- 找出所有连接到本机 kafka端口(这里是9093)的连接
- 从连接中提取出IP
- 统计出各个IP连接的数量
- 排序从高到低
由于案发现场没有留下截图,所以以下为非案发现场的数据,看个热闹行了。
找出所有连接到本机 kafka端口(这里是9093)的连接,并提取出IP
用 netstat -an|grep :9093 或者 lsof -i:9093
我比较偏爱lsof,所以就用它来做个演示,限于篇幅,我取个前10行。
-P :不打印端口名(就是显示成数字,好看点)
-n :不打印成主机名 (就是显示IP,而不是Hostname,好看点)
从连接提取IP
正常的连接记录是这样的
java 2122 kafka 112u IPv4 160272344 0t0 TCP xxx.xxx.3.141:9093->xxx.xxx.25.35:42488 (ESTABLISHED)
java 2122 kafka 113u IPv4 166503245 0t0 TCP xxx.xxx.3.141:9093->xxx.xxx.25.35:52076 (ESTABLISHED)
java 2122 kafka 115u IPv4 166503246 0t0 TCP xxx.xxx.3.141:9093->xxx.xxx.23.33:47160 (ESTABLISHED)
我们要提取出连接过来的IP,要注意以下几点:
- xxx.xxx.3.141 是我们本机的IP,无需统计
- 忽略掉端口,就提取IP出来统计
上面的例子,我们就要提出以下数据
xxx.xxx.25.35
xxx.xxx.25.35
xxx.xxx.23.33
由于每个客户端连接都是被 -> 和 : 夹着,如 ->:
所以我们用 **sed 's/.*->\([0-9|\.]*\):.*/\1/g'** 即可提取出来
[root@java_kafka_xxx.xxx.3.141 ~]#lsof -i:9093 -P -n | sed 's/.*->\([0-9|\.]*\):.*/\1/g' | head -10
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
xxx.xxx.8.70
xxx.xxx.25.35
xxx.xxx.8.125
xxx.xxx.7.101
xxx.xxx.23.33
xxx.xxx.4.101
xxx.xxx.7.34
xxx.xxx.24.32
xxx.xxx.4.101
统计出相同行的数量
统计相同行可以用 uniq -c 但是统计都是根据相邻行进行比较,所以最好还是先 sort 排序下
接上前面那些看起来如下:
[root@java_kafka_xxx.xxx.3.141 ~]#lsof -i:9093 -P -n|sed 's/.*->\([0-9|\.]*\):.*/\1/g' | sort | uniq -c
21 xxx.xxx.23.151
13 xxx.xxx.23.152
7 xxx.xxx.23.33
7 xxx.xxx.24.32
7 xxx.xxx.25.35
7 xxx.xxx.25.46
5 xxx.xxx.25.48
2 xxx.xxx.25.49
3 xxx.xxx.25.55
2 xxx.xxx.25.56
7 xxx.xxx.25.57
20 xxx.xxx.31.151
16 xxx.xxx.31.152
2 xxx.xxx.3.140
2 xxx.xxx.3.142
193 xxx.xxx.31.77
181 xxx.xxx.31.78
8 xxx.xxx.3.84
8 xxx.xxx.3.85
453 xxx.xxx.4.101
457 xxx.xxx.4.161
468 xxx.xxx.7.101
454 xxx.xxx.7.161
5 xxx.xxx.7.34
1 xxx.xxx.8.101
2 xxx.xxx.8.109
1 xxx.xxx.8.117
1 xxx.xxx.8.125
1 xxx.xxx.8.70
1 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
1 java 2122 kafka 409u IPv4 26448 0t0 TCP xxx.xxx.3.141:9093 (LISTEN)
排序从高到低
sort -nr
-n 是按照数字从小到大排序
-r 是反向排序,这里是从大到小排序
[root@java_kafka_xxx.xxx.3.141 ~]#lsof -i:9093 -P -n|sed 's/.*->\([0-9|\.]*\):.*/\1/g' | sort | uniq -c |sort -nr
468 xxx.xxx.7.101
457 xxx.xxx.4.161
454 xxx.xxx.7.161
453 xxx.xxx.4.101
193 xxx.xxx.31.77
181 xxx.xxx.31.78
21 xxx.xxx.23.151
20 xxx.xxx.31.151
16 xxx.xxx.31.152
13 xxx.xxx.23.152
8 xxx.xxx.3.85
8 xxx.xxx.3.84
7 xxx.xxx.25.57
7 xxx.xxx.25.35
7 xxx.xxx.24.32
7 xxx.xxx.23.33
6 xxx.xxx.25.46
5 xxx.xxx.25.48
4 xxx.xxx.25.55
3 xxx.xxx.7.34
2 xxx.xxx.8.109
2 xxx.xxx.8.101
2 xxx.xxx.3.142
2 xxx.xxx.3.140
2 xxx.xxx.25.56
2 xxx.xxx.25.49
1 java 2122 kafka 409u IPv4 26448 0t0 TCP xxx.xxx.3.141:9093 (LISTEN)
1 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
1 xxx.xxx.8.70
1 xxx.xxx.8.125
1 xxx.xxx.8.117
如果有强迫症,觉得结果有参杂着非IP的行,不好看 可以在前面加个 grep "\->" 基本带 -> 都是连接的行
终极版
lsof -i:9093 -P -n | grep "\->" | sed 's/.*->\([0-9|\.]*\):.*/\1/g' | sort | uniq -c |sort -nr
[root@java_kafka_xxx.xxx.3.141 ~]#lsof -i:9093 -P -n | grep "\->" | sed 's/.*->\([0-9|\.]*\):.*/\1/g' | sort | uniq -c |sort -nr
468 xxx.xxx.7.101
457 xxx.xxx.4.161
454 xxx.xxx.7.161
453 xxx.xxx.4.101
193 xxx.xxx.31.77
181 xxx.xxx.31.78
21 xxx.xxx.23.151
20 xxx.xxx.31.151
16 xxx.xxx.31.152
13 xxx.xxx.23.152
8 xxx.xxx.3.85
8 xxx.xxx.3.84
8 xxx.xxx.25.57
8 xxx.xxx.25.35
6 xxx.xxx.25.46
6 xxx.xxx.24.32
6 xxx.xxx.23.33
5 xxx.xxx.25.48
4 xxx.xxx.7.34
4 xxx.xxx.25.55
2 xxx.xxx.8.109
2 xxx.xxx.8.101
2 xxx.xxx.3.142
2 xxx.xxx.3.140
2 xxx.xxx.25.49
1 xxx.xxx.8.70
1 xxx.xxx.8.125
1 xxx.xxx.8.117
1 xxx.xxx.25.56
至此,基本找出是哪些IP的连接最多了。
后续处理
像上一篇一样,根据端口,找出是哪些程序在连接。
找到对应应用后,看了下源码,代码问题,反复创建对象来连接,没有复用到连接。
通知开发解决问题。
上线新版本后,前后连接数对比。
|