在内核中,连接跟踪表是一个二维数组结构的哈希表(hash table),哈希表的大小记作HASHSIZE,哈希表的每一项(hash table entry)称作bucket,因此哈希表中有HASHSIZE个bucket存在,每个bucket包含一个链表(linked list),每个链表能够存放若干个conntrack条目(bucket size)。需要明确的是,nf_conntrack 模块并不是所有 Linux 内核都会加载,最常见的导致加载该模块的原因是使用了 iptables、lvs 等内核态 NAT/防火墙导致内核需要对连接表进行追踪,iptable_nat、ip_vs 等多个内核模块都依赖 nf_conntrack, 但是 nf_conntrack 的存在会影响高并发下的内核收包性能。

对于一个新收到的数据包,内核使用如下步骤判断其是否属于一个已有连接:

  • 内核提取此数据包信息(源目IP,port,协议号)进行hash计算得到一个hash值,在哈希表中以此hash值做索引,索引结果为数据包所属的bucket(链表)。这一步hash计算时间固定并且很短
  • 遍历hash得到的bucket,查找是否有匹配的conntrack条目。这一步是比较耗时的操作,bucket size越大,遍历时间越长

bucket_size 和 hashsize 的关系

根据上面对哈希表的解释,系统最大允许连接跟踪数CONNTRACK_MAX = 连接跟踪表大小(HASHSIZE) * Bucket大小(bucket size)。从连接跟踪表获取bucket是hash操作时间很短,而遍历bucket相对费时,因此为了conntrack性能考虑,bucket size越小越好,默认为8或者4

nf_conntrack_max – INTEGER Size of connection tracking table. Default value is nf_conntrack_buckets value * 4.

net.netfilter.nf_conntrack_buckets 即是 /sys/module/nf_conntrack/parameters/hashsize
同时设定了 conntrack_max 和 hashsize 时,bucket_size会调整为其比值:

  1. # sysctl net.netfilter.nf_conntrack_buckets
  2. net.netfilter.nf_conntrack_buckets = 65536
  3. # sysctl net.netfilter.nf_conntrack_max
  4. net.netfilter.nf_conntrack_max = 100000000
  5. # echo "100000000 65536"| awk '{printf "%.2f\n",$1/$2}'
  6. 1525.88

计算 conntrack 消耗的内存

计算方法:

total_mem_used(bytes) = CONNTRACK_MAX * sizeof(struct ip_conntrack) + HASHSIZE * sizeof(struct list_head)

样例代码:

  1. import ctypes
  2. #不同系统可能不一样,ldconfig -v | grep conntrack 获取对应版本
  3. LIBNETFILTER_CONNTRACK = 'libnetfilter_conntrack.so.3.5.0'
  4. nfct = ctypes.CDLL(LIBNETFILTER_CONNTRACK)
  5. print 'sizeof(struct nf_conntrack):', nfct.nfct_maxsize()
  6. print 'sizeof(struct list_head):', ctypes.sizeof(ctypes.c_void_p) * 2

在上述机器(hashsize=65536, conntrack_max=100000000)上运行结果:

  1. sizeof(struct nf_conntrack): 328
  2. sizeof(struct list_head): 16

根据上述算式得出线上配置内存的理论消耗:100000000 * 328 +65536 * 16 bytes,主要由第一项组成

相关问题和处理

最近遇到了一个 nf_conntrack 相关的问题,背景是:近期贵组 LB 上线了一个新的集群,在只有接入项目较少的情况下,出现了 CPU 异常压力过大的问题,perf 发现大量 CPU 消耗在 nf_conntrack_find_get 上:

经查,nf_conntrack bucket hashsize 过小,导致 bucket size 大,查表效率差,调整前 /sys/module/nf_conntrack/parameters/hashsize 为16384,经上述算法计算 bucket size 高达6000+,将 hashsize 调整为524288后比值为100量级。

  1. echo "`sysctl -n net.netfilter.nf_conntrack_max` 16384"| awk '{printf "%.2f\n",$1/$2}'
  2. 6103.52
  3. echo "`sysctl -n net.netfilter.nf_conntrack_max` `sysctl -n net.netfilter.nf_conntrack_buckets`"| awk '{printf "%.2f\n",$1/$2}'
  4. 190.73

