文档章节

关于 Out of Socket memory 的解释

miffa
 miffa
发布于 2014/11/19 11:44
字数 2614
阅读 818
收藏 9
点赞 0
评论 0

关于 Out of Socket memory 的解释

1. 原因分析

一台 Nginx server,到晚上高峰 messages 出现大量的如下信息:
Apr 23 22:43:21 rs1 kernel: [...] Out of socket memory

两种情况会出发 "Out of socket memory" 的信息:
1.有很多的孤儿套接字(orphan sockets)
2.tcp socket 用尽了给他分配的内存

首先看看情况 2。对于 TCP socket 来说,使用 pages 来计数的,而非 bytes,一般情况下 1 page = 4096 bytes。page 大小可以通过下面命令获得:
$ getconf PAGESIZE
4096

查看内核分配了多少的内存给 TCP:
$ cat /proc/sys/net/ipv4/tcp_mem
69618   92825   139236
第一个数字表示,当 tcp 使用的 page 少于 69618 时,kernel 不对其进行任何的干预
第二个数字表示,当 tcp 使用了超过 92825 的 pages 时,kernel 会进入 “memory pressure” 
第三个数字表示,当 tcp 使用的 pages 超过 139236 时,我们就会看到题目中显示的信息

查看 tcp 实际用的内存:
$ cat /proc/net/sockstat
sockets: used 116
TCP: inuse 3 orphan 0 tw 4 alloc 4 mem 110
UDP: inuse 1 mem 1
UDPLITE: inuse 0
RAW: inuse 0
FRAG: inuse 0 memory 0
可以看到,实际使用的 mem(110) 远远小于 69618,所以,“Out of socket memory”的错误是由于第一种情况引起的。

关于 orphan socket 的解释,请看这里。orphan socket 对于应用程序来说,意义不大,这也是内核要限制被 orphan socket 消耗内存的原因。而对于 web server 来说,有大量的 orphan socket 也属正常,那么多的连接放在那儿了。
查看 orphan socket 限制:
$ cat /proc/sys/net/ipv4/tcp_max_orphans

对比当前系统中的:
$ cat /proc/net/sockstat
sockets: used 14565
TCP: inuse 35938 orphan 21564 tw 70529 alloc 35942 mem 1894

由于内核代码中有个位运算,所以实际的跟最大的是 2x 或者是 4x 的关系。现在根据实际情况,将 tcp_max_orphans 调到一个合理的值就可以了。原则上该值建议只增大,另外,每个 orphan 会消耗大概 64KB 的内存。还有个叫 tcp_orphan_retries 参数,对于 web server,可以减小。

2.  tcp_mem参数调整

tcp_mem

在服务端,连接达到一定数量,诸如50W时,有些隐藏很深的问题,就不断的抛出来。 通过查看dmesg命令查看,发现大量TCP: too many of orphaned sockets错误,也很正常,下面到了需要调整tcp socket参数的时候了。

第一个需要调整的是tcp_rmem,即TCP读取缓冲区,单位为字节,查看默认值

cat /proc/sys/net/ipv4/tcp_rmem
4096 87380 4161536

默认值为87380 byte ≈ 86K,最小为4096 byte=4K,最大值为4064K。

第二个需要调整的是tcp_wmem,发送缓冲区,单位是字节,默认值

cat /proc/sys/net/ipv4/tcp_wmem
4096 16384 4161536

解释同上

第三个需要调整的tcp_mem,调整TCP的内存大小,其单位是页,1页等于4096字节。系统默认值:

cat /proc/sys/net/ipv4/tcp_mem
932448 1243264 1864896

tcp_mem(3个INTEGER变量):low, pressure, high

  • low:当TCP使用了低于该值的内存页面数时,TCP不会考虑释放内存。

  • pressure:当TCP使用了超过该值的内存页面数量时,TCP试图稳定其内存使用,进入pressure模式,当内存消耗低于low值时则退出pressure状态。

  • high:允许所有tcp sockets用于排队缓冲数据报的页面量,当内存占用超过此值,系统拒绝分配socket,后台日志输出“TCP: too many of orphaned sockets”。

