ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

故障发散-Recv-Q阻塞

2021-05-17 17:56:53  阅读:214  来源: 互联网

标签:16777216 socket 阻塞 TCP 发散 tcp net Recv 内存


之前有个开发遇到个生产问题,开发发现有时候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

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

在这里插入图片描述

标签:16777216,socket,阻塞,TCP,发散,tcp,net,Recv,内存
来源: https://blog.51cto.com/u_2010293/2781928

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有