故障发散-Recv-Q阻塞

2021/5/17 18:28:35

本文主要是介绍故障发散-Recv-Q阻塞,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

之前有个开发遇到个生产问题,开发发现有时候CS之间的心跳直接丢了,查看日志发现客户端一直没收到心跳报文,但服务端其实已经把报文发了,觉得很奇怪,TCP 是可靠链接,不可能丢了吧,最终是发现了netstat 里的recv-q 有积压导致的,问题虽然解决了,但还是需要复盘一下,看看细节。
先看下啥是Recv-Q 和 Send-Q

Recv-Q

Established: The count of bytes not copied by the user program connected to this socket. Listening: Since Kernel 2.6.18 this column contains the current syn backlog.
单位是字节,是表示程序总共还有多少字节的数据没有从内核空间的套接字缓存拷贝到用户空间。

Send-Q

Established: The count of bytes not acknowledged by the remote host. Listening: Since Kernel 2.6.18 this column contains the maximum size of the syn backlog.
单位是字节,是表示远程主机还没有ack的数据包的大小。

这2个Q本质上操作的数据其实是socket 上的缓存数据以及用户进程的缓存数据,对应的分别是recv() 和 send() 方法, 之后的发送接收都是纯TCP来操作的,和socket关系了,所以一般发现recv-q 阻塞了,其实和tcp关系已经不大了,因为tcp的可靠性让服务器的socket 收到了来对对端的数据,但因为某些原因,应用程序没有从socket的缓存 上读数据,导致了socket的buffer 慢慢积压,堆满,这时候,tcp会告知发送方,接收端窗口大小关闭了(win=0),这个操作保证了socket 缓存不会溢出,如果发送端不管窗口大小,强行发送超过窗口大小的数据,则tcp会直接丢弃该报文。

一般可以socket 缓存区满了可以检查代码,是不是存在链接泄露等问题,如果不是,则可以考虑修改内核提高linux的性能。

基于这种场景的TCP 的性能优化

socket 缓冲区阻塞,优化思路无非就是加大缓冲区的大小,加快tcp的回收,

#网络kernel socket 预留的发送缓冲的内存数量,分为读写,单位是字节。
net.core.rmem_default = 16777216
net.core.rmem_max = 16777216
net.core.wmem_default = 16777216
net.core.wmem_max = 16777216

# tcp socket 预留的缓存,分为三个字段,min, default, max,单位是字节
net.ipv4.tcp_rmem = 4096 873800 16777216
net.ipv4.tcp_wmem = 4096 873800 16777216

# 调整TCP的内存大小,其单位是页,1页等于4096字节,分为三个字段,low, pressure, high
# low:当TCP使用了低于该值的内存页面数时,TCP不会考虑释放内存。
# pressure:当TCP使用了超过该值的内存页面数量时,TCP试图稳定其内存使用,进入pressure模式,当内存消耗低于low值时则退出pressure状态。
# high:允许所有tcp sockets用于排队缓冲数据报的页面量,当内存占用超过此值,系统拒绝分配socket,后台日志输出"TCP: too many of orphaned sockets"。
# 根据下面high tcp_mem的值进行计算,当tcp 占用内存超过 16777216*4096/1024/1024=65536MB 的时候,就会开始报错 
net.ipv4.tcp_mem = 6177504 8236672 16777216

# somaxconn是指服务端所能accept即处理数据的最大客户端数量,即完成连接上限,
net.core.somaxconn = 1024

#tcp_max_syn_backlog是指定所能接受SYN同步包的最大客户端数量,即半连接上限, 有些文章建议也调大这个参数,个人理解是因为在三次握手完成之前socket就存在了,所以在send()和recv() 之前,connect()到appect()之间,如果有大量的半开链接,也会导致类似的问题,但应该不会造成recv-q的阻塞。
tcp_max_syn_backlog = 2048
  • 补一个socket 和 tcp 之间的关系
SOCKET:

TCP-SOCKET:

TCP-SOCKET

个人公众号, 分享一些日常开发,运维工作中的日常以及一些学习感悟,欢迎大家互相学习,交流

在这里插入图片描述



这篇关于故障发散-Recv-Q阻塞的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程