设为首页收藏本站

ZMX - IT技术交流论坛 - 无限Perfect,追求梦想 - itzmx.com

 找回密码
 注册论坛

QQ登录

只需一步,快速开始

新浪微博账号登陆

只需一步,快速开始

用百度帐号登录

只需两步,快速登录

搜索
查看: 5260|回复: 1

Linux服务器高并发效率应用中出现ping icmp tcp等丢包故障的解决思路和方法。nf_conntrack连接跟踪表溢出优化,openvz商家注意啦!table full, dropping packet

[复制链接]
 成长值: 51

签到天数: 4511 天

[LV.Master]伴坛终老

发表于 2018/11/19 03:03 | 显示全部楼层 |阅读模式 |Google Chrome 70.0.3538.102|Windows 10
天涯海角搜一下: 百度 谷歌 360 搜狗 有道 雅虎 必应 即刻
Linux服务器高并发效率应用中出现ping icmp tcp等丢包故障的解决思路和方法。nf_conntrack连接跟踪表溢出优化,openvz商家注意啦!table full, dropping packet

连接跟踪表溢出
连接跟踪表nf_conntrack,Linux为每个经过内核网络栈的数据包,生成一个新的连接记录项,当服务器处理的连接过多时,连接跟踪表被打满,服务器会丢弃新建连接的数据包。

如何确认
通过dmesg可以确认是否有该情况发生
  1. dmesg | grep nf_conntrack
复制代码


2.png

如果输出值中有“nf_conntrack: table full, dropping packet”,说明服务器nf_conntrack表已经被打满。


通过/proc文件系统查看nf_conntrack表实时状态:
跟踪连接详细信息:
  1. cat /proc/net/nf_conntrack
复制代码


查看nf_conntrack表最大连接数
  1. cat /proc/sys/net/netfilter/nf_conntrack_max
复制代码


查看nf_conntrack表当前连接数
  1. cat /proc/sys/net/netfilter/nf_conntrack_count
复制代码


查看nf_conntrack_buckets哈希表最大大小(对应内核参数net.netfilter.nf_conntrack_buckets)
  1. cat /proc/sys/net/netfilter/nf_conntrack_buckets
复制代码


查看netfilter相关的内核参数
  1. sysctl -a | grep conntrack
复制代码



1.png

如果确认服务器因连接跟踪表溢出而开始丢包,首先需要判断是否正遭受DDOS攻击,如果是正常的业务流量造成,可以考虑调整nf_conntrack的参数

nf_conntrack_max决定连接跟踪表的大小,默认值是65536,可以根据系统内存大小计算一个合理值:CONNTRACK_MAX = RAMSIZE(in bytes)/16384(65536/4),如16G内存可以设置1048576;
一个连接占用320字节(0.3KB)内存,65536大约20MB系统内存占用,存储在内核空间,这部分内存不能swap,当CONNTRACK_MAX为 1048576,HASHSIZE buckets为 262144 时,最多占320MB系统内存开销,对现在的vps服务器来说毫无压力,你用512M的vps跑mysql业务当我没说。
nf_conntrack_buckets决定存储conntrack条目的哈希表大小,默认值是nf_conntrack_max的1/4,延续这种计算方式:BUCKETS = CONNTRACK_MAX/4,如16G内存可以设置262144;
net.netfilter.nf_conntrack_tcp_timeout_established  # 决定ESTABLISHED状态连接的超时时间,默认值是5天,可以缩短到1小时,即3600,不推荐修改这个设置,会导致游戏服务器出现玩家1小时立即出现掉线情况。
net.netfilter.nf_conntrack_tcp_timeout_fin_wait  # 默认 120 秒
net.netfilter.nf_conntrack_tcp_timeout_time_wait  # 默认 120 秒,可以适当修改这个值
net.netfilter.nf_conntrack_tcp_timeout_close_wait  # 默认 60 秒,CLOSE_WAIT是被动方收到FIN发ACK,然后会转到LAST_ACK发FIN,除非程序写得有问题,正常来说这状态持续时间很短。
net.netfilter.nf_conntrack_generic_timeout  # 默认 600 秒(10分钟)通用超时设置,作用于4层(传输层)未知或不支持的协议
net.netfilter.nf_conntrack_tcp_timeout_max_retrans  # 默认 300 秒
net.netfilter.nf_conntrack_tcp_timeout_unacknowledged  # 默认 300 秒
推荐bucket至少 262144,max至少 1048576,不够再继续加,或者缩短ESTABLISHED超时时间可以让netfilter更快地把跟踪的记录从哈希表里移除。


