查看一个socket的开始时间
问题起源
有一个服务分布在3个数据中心, 有一个统一的FQDN(svc1.vip.tianxioahui.com)让别人去访问它, 同时每个数据中心都有一个单独的IP来访问该服务, 也就是说这个域名能解析到3个不同的IP. 有一次某个数据中心的该服务出现了点问题, 于是对应的IP被从DNS服务器上临时去掉了. 当问题修复之后, DNS服务器上恢复对应的IP, 该数据中心的流量却没有恢复, 还是流向了其它2个数据中心. 问题到底出现在哪呢?
初步调查
该服务的使用方是我们内部的一个服务, 于是我们首先检查客户端的DNS解析. 同时, 我们的DNS服务器会根据查询者所在的数据中心首先返回本数据中心的IP, 当没有对应数据中心的IP之后, 才会返回不同的数据中心的IP.
正常情况下的服务访问情况:
当 DC-C 的服务出问题的时候:
于是我们登录之前出问题数据中心某个客户端, 查询 DNS 解析情况, 发现查询的结果就是已经恢复的数据中心的IP, 也就是DNS解析已经完全恢复.
于是通过 ss 去查看现存的tcp连接, 发现确实是连接到其它数据中心的.
为什么恢复后还连接到其它数据中心?
首先经过连续多次测试, DNS解析的结果仍然是当前数据中心的IP, 所以DNS解析完全是正常的. 所以怀疑这个连接是之前早就建立好的, 并且一直 keep-alive, 所以一直还是正常在用的.
如何确定这个连接已经存活多久了?
我们想通过最简单的方式: ss 命令, 看看它是否提供了一个tcp连接的开始时间man ss
答案是, 并没有.
于是, 我们找到这篇: https://superuser.com/questions/565991/how-to-determine-the-socket-connection-up-time-on-linux
这个问题的最高评答案里面给的过程是:
- 找到这个tcp连接所在的进程
和proc文件系统的inode - 然后使用
stat
命令去查看文件的最后访问时间(回答里用的是: query the file access time of the symbolic link)
然而这个并不是socket uptime, 而是socket最后的访问时间, 可是那个shell函数又命名为suptime, 真是对不上.
但是, 他使用stat
访问文件的创建时间是对的
文件创建时间
通常情况下,使用stat都能查看文件的创建时间, 比如:
supra@suprabox:~$ stat ./bootstrap.sh
File: ./bootstrap.sh
Size: 4162 Blocks: 16 IO Block: 4096 regular file
Device: fd01h/64769d Inode: 10763859 Links: 1
Access: (0775/-rwxrwxr-x) Uid: ( 1000/ supra) Gid: ( 1000/ supra)
Access: 2022-11-22 19:06:03.507882931 -0800
Modify: 2022-11-22 19:05:59.487695031 -0800
Change: 2022-11-22 19:05:59.491695212 -0800
Birth: 2022-11-22 19:05:59.487695031 -0800
上面最后一行 Birth 就是它的创建时间.
查看socket inode的创建时间
其实上面输出中的 Birth 是在 inode 的元数据里的, 所以, 如果我们按照那个答案的方法去访问socket虚拟文件的inode是不是就找到了socket 的创建时间?
sudo ss -t -p -e
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
ESTAB 0 0 10.249.64.103:ssh 10.226.199.52:61340 users:(("sshd",pid=812231,fd=4),("sshd",pid=812101,fd=4)) timer:(keepalive,54min,0) ino:2211652 sk:5063 cgroup:/system.slice/ssh.service <->
ss
命令通过制定 -p 参数, 现实进程号和fd信息(pid=812101,fd=4), 通过-e参数, 显示inode 信息(ino:2211652). 于是, 我们可以查看这个虚拟文件的inode 信息了
supra@suprabox:~$ sudo stat /proc/812101/fd/4
File: /proc/812101/fd/4 -> socket:[2211652]
Size: 64 Blocks: 0 IO Block: 1024 symbolic link
Device: 17h/23d Inode: 2228948 Links: 1
Access: (0700/lrwx------) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2023-02-11 01:51:35.510079439 -0800
Modify: 2023-02-11 01:51:26.442196746 -0800
Change: 2023-02-11 01:51:26.442196746 -0800
Birth: -
可是Birth 这行是空.
文件的符号链接指向 socket:[2211652], 这个方括号里面的值就是我们通过ss查看得到的 inode id.
同时, 我们去查看 cat /proc/net/tcp
也能看到一样的行
最终, 也没找到一个可以查看socket创建时间的命令.