一般情况下这些值是在系统启动时根据系统内存数量计算得到的。 根据当前tcp_mem最大内存页面数是1864896,当内存为(1864896*4)/1024K=7284.75M时,系统将无法为新的socket连接分配内存,即TCP连接将被拒绝。

实际测试环境中,据观察大概在99万个连接左右的时候(零头不算),进程被杀死,触发out of socket memory错误(dmesg命令查看获得)。每一个连接大致占用7.5K内存(下面给出计算方式),大致可算的此时内存占用情况(990000 * 7.5 / 1024K = 7251M)。

这样和tcp_mem最大页面值数量比较吻合,因此此值也需要修改。

三个TCP调整语句为:

echo "net.ipv4.tcp_mem = 786432 2097152 3145728">> /etc/sysctl.conf
echo "net.ipv4.tcp_rmem = 4096 4096 16777216">> /etc/sysctl.conf
echo "net.ipv4.tcp_wmem = 4096 4096 16777216">> /etc/sysctl.conf

备注: 为了节省内存,设置tcp读、写缓冲区都为4K大小,tcp_mem三个值分别为3G 8G 16G,tcp_rmemtcp_wmem最大值也是16G。

目标达成

经过若干次的尝试,最终达到目标,1024000个持久连接。1024000数字是怎么得来的呢,两台物理机器各自发出64000个请求,两个配置为6G左右的centos测试端机器(绑定7个桥接或NAT连接)各自发出640007 = 448000。也就是 1024000 = (64000) + (64000) + (640007) + (64000*7), 共使用了16个网卡(物理网卡+虚拟网卡)。 
终端输出

......
online user 1023990
online user 1023991
online user 1023992
online user 1023993
online user 1023994
online user 1023995
online user 1023996
online user 1023997
online user 1023998
online user 1023999
online user 1024000

在线用户目标达到1024000个!

服务器状态信息

服务启动时内存占用:

                 total       used       free     shared    buffers     cached
    Mem:         10442        271      10171          0         22         78
    -/+ buffers/cache:        171      10271
    Swap:         8127          0       8127

系统达到1024000个连接后的内存情况(执行三次 free -m 命令,获取三次结果):

                 total       used       free     shared    buffers     cached
    Mem:         10442       7781       2661          0         22         78
    -/+ buffers/cache:       7680       2762
    Swap:         8127          0       8127

                 total       used       free     shared    buffers     cached
    Mem:         10442       7793       2649          0         22         78
    -/+ buffers/cache:       7692       2750
    Swap:         8127          0       8127

                 total       used       free     shared    buffers     cached
    Mem:         10442       7804       2638          0         22         79
    -/+ buffers/cache:       7702       2740
    Swap:         8127          0       8127

这三次内存使用分别是7680,7692,7702,这次不取平均值,取一个中等偏上的值,定为7701M。那么程序接收1024000个连接,共消耗了 7701M-171M = 7530M内存, 7530M*1024K / 1024000 = 7.53K, 每一个连接消耗内存在为7.5K左右,这和在连接达到512000时所计算较为吻合。 
虚拟机运行Centos内存占用,不太稳定,但一般相差不大,以上数值,仅供参考。

执行top -p 某刻输出信息:

    top - 17:23:17 up 18 min,  4 users,  load average: 0.33, 0.12, 0.11

    Tasks:   1 total,   1 running,   0 sleeping,   0 stopped,   0 zombie
    Cpu(s):  0.2%us,  6.3%sy,  0.0%ni, 80.2%id,  0.0%wa,  4.5%hi,  8.8%si,  0.0%st
    Mem:  10693580k total,  6479980k used,  4213600k free,    22916k buffers
    Swap:  8323056k total,        0k used,  8323056k free,    80360k cached

      PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND                      
     2924 yongboy   20   0 82776  74m  508 R 51.3  0.7   3:53.95 server 

执行vmstate:

vmstat
procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu-----
 r b swpd free buff cache si so bi bo in cs us sy id wa st
 0 0 0 2725572 23008 80360 0 0 21 2 1012 894 0 9 89 2 0

获取当前socket连接状态统计信息:

cat /proc/net/sockstat
sockets: used 1024380
TCP: inuse 1024009 orphan 0 tw 0 alloc 1024014 mem 2
UDP: inuse 11 mem 1
UDPLITE: inuse 0
RAW: inuse 0
FRAG: inuse 0 memory 0

获取当前系统打开的文件句柄:

sysctl -a | grep file
fs.file-nr = 1025216 0 1048576
fs.file-max = 1048576

此时任何类似于下面查询操作都是一个慢,等待若干时间还不见得执行完毕。

netstat -nat|grep -i "8000"|grep ESTABLISHED|wc -l 
netstat -n | grep -i "8000" | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'

以上两个命令在二三十分钟过去了,还未执行完毕,只好停止。

小结

本次从头到尾的测试,所需要有的linux系统需要调整的参数也就是那么几个,汇总一下:

     echo "* - nofile 1048576" >> /etc/security/limits.conf

    echo "fs.file-max = 1048576" >> /etc/sysctl.conf
    echo "net.ipv4.ip_local_port_range = 1024 65535" >> /etc/sysctl.conf

    echo "net.ipv4.tcp_mem = 786432 2097152 3145728" >> /etc/sysctl.conf
    echo "net.ipv4.tcp_rmem = 4096 4096 16777216" >> /etc/sysctl.conf
    echo "net.ipv4.tcp_wmem = 4096 4096 16777216" >> /etc/sysctl.conf

其它没有调整的参数,仅仅因为它们暂时对本次测试没有带来什么影响,实际环境中需要结合需要调整类似于SO_KEEPALIVE、tcpmax_orphans等大量参数。


 sysctl -p /etc/sysctl.conf    加载修改后的tcp相关参数


附目前服务器的参数设置

echo "net.ipv4.tcp_mem = 786432 1048576 1572864" >> /etc/sysctl.conf

echo "net.ipv4.tcp_rmem = 4096 87380 8388608" >> /etc/sysctl.conf

echo "net.ipv4.tcp_wmem = 4096 87380 8388608" >> /etc/sysctl.conf

echo "net.ipv4.tcp_max_tw_buckets = 500000" >> /etc/sysctl.conf

echo "net.ipv4.tcp_tw_recycle = 1" >> /etc/sysctl.conf

echo "net.ipv4.tcp_max_orphans = 262144" >> /etc/sysctl.conf

echo "net.ipv4.tcp_max_syn_backlog = 20480" >> /etc/sysctl.conf

echo "net.ipv4.tcp_synack_retries = 1" >> /etc/sysctl.conf

echo "net.ipv4.tcp_syn_retries = 1" >> /etc/sysctl.conf

echo "net.ipv4.tcp_max_syn_backlog = 20480" >> /etc/sysctl.conf

echo "net.ipv4.tcp_synack_retries = 1" >> /etc/sysctl.conf

echo "net.ipv4.tcp_syn_retries = 1" >> /etc/sysctl.conf

 sysctl -p /etc/sysctl.conf 

内核相关参数说明如下

# TCP and memory optimization
# increase TCP max buffer size setable using setsockopt()
#it's already auto-tuned very well by Linux based on the amount of RAM.
#net.ipv4.tcp_mem = 94500000 915000000 927000000
net.ipv4.tcp_rmem = 4096 87380 8388608
net.ipv4.tcp_wmem = 4096 87380 8388608
net.ipv4.tcp_max_orphans = 3276800
net.ipv4.tcp_timestamps = 1
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_syn_retries = 2
#表示SYN队列的长度,默认为1024,加大队列长度为8192,可以容纳更多等待连接的网络连接数。
net.ipv4.tcp_max_syn_backlog = 65536
#表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0,表示关闭;
net.ipv4.tcp_syncookies = 1
#表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭;
net.ipv4.tcp_tw_reuse = 1
#表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭;
net.ipv4.tcp_tw_recycle = 1
#修改系統默认的 TIMEOUT 时间。
net.ipv4.tcp_fin_timeout = 30
#表示当keepalive起用的时候,TCP发送keepalive消息的频度。缺省是2小时,改为20分钟。
net.ipv4.tcp_keepalive_time = 1200
#表示用于向外连接的端口范围。缺省情况下很小:32768到61000,改为10000到65000。(注意:这里不要将最低值设的太低,否则可能会占用掉正常的端口!)
net.ipv4.ip_local_port_range = 10000 65000
#表示系统同时保持TIME_WAIT的最大数量,如果超过这个数字,TIME_WAIT将立刻被清除并打印警告信息。默 认为180000,改为6000。对于Apache、Nginx等服务器,上几行的参数可以很好地减少TIME_WAIT套接字数量,但是对于 Squid,效果却不大。此项参数可以控制TIME_WAIT的最大数量,避免Squid服务器被大量的TIME_WAIT拖死。
net.ipv4.tcp_max_tw_buckets = 6000