哈希表使用情况:
  1. grep conntrack /proc/slabinfo
复制代码

前面三个数字代表
当前活动对象数、当前使用对象总数、每个对象的内存占用大小(单位字节)

  1. sysctl -w net.netfilter.nf_conntrack_max=1048576
  2. sysctl -w net.netfilter.nf_conntrack_buckets=262144
复制代码

通过sysctl -w的命令,是临时生效的,重启会复原


如果报错,因为iptables防火墙没有开启,模块无法自动载入,可以手动载入并且开机执行模块,执行命令(注意,未开启防火墙处于开机自启默认禁用状态时不会受到nf_conntrack影响导致问题限制引起丢包:https://bbs.itzmx.com/thread-91880-1-1.html
  1. modprobe nf_conntrack
  2. echo "modprobe nf_conntrack" >> /etc/rc.d/rc.local
复制代码



问题解决
QQ图片20181119025850.png


也可以编辑文件添加:/etc/sysctl.conf,实现开机自动生效。
  1. net.netfilter.nf_conntrack_max = 1048576
  2. net.netfilter.nf_conntrack_buckets = 262144
复制代码

修改后,执行sysctl -p 生效
开机自动修改


特别是卖openvz虚拟化的商家注意了,几百几千个用户小鸡公用内核,母鸡上不调好,等着丢包卡顿等问题,至少也要保证1048576,想想系统默认65536,几百上千个用户公用够用吗?
母鸡配置富裕点的话,max直接给9999999吧(跑满1000W会消耗3GB系统内存),毕竟母鸡呢,好比我这个论坛,晚上2点钟占用都有40W,下午8点-晚上1点高峰期的时候,基本上都有60W占用。
1.png
一个有点B数的用户网站,随便都能上10-20W不等左右。
推销啦(论坛自建CDN用的就是,稳定快一年了,国人学生开的,跑路自负,定期备份数据):https://www.cfhost.cn/aff.php?aff=75
10元每个月ovh直连 速度快,咖啡主机家的法国OVH母鸡已经调到1048576,适合跑访问频率大的网站,抗攻击等。

QQ图片20181120012314.png

3.png

QQ图片20181120011854.png

参考文章:http://blog.51cto.com/wujingfeng/2096885




下方内容转:
Ring Buffer溢出问题
我们从底向上来看Linux接收数据包的处理过程,首先是网卡驱动层。
如下图所示,物理介质上的数据帧到达后首先由NIC(网络适配器)读取,写入设备内部缓冲区Ring Buffer中,再由中断处理程序触发Softirq从中消费,Ring Buffer的大小因网卡设备而异。当网络数据包到达(生产)的速率快于内核处理(消费)的速率时,Ring Buffer很快会被填满,新来的数据包将被丢弃。
linux-server-packet-fig-1.png
如何确认
通过ethtool -S eth0 | grep fifo或者cat /proc/net/dev可以查看因Ring Buffer满而丢弃的包统计,在统计项中以fifo标识:
[root@bb ~]# ethtool -S eth1 | grep fifo
     tx_fifo_errors: 0
[root@bb ~]# cat /proc/net/dev
Inter-|   Receive                                                |  Transmit
face |bytes    packets errs drop fifo frame compressed multicast|bytes    packets errs drop fifo colls carrier compressed
    lo: 21533986276 83326362    0    0    0     0          0         0 21533986276 83326362    0    0    0     0       0          0
  eth0:       0       0    0    0    0     0          0         0        0       0    0    0    0     0       0          0
  eth1: 5271207500825 39566446333    0    0    0     0          0        13 7351838993221 30688577117    0    0    0     0       0          0
[root@bb ~]#


可以看到服务器的接收方向的fifo丢包数并没有增加,这里自然也排除这个原因。
如何解决
如果发现服务器上某个网卡的fifo数持续增大,可以去确认CPU中断是否分配均匀,也可以尝试增加Ring Buffer的大小,通过ethtool可以查看网卡设备Ring Buffer最大值,修改Ring Buffer当前设置:

查看eth0网卡Ring Buffer最大值和当前设置
[root@bb ~]# ethtool -g eth0
Ring parameters for eth0:
Pre-set maximums:
RX:                4096
RX Mini:        0
RX Jumbo:        0
TX:                4096
Current hardware settings:
RX:                256
RX Mini:        0
RX Jumbo:        0
TX:                256
[root@bb ~]#

修改网卡eth0接收与发送硬件缓存区大小,期间网卡会重启闪断三秒。
  1. ethtool -G eth0 rx 4096 tx 4096
复制代码

Ring parameters for eth0:
Pre-set maximums:
RX:                4096
RX Mini:        0
RX Jumbo:        0
TX:                4096
Current hardware settings:
RX:                4096
RX Mini:        0
RX Jumbo:        0
TX:                4096




netdev_max_backlog溢出
netdev_max_backlog是内核从NIC收到包后,交由协议栈(如IP、TCP)处理之前的缓冲队列。每个CPU核都有一个backlog队列,与Ring Buffer同理,当接收包的速率大于内核协议栈处理的速率时,CPU的backlog队列不断增长,当达到设定的netdev_max_backlog值时,数据包将被丢弃。
如何确认
通过下方命令查看softnet_stat可以确定是否发生了netdev backlog队列溢出:
  1. cat /proc/net/softnet_stat
复制代码
34a114c4 00000000 00000ab8 00000000 00000000 00000000 00000000 00000000 00000000 00000000
006f1620 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
018d7552 00000000 00000004 00000000 00000000 00000000 00000000 00000000 00000000 00000000
0039078c 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
01125110 00000000 00000006 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00259e58 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
001cde44 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
004b861a 00000000 00000001 00000000 00000000 00000000 00000000 00000000 00000000 00000000
0134d8d2 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00919376 00000000 00000003 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00161566 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
0053727e 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00294f9e 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00464f14 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
000ea276 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
001727a2 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000


其中:
每一行代表每个CPU核的状态统计,从CPU0依次往下;
每一列代表一个CPU核的各项统计:第一列代表中断处理程序收到的包总数;第二列即代表由于netdev_max_backlog队列溢出而被丢弃的包总数。
从上面的输出可以看出,这台服务器统计中,并没有因为netdev_max_backlog导致的丢包。

如何解决
netdev_max_backlog的默认值是1000,在高速链路上,可能会出现上述第二列统计不为0的情况,可以通过修改内核参数net.core.netdev_max_backlog来解决:
  1. sysctl -w net.core.netdev_max_backlog=2000
复制代码





反向路由过滤
反向路由过滤机制是Linux通过反向路由查询,检查收到的数据包源IP是否可路由(Loose mode)、是否最佳路由(Strict mode),如果没有通过验证,则丢弃数据包,设计的目的是防范IP地址欺骗攻击。rp_filter提供了三种模式供配置:

0 - 不验证
1 - RFC3704定义的严格模式:对每个收到的数据包,查询反向路由,如果数据包入口和反向路由出口不一致,则不通过
2 - RFC3704定义的松散模式:对每个收到的数据包,查询反向路由,如果任何接口都不可达,则不通过
如何确认
查看当前rp_filter策略配置:
  1. cat /proc/sys/net/ipv4/conf/eth0/rp_filter
复制代码

1

如果这里设置为1,就需要查看主机的网络环境和路由策略是否可能会导致客户端的入包无法通过反向路由验证了。
从原理来看这个机制工作在网络层,因此,如果客户端能够Ping通服务器,就能够排除这个因素了。

如何解决
根据实际网络环境将rp_filter设置为0或2:
  1. sysctl -w net.ipv4.conf.all.rp_filter=2
复制代码

或者指定网卡
  1. sysctl -w net.ipv4.conf.eth0.rp_filter=2
复制代码





半连接队列溢出
半连接队列指的是TCP传输中服务器收到SYN包但还未完成三次握手的连接队列,队列大小由内核参数tcp_max_syn_backlog定义。
当服务器保持的半连接数量达到tcp_max_syn_backlog后,内核将会丢弃新来的SYN包。

如何确认
通过dmesg可以确认是否有该情况发生:
  1. dmesg | grep "TCP: drop open request from"
复制代码


半连接队列的连接数量可以通过netstat统计SYN_RECV状态的连接得知
  1. netstat -ant | grep SYN_RECV|wc -l
复制代码

1024

大多数情况下这个值应该是0或很小,因为半连接状态从第一次握手完成时进入,第三次握手完成后退出,正常的网络环境中这个过程发生很快,如果这个值较大,服务器极有可能受到了SYN Flood攻击。

如何解决
tcp_max_syn_backlog的默认值是1024,增加方法同样,该参数通过sysctl修改:
  1. sysctl -w net.ipv4.tcp_max_syn_backlog=8192
复制代码


另外,上述行为受到内核参数tcp_syncookies的影响,若启用syncookie机制,当半连接队列溢出时,并不会直接丢弃SYN包,而是回复带有syncookie的SYC+ACK包,设计的目的是防范SYN Flood造成正常请求服务不可用。
  1. sysctl -w net.ipv4.tcp_syncookies=1
复制代码



同时大概率还遇到另一种系统内核限制
Linux服务器并发连接数高时dmesg 内核报错TCP: too many orphaned sockets socket端口号过多导致系统内存资源用尽 引起高丢包ping超时 tcp_mem计算方式
https://bbs.itzmx.com/forum.php?mod=viewthread&tid=100689&fromuid=1

欢迎光临IT技术交流论坛:http://bbs.itzmx.com/
回复

使用道具 举报

 成长值: 51

签到天数: 4511 天

[LV.Master]伴坛终老

发表于 2019/1/22 21:46 | 显示全部楼层 |Google Chrome 71.0.3578.98|Windows 10
联系openvz商家模板
I checked the gateway through mtr: 185.243.56.1 without any problems
But there is a problem with vps IP, it should be that the server's nf_conntrack is full.
You can confirm if this happens by dmesg

dmesg | grep nf_conntrack

"nf_conntrack: table full, dropping packet"
Representative problem exists.

View the real-time status of the nf_conntrack table via the /proc file system:
Track connection details:
cat /proc/net/nf_conntrack

View the maximum number of connections in the nf_conntrack table
cat /proc/sys/net/netfilter/nf_conntrack_max

View the current number of connections in the nf_conntrack table
cat /proc/sys/net/netfilter/nf_conntrack_count

View the maximum size of the nf_conntrack_buckets hash table
cat /proc/sys/net/netfilter/nf_conntrack_buckets

There are usually thousands of users on openvz, kernel he is public, so you need to have a larger value.
Can optimize this value.
sysctl -w net.netfilter.nf_conntrack_max=9999999
sysctl -w net.netfilter.nf_conntrack_buckets=1048576

The sysctl -w commands are temporarily valid.

Edit the file to add: /etc/sysctl.conf, the startup will take effect automatically.
net.netfilter.nf_conntrack_max = 9999999
net.netfilter.nf_conntrack_buckets = 1048576

After modification, execute sysctl -p to take effect
boot automatically modified

After the server is finished, openvz vps reboot will get the new kernel parameters.
I can't operate to your server, I hope you can check this problem.

https://wiki.khnet.info/index.php/Conntrack_tuning
Wiki data, you can try temporary changes, restart is not necessary, he will take effect on the server immediately
The user can restart in the control panel to get new parameters.

You can check it first?
dmesg | grep nf_conntrack

Is this , it does not involve any changes.
欢迎光临IT技术交流论坛:http://bbs.itzmx.com/
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册论坛 新浪微博账号登陆用百度帐号登录

本版积分规则

手机版|Archiver|Mail me|网站地图|IT技术交流论坛 ( 闽ICP备13013206号-7 )

GMT+8, 2024/5/11 02:26 , Processed in 0.143918 second(s), 23 queries , MemCache On.

Powered by itzmx! X3.4

© 2011- sakura

快速回复 返回顶部 返回列表