zabbix4.4监控案例之TCP连接状态监控

这一节我们继续介绍如何通过zabbix监控TCP的连接状态。TCP的连接状态,一般在排查问题的时候会提高很好的参考依据。可能首先你会想到netstat这个我们经常使用的命令,当然一般服务器的连接量级不会太大,你可能感觉不到明显的区别。但是当你的服务器连接数好几万的时候,不仅这个统计时间会比较久而且CPU会占用特别狠,如果你又统计的很频繁如一分钟统计一次,你就会发现这并不是一个很好的方案了。

下面我们先来看看什么是TCP连接状态?一个连接从开始建立到断开,经历了一连串的状态变化,下面状态变迁图详细的展示了TCP连接的过程:

img

客户端的状态变迁:CLOSED–>SYN_SENT–>ESTABLISHED–>FIN_WAIT_1–>FIN_WAIT_2–>TIME_WAIT–>CLOSED
服务器的状态变迁:CLOSED–>LISTEN–>SYN_RCVD–>ESTABLISHED–>CLOSE_WAIT–>LAST_ACK—>CLOSED
CLOSED:这个状态不是一个真正的状态,是图中假想的一个起点或者是终点
LISTEN: 服务器等待连接过来的状态
SYN_SENT: 客户端发起连接(主动打开),变成此状态,如果SYN超时,或者服务器不存在直接CLOSED
SYN_RCVD:服务器收到SYN包的时候,就变成此状态,
ESTABLISHED:完成三次握手,进入连接建立状态,说明此时可以进行数据传输了
FIN_WAIT_1:客户端执行主动关闭,发送完FIN包之后便进入FIN_WAIT_1状态
FIN_WAIT_2:客户端发送FIN包之后,收到ACK,即进入此状态,其实就是半关闭的状态
TIME_WAIT:这个状态从图上看,有3中情况,从FIN_WAIT_2进入,客户端收到服务器发送过来的FIN包之后进入TIME_WAIT状态,有CLOSING状态进入,这是同时关闭的状态,同时发起FIN请求,同时接收并做了ACK的回复,从FIN_WAIT_1进入,收到对端的FIN,ACK,并回复ACK,这个地方感觉是,FIN和ACK是一块来的.
CLOSE_WAIT:接收到FIN之后,被动的一方进入此状态,并回复ACK
LAST_ACK:被动的一端发送FIN包之后 处于LAST_ACK状态
CLOSING:两边同时发出FIN请求

img

1、TCP连接状态监控项

了解了TCP的连接状态以后、我们继续来看看TCP连接状态具体的监控项:

  • ESTABLISHED socket已经建立连接
  • CLOSED socket没有被使用,无连接
  • CLOSING 服务器端和客户端都同时关闭连接
  • CLOSE_WAIT 等待关闭连接
  • TIME_WAIT 表示收到了对方的FIN报文,并发送出了ACK报文,等待2MSL后就可回到CLOSED状态
  • LAST_ACK 远端关闭,当前socket被动关闭后发送FIN报文,等待对方ACK报文
  • LISTEN 监听状态
  • SYN_RECV 接收到SYN报文
  • SYN_SENT 已经发送SYN报文
  • FIN_WAIT1 socket关闭, 连接停止
  • FIN_WAIT2 连接停止, socket正在等待远程端关闭

2、创建监控脚本

其实为了解决netstat的低效问题、我们常用的方案是通过ss来进行查看。ss命令用于显示socket状态。 他可以显示PACKET sockets,TCP sockets,UDP sockets,DCCP sockets,RAW sockets,Unix domain sockets等等统计。它比其他工具展示等多tcp和state信息. 它是一个非常实用、快速、有效的跟踪IP连接和sockets的新工具。很多流行的Linux发行版都支持ss以及很多监控工具使用ss命令。熟悉这个工具有助于我们更好的发现与解决系统性能问题。这里我们使用ss命令替代netstat部分命令,例如netsat -ant/lnt等。

比如我们可以使用 ss -antp |awk ‘{a[$1]++}END{print a[“ESTAB”]}’ 命令查看已建立连接:

img

代码含义解析:

ss -antp详细的展示了TCP当前的所有连接和状态、那么我们可以通过 ss -antp |awk ‘{print $1}’ 命令中的awk过滤出第一列的数据。

img

img

然后我们把获取到的第一列数据写入 awk 数组中、通过++的方式进行计数统计;然后通过for循环的方式取出数组:

ss -antp |awk '{a[$1]++}END{for(i in a)print i,a[i]}'

img

上面就是我们期望得到的值,但是这里我们希望脚本能写的更灵活一点、如果我们传入的是LISTEN、那么就就显示LISTEN。例如下面就是我们最终需要的效果:

ss -antp |awk '{a[$1]++}END{print a["ESTAB"]}'

img

这里我们还是通过UserParmeter的方式进行参数的获取。在 /usr/local/zabbix/etc/zabbix_agentd.conf 配置文件中添加如下配置,添加完成以后重启zabbix_agentd客户端:

UserParameter=tcp.status[*],ss -antp |awk '{a[ParseError: KaTeX parse error: Expected 'EOF', got '}' at position 5: 1]++}̲END{print a["'1'"]}'

img

注:通过tcp.status[*],传入一个值给ss,然后通过写入awk数组进行循环计数、就是我们最终要的效果啦。

然后我们继续通过 zabbix_get 工具测试能不能我们所需要的参数:

/usr/local/zabbix/bin/zabbix_get -s 127.0.0.1 -p 10050 -k "tcp.status[ESTAB]"

img

成功拿到参数之后我们就可以去创建监控模板了。

3、创建监控模板

这里我们还是同样创建TCP Status监控模板、并写入对应的键值、具体如下:

img

4、应用监控模板

模板创建完成以后、我们和对应的主机进行关联,然后我们就可以拿到数据啦:

img

5、最终展示效果

img

注:最后讲一下关于触发器、这里的TCP连接数和前面几个小节都没有具体讲到关于触发器,触发器可以根据自己的需求来进行配置。但是个人觉得还是要在模板里面加入宏的概念,比如你定了个连接数1000就报警,但是有的机器连接数就是要上万的,对于那些连接数就是上万的机器呢,你都引用模板了触发器的阀值又没办法单独更改,所以引用宏变量是一个不错的解决方案。

推荐文章