The "Out of socket memory" error

I recently did some work on some of our frontend machines (on which we run Varnish) at StumbleUpon and decided to track down some of the errors the Linux kernel was regularly throwing in kern.log such as:

Feb 25 08:23:42 foo kernel: [3077014.450011] Out of socket memory

Before we get started, let me tell you that you should NOT listen to any blog or forum post without doing your homework, especially when the post recommends that you tune up virtually every TCP related knob in the kernel. These people don't know what they're doing and most probably don't understand much to TCP/IP. Most importantly, their voodoo won't help you fix your problem and might actually make it worse.

Dive in the Linux kernel

In order to best understand what's going on, the best thing is to go read the code of the kernel. Unfortunately, the kernel's error messages or counters are often imprecise, confusing, or even misleading. But they're important. And reading the kernel's code isn't nearly as hard as what people say.

The "Out of socket memory" error

The only match for "Out of socket memory" in the kernel's code (as of v2.6.38) is in net/ipv4/tcp_timer.c:

66 static int tcp_out_of_resources(struct sock *sk, int do_reset)

67 {

68         struct tcp_sock *tp = tcp_sk(sk);

69         int shift = 0;

70

71         /* If peer does not open window for long time, or did not transmit

72          * anything for long time, penalize it. */

73         if ((s32)(tcp_time_stamp - tp->lsndtime) > 2*TCP_RTO_MAX || !do_reset)

74                 shift++;

75

76         /* If some dubious ICMP arrived, penalize even more. */

77         if (sk->sk_err_soft)

78                 shift++;

79

80         if (tcp_too_many_orphans(sk, shift)) {

81                 if (net_ratelimit())

82                         printk(KERN_INFO "Out of socket memory\n");

So the question is: when does tcp_too_many_orphans return true? Let's take a look in include/net/tcp.h:

268 static inline bool tcp_too_many_orphans(struct sock *sk, int shift)

269 {

270         struct percpu_counter *ocp = sk->sk_prot->orphan_count;

271         int orphans = percpu_counter_read_positive(ocp);

272

273         if (orphans << shift > sysctl_tcp_max_orphans) {

274                 orphans = percpu_counter_sum_positive(ocp);

275                 if (orphans << shift > sysctl_tcp_max_orphans)

276                         return true;

277         }

278

279         if (sk->sk_wmem_queued > SOCK_MIN_SNDBUF &&

280             atomic_long_read(&tcp_memory_allocated) > sysctl_tcp_mem[2])

281                 return true;

282         return false;

283 }

So two conditions that can trigger this "Out of socket memory" error:

1.There are "too many" orphan sockets (most common).

2.The socket already has the minimum amount of memory and we can't give it more because TCP is already using more than its limit.

In order to remedy to your problem, you need to figure out which case you fall into. The vast majority of the people (especially those dealing with frontend servers like Varnish) fall into case 1.

Are you running out of TCP memory?

Ruling out case 2 is easy. All you need is to see how much memory your kernel is configured to give to TCP vs how much is actually being used. If you're close to the limit (uncommon), then you're in case 2. Otherwise (most common) you're in case 1. The kernel keeps track of the memory allocated to TCP in multiple of pages, not in bytes. This is a first bit of confusion that a lot of people run into because some settings are in bytes and other are in pages (and most of the time 1 page = 4096 bytes).

Rule out case 2: find how much memory the kernel is willing to give to TCP:

$ cat /proc/sys/net/ipv4/tcp_mem

3093984 4125312 6187968

The values are in number of pages. They get automatically sized at boot time (values above are for a machine with 32GB of RAM). They mean:

When TCP uses less than 3093984 pages (11.8GB), the kernel will consider it below the "low threshold" and won't bother TCP about its memory consumption.

When TCP uses more than 4125312 pages (15.7GB), enter the "memory pressure" mode.

The maximum number of pages the kernel is willing to give to TCP is 6187968 (23.6GB). When we go above this, we'll start seeing the "Out of socket memory" error and Bad Things will happen.

Now let's find how much of that memory TCP actually uses.

$ cat /proc/net/sockstat

sockets: used 14565

TCP: inuse 35938 orphan 21564 tw 70529 alloc 35942 mem 1894

UDP: inuse 11 mem 3

UDPLITE: inuse 0

RAW: inuse 0

FRAG: inuse 0 memory 0

The last value on the second line (mem 1894) is the number of pages allocated to TCP. In this case we can see that 1894 is way below 6187968, so there's no way we can possibly be running out of TCP memory. So in this case, the "Out of socket memory" error was caused by the number of orphan sockets.

Do you have "too many" orphan sockets?

First of all: what's an orphan socket? It's simply a socket that isn't associated to a file descriptor. For instance, after you close() a socket, you no longer hold a file descriptor to reference it, but it still exists because the kernel has to keep it around for a bit more until TCP is done with it. Because orphan sockets aren't very useful to applications (since applications can't interact with them), the kernel is trying to limit the amount of memory consumed by orphans, and it does so by limiting the number of orphans that stick around. If you're running a frontend web server (or an HTTP load balancer), then you'll most likely have a sizeable number of orphans, and that's perfectly normal.

In order to find the limit on the number of orphan sockets, simply do:

$ cat /proc/sys/net/ipv4/tcp_max_orphans

65536

Here we see the default value, which is 64k. In order to find the number of orphan sockets in the system, look again in sockstat:

$ cat /proc/net/sockstat

sockets: used 14565

TCP: inuse 35938 orphan 21564 tw 70529 alloc 35942 mem 1894

[...]

So in this case we have 21564 orphans. That doesn't seem very close to 65536... Yet, if you look once more at the code above that prints the warning, you'll see that there is this shift variable that has a value between 0 and 2, and that the check is testing if (orphans << shift > sysctl_tcp_max_orphans). What this means is that in certain cases, the kernel decides to penalize some sockets more, and it does so by multiplying the number of orphans by 2x or 4x to artificially increase the "score" of the "bad socket" to penalize. The problem is that due to the way this is implemented, you can see a worrisome "Out of socket memory" error when in fact you're still 4x below the limit and you just had a couple "bad sockets" (which happens frequently when you have an Internet facing service). So unfortunately that means that you need to tune up the maximum number of orphan sockets even if you're 2x or 4x away from the threshold. What value is reasonable for you depends on your situation at hand. Observe how the count of orphans in /proc/net/sockstat is changing when your server is at peak traffic, multiply that value by 4, round it up a bit to have a nice value, and set it. You can set it by doing a echo of the new value in /proc/sys/net/ipv4/tcp_max_orphans, and don't forget to update the value of net.ipv4.tcp_max_orphans in /etc/sysctl.conf so that your change persists across reboots.

That's all you need to get rid of these "Out of socket memory" errors, most of which are "false alarms" due to the shift variable of the implementation.

原文

[本来准备翻译,时间不够,直接贴原文吧]

http://blog.tsunanet.net/2011/03/out-of-socket-memory.html

The "Out of socket memory" error的更多相关文章

  1. Myeclipse运行报错:an out of memory error has occurred的解决方法

    不知道怎么了,重装的myeclipse2013,里边就放了一个项目,启动myeclipse就报 an out of memory error has occurred....... 一点yes就退出 ...

  2. java.net.SocketException: Software caused connection abort: socket write error

    用Java客户端程序访问Java Web服务器时出错: java.net.SocketException: Software caused connection abort: socket write ...

  3. 解决:编译CM14.1 提示Jack “Out of memory error”错误

    Android 7.1编译到33%时出现JDK内存溢出的错误: Out of memory error (version f95d7bdecfceb327f9d201a1348397ed8a84384 ...

  4. Software caused connection abort: socket write error

    Exception in thread "main" java.net.SocketException: Software caused connection abort: soc ...

  5. Java socket 说明 以及web 出现java.net.SocketException:(Connection reset或者Connectreset by peer:Socket write error)的解释

    另外http://www.cnblogs.com/fengmk2/archive/2007/01/15/using-Socket.html可供参考   一Java socket 说明 所谓socket ...

  6. spring+ibatis问题1—— 程序报错:java.sql.SQLException: Io 异常: Connection reset by peer, socket write error; ”或“java.sql.SQLException 关闭的连接”异常

    转自:http://blog.sina.com.cn/s/blog_1549fb0710102whz2.html spring+ibatis程序测试时报错:java.sql.SQLException: ...

  7. testNG java.net.SocketException: Software caused connection abort: socket write error

    执行用例报错,提示 java.net.SocketException: Software caused connection abort: socket write error java.net.So ...

  8. Caused by: java.net.SocketException: Software caused connection abort: socket write error

    1.错误描述 [ERROR:]2015-05-06 10:54:18,967 [异常拦截] ClientAbortException: java.net.SocketException: Softwa ...

  9. 第一次JVM分析记录:Out of Memory Error (workgroup.cpp:96), pid=6196, tid=139999645685504

    tomcat的catalina.out日志报错如下: Exception in thread "http-bio-8081-Acceptor-0" java.lang.OutOfM ...

随机推荐

  1. Java中public、protected、default和private的区别

    public: 具有最大的访问权限,可以访问任何一个在classpath下的类.接口.异常等.它往往用于对外的情况,也就是对象或类对外的一种接口的形式. protected: 主要的作用就是用来保护子 ...

  2. SQL Server密码爆破工具SQLdict

    SQL Server密码爆破工具SQLdict SQL Server是Windows系统常用的数据库服务器.它广泛采用用户名和密码方式,进行身份认证.Kali Linux提供一款专用的数据库密码爆破工 ...

  3. react运行阶段

    运行中可以使用的函数componentWillReceiveProps:父组件修改属性触发,可以修改新属性,修改状态.字面意思,组件将要接收属性,这个函数触发的时机就是组件的属性将要发生改变的时候,但 ...

  4. HDU 5909 Tree Cutting 动态规划 快速沃尔什变换

    Tree Cutting 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5909 Description Byteasar has a tree T ...

  5. Emmet 语法介绍

    一.生成 HTML 文档初始结构 HTML 文档的初始结构,就是包括 doctype.html.head.body 以及 meta 等内容.你只需要输入一个 “!” 就可以生成一个 HTML5 的标准 ...

  6. vue项目开发之v-for列表渲染的坑

    不知道大家在用vue开发的过程中有没有遇到过在使用v-for的时候会出现大片的黄色警告,比如下图: 其实这是因为没有写key的原因 :key是为vue的响应式渲染提供方法,在列表中单条数据改变的情况下 ...

  7. stap 命令

    SystemTap accepts script as command line option or external file, for example: * Command-line script ...

  8. [Android 动画]简要分析一下Animator 与 Animation

    大家假设喜欢我的博客,请关注一下我的微博,请点击这里(http://weibo.com/kifile),谢谢 转载请标明出处(http://blog.csdn.net/kifile),再次感谢 在 A ...

  9. iOS 实现复选框 checkbox

    -(void)checkboxClick:(UIButton *)btn{    btn.selected = !btn.selected;} - (void)viewDidLoad {UIButto ...

  10. 【ELK】【docker】【elasticsearch】2.使用elasticSearch+kibana+logstash+ik分词器+pinyin分词器+繁简体转化分词器 6.5.4 启动 ELK+logstash概念描述

    官网地址:https://www.elastic.co/guide/en/elasticsearch/reference/current/docker.html#docker-cli-run-prod ...