所有的TCP/IP参数都位于/proc/sys/net目录下(请注意,对/proc/sys/net目录下内容的修改都是临时的,任何修改在系统重启后都会丢失)

 /etc/sysctl.conf是一个允许你改变正在运行中的Linux系统的接口。它包含一些TCP/IP堆栈和虚拟内存系统的高级选项,可用来控制Linux网络配置,由于/proc/sys/net目录内容的临时性,建议把TCPIP参数的修改添加到/etc/sysctl.conf文件, 然后保存文件,使用命令“/sbin/sysctl –p”使之立即生效



本文转载自:

共有 人打赏支持
miffa
粉丝 2
博文 19
码字总数 17938
作品 0
天津
高级程序员
TaintDroid剖析之File & Memiry & Socket级污点传播

TaintDroid剖析之File & Memiry & Socket级污点传播 作者:简行、走位@阿里聚安全 1、涉及到的代码文件 TaintDroid在File, Memory以及Socket三方面的污点传播主要涉及到如下一些文件: /lib...

阿里聚安全 ⋅ 2016/08/29 ⋅ 0

libvirt重头戏,很总要的API!!!

刚取云计算群里跟大家神吹了一阵……放松了不少……哈哈 再接再厉,为什吗说这个API很总要呢???!!! 先来看看这个函数调用接口是? virNodeGetInfo() 果断引用官方开发文档的说明 ——这...

张智恒 ⋅ 2012/04/24 ⋅ 0

Kafka实现细节(上)

如果你第一次看kafka的文章,请先看《分布式消息系统kafka初步》 之前有人问kafka和一般的MQ之间的区别,这个问题挺难回答,我觉得不如从kafka的实现原理来分析更为透彻,这篇将依据官网上给...

Gaischen ⋅ 2012/12/05 ⋅ 0

关于mod_jk整合apache+tomcat

小弟刚接触linux不久,因为公司的环境是:modjk+apache+tomcat+mysql ,最近在学习modjk,关于网上的资料了看了一些,现在有些迷惑,发出来求大神给我指点下!!! 小弟做了一个整合的试验,...

Hcl-胡 ⋅ 2013/03/07 ⋅ 2

关于 HP-Socket 的安全策略:

关于 HP-Socket 的安全策略: 首先非常感谢 HP-Socket 作者的开源,也给我的项目带来巨大的帮助,也表示由衷的感谢! 希望能增加以下功能: 因为本人服务器偶尔遭受黑客的攻击,数据量往往达...

我是VV ⋅ 2014/09/06 ⋅ 7

谁测试过SOCKET TCP 的BACKLOG的上限的?

最近在重新整理SOCKET的资料。对于listen (std,backlog); 后面是一个listen可以保持最大连通数,简单这么解释吧。现在man上表明可以通过修改 tcpmaxsyn_backlog 的值来调整。 建议可以调整到...

中山野鬼 ⋅ 2012/04/17 ⋅ 7

Ubuntu下查看CPU、内存和硬盘详细信息的几个命令

(1)CPU: 型号:grep "model name" /proc/cpuinfo awk -F ':' '{print $NF}' 数量:lscpu grep "CPU socket" awk '{print $NF}' 或 lscpu grep "Socket" awk '{print $NF}' 每个CPU的核数:......

Airship ⋅ 01/11 ⋅ 0

MySQL命令行工具

shell> mysql --user=username --password=yourpassword db_name shell> mysql --help shell> mysql -? 选项 --protocol={TCP | SOCKET | PIPE | MEMORY} mysql 命令 有些命令mysql可以自己解......

zhaozhiliang521 ⋅ 2017/02/08 ⋅ 0

