大家好,我是飞哥!
前段时间飞哥参加了一期 OSChina 官方举办的「高手问答」栏目。在这个栏目里,我和 OSChina 的网友们以《深入理解 Linux 网络》为主题,对大家日常所关心的一些问题展开了一些技术探讨。
今天我把这个活动中探讨的内容都记录下来,分享给大家!
问题1:虚拟化时代,65535 的端口号更不够用了吧?
问:一个 linux 最多能 65535 个端口,那么在虚拟化盛行的现在,这个 65535 更容易被占满了吧,怎么处理?
答:首先一个 linux 最多能 65535 个端口的说法是不确切的。因为即使在一台 Linux 上也是可以配置多 ip 的,每个 ip 都可以有 65535个 端口可用。
另外再说说现代的虚拟化。在 2008 年发布的 Linux2.6.24 内核版本里,引入了一个叫网络命名空间的东东。这个就是现代容器虚拟化的基石。在每一个命名空间里,都可以拥有自己独立的 ip、端口号、路由表等等网络资源。对于现在常用的 docker ,一个 docker 里就对应一个网络命名空间(非host模式下)。每个容器都是 65536 个端口可用的。
另外还有一个要知道的是,如果连接不同的服务器端的时候,即使只有一个 ip,同一个端口号也是可以用于连接不同的服务端的。所以不要担心 65535 的限制。
问题2:访问本机的 ip 会通过交换机或者路由器吗?
问:ip 填写自己本机的 ip 会通过交换机或者路由器吗。
答:不会的,你可以试试,无论是使用本机 ip,还是 127.0.0.1 都是只过回环设备 lo。通过在 lo 上抓包即可看到,而在真正的物理网卡下是抓不到包的。
问题3:服务器端只有一个端口,收发请求不会乱吗?
问:老师我本来没觉得我不明白 但是看了上面 列举的问题 <一台机器最多能支持多少条 TCP 连接>就有点疑惑了 就是服务器作为接收 WEB 或者其他端请求时 不管是 80 还是 443, 对外暴露的基本上是一样的端口,http请求来了之后 请求之间不会相互干扰吗?或者同一个端口可以有多少个http请求,我自己都凌乱了,谢谢老师!
答:我们分三步来理解你说的问题。
第一、服务器端在接收到新连接的时候会创建新的 socket 出来。这个新的socket 上有完整的四元组(内部源 IP、源端口、目的 IP 和目的端口)信息,并以 hashtable 的方式管理。
第二、TCP 网络包体内部源 IP、源端口、目的 IP 和目的端口等信息都是携带在包头里的。
第三。内核在接收到网络包的时候,在协议栈处理的时候会解析包头,根据这个包头中完整的四元组和内核中 hashtable 中管理的 socket 进行匹配,只有四元组信息完全一致,才能把接收到的数据放到该 socket 的接收队列中。不同的请求的 socket 上四元组信息并不完全一致,所以请求之间不会相互干扰。
问题4:网上著名的 C10K 并发连接问题 具体是怎么回事?
问:网上著名的 C10K 并发连接问题 具体是怎么回事?
答:C10K 问题算是历史上的一个问题,在 Linux 上最早的开发模型里,只有线程编程模型,来一个用户就需要使用一个进程来处理。但随着互联网发展的井喷,服务器端要支持的并发数越来越高。如果还继续沿用这个模型的话,就需要投入巨量的服务器资源。所以 C10K 问题的提出,就是要处理如何让一台服务器同时处理 1 万个用户连接请求。在 epoll 诞生以后,C10K 已经不是问题了。
问题5:网络丢包该如何排查
问:刚好遇到疑似 TCP 传输丢包的问题,想请教老师科普下这种问题排查的整体思路和顺序是什么
答:TCP 传输丢包问题使用 tcpdump 抓包看看,看看重试是如何发生的,使用 wireshark 打开,使用过滤器 tcp.analysis.retransmission 找到重传的包。还有一个基于 eBPF 的轻量级工具 tcpretrans ,也可以试试。不过 eBPF 对 Linux 版本要求较高。
问题6:一台机器最多能支持多少条 TCP 连接?
问:一台机器最多能支持多少条 TCP 连接? 这个公式是什么?怎么计算,64GB 的 Linux 服务器,可以支持多少条?
答:一台机器最多能支持多少条 TCP 连接。只说服务器端吧,一是受限于 Linux 里配置的可打开文件句柄数等内核参数,但这些都很好修改,调几个参数就行了。二就是内存了,这个是硬性限制。最少也得是 3.3 KB 左右。所以如果算极限情况下的TCP连接数,64 GB 除以 3.3KB 就行了。但一般都会给收发缓存区以及其它应用留一些 buffer
问题7:一条 TCP 需要消耗多大的内存
问:一条 TCP 连接需要消耗多大的内存 ,像mysql这种连接数,和用户登录这种 session 信息,也是一条 tcp 连接吗?
答:TCP 连接在内核里消耗内存主要是两块,一是表示 TCP 连接的 socket,大约是 3.3K 左右。二是接收和发送数据的缓存区,这个可大可小,大了收发速度更快,小了更省内存。但在较新的版本里,只要收发结束,内存就都可以回收了。你说的 mysql 的用户登录、session 等信息这个数据 TCP 里传输的数据。这个数据就看用户进程里是怎么存储的了,如果存在内存里就占内存,存到磁盘里就占磁盘。
问题8:CPU 飙高到 100%
问:老师好,我的线上服务总是莫名其妙 CPU 飙高到 100%,然后到某一个时刻突然掉下来,内存和 IO 几乎都正常值,请问应该从哪方面入手排查呢?
答:这个就得具体问题具体分析了。得看看是用户态内存消耗的高,还是内核态消耗的高。相关的命令有 top、vmstat、sar、mpstat 等。如果是内核态就用 strace 命令统计一下系统调用的耗时情况,看有没有耗时特别长的。还可以考虑使用 perf 火焰图分析一下。
问题9:有没有推荐网络调优和监控的工具
问:请问张老师, 有没有推荐网络调优和监控的工具。
答:网络比较复杂,最好先了解它内部的工作原理,看一下《深入理解Linux网络》,然后再找相应步骤的工具,可以看看《性能之巅》,这样更好一些。
问题10:net.ipv4 有非常多的属性,难道要挨个背下来?
问:net.ipv4 有非常多的属性,难道要挨个背下来?现在就处于不知道从何看起的阶段,不知道直接看您的这本书是否能帮忙建立起知识结构,能知其然且知其所以然
答:不需要背,最重要的是要理解网络工作底层工作原理,这样再看这些参数的时候就非常容易理解了。这就好比庖丁解牛,你如果对牛的骨骼肌肉的内部原理理解非常透彻的时候,你解牛的时候自然就非常容易。而不是去死记硬背这些内核参数。
咱们《深入理解Linux网络》就是这样一本介绍网络底层工作原理的书。书中会介绍到半连接队列、全连接是如何工作的,理解这个原理你就能轻松理解 syncookie 这个参数了。而且再遭遇 TCP 中的三次握手等问题的时候,你也能快速排查和定位原因了。
问题11:线上被冲垮,帮忙 review 一下
问:你好,曾经解决过一次线上服务器高峰时被冲垮的问题,原因是网络相关,靠着搜索引擎解决了后还是处于知其然不知其所以然的情况,麻烦帮忙 review 下
首先高峰被冲垮,看了 mysql ,程序都没异常,怀疑是网络问题。然后 netstat -n | awk 统计各种tcp连接状态的数量,发现别的都很少,established 单机上万了,time_wait 也非常高。带宽直接被打满
然后修改 file-max 和 sysctl 配置了如下和一些其他属性后,time_wait 瞬间下降。
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
最后又加上 nginx ip 限流解决。虽然搜索到了生效的几个 net.ipv4 配置的意思,但是依然不知道为什么会有这么多的 time_wait
答:你的问题的根本原因是在大流量(可能是攻击流量)请求的情况下使用了短连接。每一个短连接的主动释放连接的一方的 socket 都不会直接消失,而是会先释放一部分内核对象后进入 TIME_WAIT 状态,然后这个 socket 会一直占用一个端口号大约 2 分钟左右。recycle 和 reuse 的共同的作用都是尽量减少 socket 在 TIME_WAIT 上呆的时间,这样就能尽快释放端口。尽快地退出 TIME_WAIT 可以释放端口,保证后面的用户来的时候,服务器请求如 mysql 等数据服务器的时候,可以有充足的端口可用。
问题12:Linux 网络连接建立以后,在文件层发生的变化是什么样的?
问:Linux 网络连接建立以后,在文件层发生的变化是什么样的?都说linux中所有的东西是文件,我如何通过网络连接去寻找该连接对应的文件?是一个文件还是多个文件?
答:linux一切皆是文件,说的其实是一个 struct file 结构体。磁盘上的文件,socket 都有这样一个 struct file 对象,是一个内核上层的抽象。
但是在内核底层上磁盘文件、socket 还是完完全全不一样的东西。cat命令也并不能把一个socket中的数据内容给展示出来。如果你非得想用类似 cat 的功能,linux 下有个 ncat 命令你可以玩玩。
服务器端
# ncat -v -lp 8081
Ncat: Version 6.40 ( http://nmap.org/ncat )
......
hello world
客户端
# nc -v 127.0.0.1 8081
Ncat: Version 6.40 ( http://nmap.org/ncat )
Ncat: Connected to 127.0.0.1:8081.
hello world
问题13:有没有通用的线上配置核心参数
问:关于连接和性能瓶颈,线上我们经常是遇到问题再去搜方案,有没有通用的必须要在线上配置的核心参数呢。
答:通用的其实内核都已经用默认值的方式给弄好了。无奈业务之间差异太多,所以想一套参数适配所有的业务,基本上还是不可能的。还得靠工程师根据当前业务的特点来适当灵活调整
想看这次活动的同学可以点击左下角的「阅读原文」!