linux 路由跟踪表 nf_conntrack 数据结构 参数 简介相关推荐

  1. linux 路由跟踪表满错误 nf_conntrack: table full, dropping packet 原理解决方法

    netfilter/conntrack 相关内核参数往往是用 Linux 服务器的互联网小公司业务量上去之后遇到的第 3 个"新手怪".(第 1 位:进程可用的 FD 不足,第 2 ...

  2. linux 网络错误 nf_conntrack: table full, dropping packet. 路由跟踪表满

    "连接跟踪表已满,开始丢包"!相信不少用iptables的同学都会见过这个错误信息吧,这个问题曾经也困扰过我好长一段时间.此问题的解决办法有四种(nf_conntrack 在Cen ...

  3. linux端口跟踪命令,Linux路由跟踪的命令是什么

    1. 了解traceroute的作用与原理 Linux 上的traceroute命令用于路由跟踪.通常用于了解网络数据包所经过的节点,或者查找网络故障点.网络中的数据包是经过一个一个路由器转发的,专业 ...

  4. linux 路由跟踪命令_云计算网络知识学习-linux网络基础

    1 linux虚拟网络基础 1.1 Device 在linux里面devic(设备)与传统网络概念里的物理设备(如交换机.路由器)不同,Linux所说的设备,其背后指的是一个类似于数据结构.内核模块或 ...

  5. Linux下top使用及各参数简介

    top top命令能够显示出各项与系统和进程相关的信息,在运维.调试以及问题定位方面经常使用. 语法: top -hv | -abcHimMsS -d delay -n iterations -p p ...

  6. vue路由对象($route)参数简介

    路由对象 在使用了 vue-router 的应用中,路由对象会被注入每个组件中,赋值为 this.$route ,并且当路由切换时,路由对象会被更新. so , 路由对象暴露了以下属性: 1.$rou ...

  7. linux 内核 vfs_readdir函数的filldir_t参数简介

    filldir有两重含义: 第一,vfs_readir的回调函数(确切的应该叫filldir_t filler): 第二,sys_getdents传递给vfs_readdir的回调函数. filldi ...

  8. vue 传递 对象 路由_vue 04 -vue路由对象($route)参数简介以及和router的区别

    vue路由对象($route) 在使用了 vue-router 的应用中,路由对象会被注入每个组件中,赋值为 this.$route ,并且当路由切换时,路由对象会被更新. so , 路由对象暴露了以 ...

  9. linux 路由跟踪命令_一文掌握linux系统路由跟踪指令traceroute

    概述 traceroute我们可以知道信息从你的计算机到互联网另一端的主机是走的什么路径.当然每次数据包由某一同样的出发点(source)到达某一同样的目的地(destination)走的路径可能会不 ...

最新文章

  1. 产品经理一定要懂得“借力”
  2. 元旦是星期天,春节是1.29,也是星期天哦,祝贺大家节日了!
  3. C语言入门(4)——常量、变量与赋值
  4. 程序员如何与人打交道
  5. 鸟哥linux 私房菜
  6. 虚拟化精华问答 | 虚拟化技术分类
  7. 颈椎病分型及对症治疗
  8. 哪些程序员在围观 996.ICU?Python 爬取 40000 条 GitHub 数据告诉你!
  9. 她要到另外一座城市去工作
  10. 【转】[FPGA博客大赛](updated)在xilinx的FPGA系统中scanf函数的使用
  11. java自定义表单系统_java自定义表单
  12. 7个良心到难以置信的自媒体免费网站推荐
  13. ie9 ajax 二进制流,2.ajax兼容IE9 非常实用!!!
  14. 杭州好玩景点攻略884
  15. php货币2019年12月31日汇率,2019年12月31日中国外汇交易中心受权公布人民币汇率中间价公告...
  16. 免费申请office365 A1 和 a1plus 带OneDrive 5T 网盘 office365学生版(转载)
  17. PR-AE-C4D 视频编辑工具的下载地址
  18. icq蓝牙_使用WhizBase发送ICQ消息
  19. IP地址划分时192.168.1.0/24含义是什么
  20. HashMap的工作原理(一):Hash算法

热门文章

  1. 几种常见自动化测试框架
  2. Docker 容器技术 — Dockerfile
  3. 5G 信令流程 — 5GC 的连接管理(CM,Connection Management)
  4. ETSI — MEC — APIs 清单
  5. 架构师之路 — API 经济 — RESTful API
  6. 用 Flask 来写个轻博客 (21) — 结合 reCAPTCHA 验证码实现用户注册与登录
  7. Python基本语法_函数_返回值
  8. Simulink仿真---PMSM滞环电流控制仿真模型学习
  9. python模块-paramiko-修改源码(demo实例)
  10. clojure 中使用 actor