linux系统级别的能够打开的文件句柄的数file-max命令

简单的说, max-file表示系统级别的能够打开的文件句柄的数量, 而ulimit -n控制进程级别能够打开的文件句柄的数量. man 5 proc, 找到file-max的解释: file-max中指定了系统范围内所有进程可打...

晨曦之光 ⋅ 2012/03/09 ⋅ 0

那些 IT 界的神翻译,原来我学不好编程的原因就在这

近日博主 ruanyf 在网上发布了一条关于套接字“socket”的解释,引发了网友对于那些 IT 界的神翻译的讨论: 突然想到,socket就是插座。服务器的socket,就是服务器提供插座,等着客户端的插...

两味真火 ⋅ 2017/05/13 ⋅ 19

没有更多内容

加载失败,请刷新页面

加载更多

下一页

来自一个优秀Java工程师的简历

写在前面: 鉴于前几天的一份前端简历,虽然带着很多不看好的声音,但却帮助了很多正在求职路上的人,不管评论怎么说,我还是决定要贴出一份后端的简历。 XXX ID:357912485 目前正在找工作 ...

颖伙虫 ⋅ 17分钟前 ⋅ 0

Confluence 6 恢复一个站点有关使用站点导出为备份的说明

推荐使用生产备份策略。我们推荐你针对你的生产环境中使用的 Confluence 参考 Production Backup Strategy 页面中的内容进行备份和恢复(这个需要你备份你的数据库和 home 目录)。XML 导出备...

honeymose ⋅ 今天 ⋅ 0

JavaScript零基础入门——(九)JavaScript的函数

JavaScript零基础入门——(九)JavaScript的函数 欢迎回到我们的JavaScript零基础入门,上一节课我们了解了有关JS中数组的相关知识点,不知道大家有没有自己去敲一敲,消化一下?这一节课,...

JandenMa ⋅ 今天 ⋅ 0

火狐浏览器各版本下载及插件httprequest

各版本下载地址:http://ftp.mozilla.org/pub/mozilla.org//firefox/releases/ httprequest插件截至57版本可用

xiaoge2016 ⋅ 今天 ⋅ 0

Docker系列教程28-实战:使用Docker Compose运行ELK

原文:http://www.itmuch.com/docker/28-docker-compose-in-action-elk/,转载请说明出处。 ElasticSearch【存储】 Logtash【日志聚合器】 Kibana【界面】 答案: version: '2'services: ...

周立_ITMuch ⋅ 今天 ⋅ 0

使用快嘉sdkg极速搭建接口模拟系统

在具体项目研发过程中,一旦前后端双方约定好接口,前端和app同事就会希望后台同事可以尽快提供可供对接的接口方便调试,而对后台同事来说定好接口还仅是个开始、设计流程,实现业务逻辑,编...

fastjrun ⋅ 今天 ⋅ 0

PXE/KickStart 无人值守安装

导言 作为中小公司的运维,经常会遇到一些机械式的重复工作,例如:有时公司同时上线几十甚至上百台服务器,而且需要我们在短时间内完成系统安装。 常规的办法有什么? 光盘安装系统 ===> 一...

kangvcar ⋅ 昨天 ⋅ 0

使用Puppeteer撸一个爬虫

Puppeteer是什么 puppeteer是谷歌chrome团队官方开发的一个无界面(Headless)chrome工具。Chrome Headless将成为web应用自动化测试的行业标杆。所以我们很有必要来了解一下它。所谓的无头浏...

小草先森 ⋅ 昨天 ⋅ 0

Java Done Right

* 表示难度较大或理论性较强。 ** 表示难度更大或理论性更强。 【Java语言本身】 基础语法,面向对象,顺序编程,并发编程,网络编程,泛型,注解,lambda(Java8),module(Java9),var(...

风华神使 ⋅ 昨天 ⋅ 0

Linux系统日志

linux 系统日志 /var/log/messages /etc/logrotate.conf 日志切割配置文件 https://my.oschina.net/u/2000675/blog/908189 logrotate 使用详解 dmesg 命令 /var/log/dmesg 日志 last命令,调......

Linux学习笔记 ⋅ 昨天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部