42 | 案例篇:如何优化 NAT 性能?(下)
案例准备
# Ubuntu
apt-get install -y docker.io tcpdump curl apache2-utils# CentOS
curl -fsSL https://get.docker.com | sh
yum install -y tcpdump curl httpd-tools
SystemTap
# Ubuntu
apt-get install -y systemtap-runtime systemtap
# Configure ddebs source
echo "deb http://ddebs.ubuntu.com $(lsb_release -cs) main restricted universe multiverse
deb http://ddebs.ubuntu.com $(lsb_release -cs)-updates main restricted universe multiverse
deb http://ddebs.ubuntu.com $(lsb_release -cs)-proposed main restricted universe multiverse" | \
sudo tee -a /etc/apt/sources.list.d/ddebs.list
# Install dbgsym
apt-key adv --keyserver keyserver.ubuntu.com --recv-keys F2EDC64DC5AEE1F6B9C621F0C8CAB6595FDFF622
apt-get update
apt install ubuntu-dbgsym-keyring
stap-prep
apt-get install linux-image-`uname -r`-dbgsym# CentOS
yum install systemtap kernel-devel yum-utils kernel
stab-prep
案例分析
docker run --name nginx-hostnet --privileged --network=host -itd feisky/nginx:80
curl http://192.168.0.30/
...
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
# open files
ulimit -n
1024
# 临时增大当前会话的最大文件描述符数
ulimit -n 65536
# -c 表示并发请求数为 5000,-n 表示总的请求数为 10 万
# -r 表示套接字接收错误时仍然继续执行,-s 表示设置每个请求的超时时间为 2s
ab -c 5000 -n 100000 -r -s 2 http://192.168.0.30/
...
Requests per second: 6576.21 [#/sec] (mean)
Time per request: 760.317 [ms] (mean)
Time per request: 0.152 [ms] (mean, across all concurrent requests)
Transfer rate: 5390.19 [Kbytes/sec] receivedConnection Times (ms)min mean[+/-sd] median max
Connect: 0 177 714.3 9 7338
Processing: 0 27 39.8 19 961
Waiting: 0 23 39.5 16 951
Total: 1 204 716.3 28 7349
...
- 每秒请求数(Requests per second)为 6576;
- 每个请求的平均延迟(Time per request)为 760ms;
- 建立连接的平均延迟(Connect)为 177ms。
docker rm -f nginx-hostnet
docker run --name nginx --privileged -p 8080:8080 -itd feisky/nginx:nat
iptables -nL -t nat
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
DOCKER all -- 0.0.0.0/0 0.0.0.0/0 ADDRTYPE match dst-type LOCAL...Chain DOCKER (2 references)
target prot opt source destination
RETURN all -- 0.0.0.0/0 0.0.0.0/0
DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:8080 to:172.17.0.2:8080
curl http://192.168.0.30:8080/
...
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
# -c 表示并发请求数为 5000,-n 表示总的请求数为 10 万
# -r 表示套接字接收错误时仍然继续执行,-s 表示设置每个请求的超时时间为 2s
ab -c 5000 -n 100000 -r -s 2 http://192.168.0.30:8080/
...
apr_pollset_poll: The timeout specified has expired (70007)
Total of 5602 requests completed
ab -c 5000 -n 10000 -r -s 30 http://192.168.0.30:8080/
...
Requests per second: 76.47 [#/sec] (mean)
Time per request: 65380.868 [ms] (mean)
Time per request: 13.076 [ms] (mean, across all concurrent requests)
Transfer rate: 44.79 [Kbytes/sec] receivedConnection Times (ms)min mean[+/-sd] median max
Connect: 0 1300 5578.0 1 65184
Processing: 0 37916 59283.2 1 130682
Waiting: 0 2 8.7 1 414
Total: 1 39216 58711.6 1021 130682
...
- 每秒请求数(Requests per second)为 76;
- 每个请求的延迟(Time per request)为 65s;
- 建立连接的延迟(Connect)为 1300ms。
- 第一,利用 Netfilter 中的钩子函数(Hook),修改源地址或者目的地址。
- 第二,利用连接跟踪模块 conntrack ,关联同一个连接的请求和响应。
#! /usr/bin/env stap############################################################
# Dropwatch.stp
# Author: Neil Horman <nhorman@redhat.com>
# An example script to mimic the behavior of the dropwatch utility
# http://fedorahosted.org/dropwatch
############################################################# Array to hold the list of drop points we find
global locations# Note when we turn the monitor on and off
probe begin { printf("Monitoring for dropped packets\n") }
probe end { printf("Stopping dropped packet monitor\n") }# increment a drop counter for every location we drop at
probe kernel.trace("kfree_skb") { locations[$location] <<< 1 }# Every 5 seconds report our drop locations
probe timer.sec(5)
{printf("\n")foreach (l in locations-) {printf("%d packets dropped at %s\n",@count(locations[l]), symname(l))}delete locations
}
stap --all-modules dropwatch.stp
Monitoring for dropped packets
ab -c 5000 -n 10000 -r -s 30 http://192.168.0.30:8080/
10031 packets dropped at nf_hook_slow
676 packets dropped at tcp_v4_rcv7284 packets dropped at nf_hook_slow
268 packets dropped at tcp_v4_rcv
ab -c 5000 -n 10000 -r -s 30 http://192.168.0.30:8080/
# 记录一会(比如 30s)后按 Ctrl+C 结束
perf record -a -g -- sleep 30# 输出报告
perf report -g graph,0
- 第一,接收网络包时,在连接跟踪表中查找连接,并为新的连接分配跟踪对象(Bucket)。
- 第二,在 Linux 网桥中转发包。这是因为案例 Nginx 是一个 Docker 容器,而容器的网络通过网桥来实现;
- 第三,接收网络包时,执行 DNAT,即把 8080 端口收到的包转发给容器。
sysctl -a | grep conntrack
net.netfilter.nf_conntrack_count = 180
net.netfilter.nf_conntrack_max = 1000
net.netfilter.nf_conntrack_buckets = 65536
net.netfilter.nf_conntrack_tcp_timeout_syn_recv = 60
net.netfilter.nf_conntrack_tcp_timeout_syn_sent = 120
net.netfilter.nf_conntrack_tcp_timeout_time_wait = 120
...
- net.netfilter.nf_conntrack_count,表示当前连接跟踪数;
- net.netfilter.nf_conntrack_max,表示最大连接跟踪数;
- net.netfilter.nf_conntrack_buckets,表示连接跟踪表的大小。
dmesg | tail
[104235.156774] nf_conntrack: nf_conntrack: table full, dropping packet
[104243.800401] net_ratelimit: 3939 callbacks suppressed
[104243.800401] nf_conntrack: nf_conntrack: table full, dropping packet
[104262.962157] nf_conntrack: nf_conntrack: table full, dropping packet
# 连接跟踪对象大小为 376,链表项大小为 16
nf_conntrack_max* 连接跟踪对象大小 +nf_conntrack_buckets* 链表项大小
= 1000*376+65536*16 B
= 1.4 MB
sysctl -w net.netfilter.nf_conntrack_max=131072
sysctl -w net.netfilter.nf_conntrack_buckets=65536
ab -c 5000 -n 100000 -r -s 2 http://192.168.0.30:8080/
...
Requests per second: 6315.99 [#/sec] (mean)
Time per request: 791.641 [ms] (mean)
Time per request: 0.158 [ms] (mean, across all concurrent requests)
Transfer rate: 4985.15 [Kbytes/sec] receivedConnection Times (ms)min mean[+/-sd] median max
Connect: 0 355 793.7 29 7352
Processing: 8 311 855.9 51 14481
Waiting: 0 292 851.5 36 14481
Total: 15 666 1216.3 148 14645
- 每秒请求数(Requests per second)为 6315(不用 NAT 时为 6576);
- 每个请求的延迟(Time per request)为 791ms(不用 NAT 时为 760ms);
- 建立连接的延迟(Connect)为 355ms(不用 NAT 时为 177ms)。
# -L 表示列表,-o 表示以扩展格式显示
conntrack -L -o extended | head
ipv4 2 tcp 6 7 TIME_WAIT src=192.168.0.2 dst=192.168.0.96 sport=51744 dport=8080 src=172.17.0.2 dst=192.168.0.2 sport=8080 dport=51744 [ASSURED] mark=0 use=1
ipv4 2 tcp 6 6 TIME_WAIT src=192.168.0.2 dst=192.168.0.96 sport=51524 dport=8080 src=172.17.0.2 dst=192.168.0.2 sport=8080 dport=51524 [ASSURED] mark=0 use=1
# 统计总的连接跟踪数
conntrack -L -o extended | wc -l
14289# 统计 TCP 协议各个状态的连接跟踪数
conntrack -L -o extended | awk '/^.*tcp.*$/ {sum[$6]++} END {for(i in sum) print i, sum[i]}'
SYN_RECV 4
CLOSE_WAIT 9
ESTABLISHED 2877
FIN_WAIT 3
SYN_SENT 2113
TIME_WAIT 9283# 统计各个源 IP 的连接跟踪数
conntrack -L -o extended | awk '{print $7}' | cut -d "=" -f 2 | sort | uniq -c | sort -nr | head -n 1014116 192.168.0.2172 192.168.0.96
sysctl net.netfilter.nf_conntrack_tcp_timeout_time_wait
net.netfilter.nf_conntrack_tcp_timeout_time_wait = 120
小结
42 | 案例篇:如何优化 NAT 性能?(下)相关推荐
- 41 | 案例篇:如何优化 NAT 性能?(上)
上一节,探究了网络延迟增大问题的分析方法,并通过一个案例,掌握了如何用 hping3.tcpdump.Wireshark.strace 等工具,来排查和定位问题的根源. 简单回顾一下,网络延迟是最核心 ...
- python 速度 memmap_从20秒到0.5秒:一个使用Rust语言来优化Python性能的案例
<从20秒到0.5秒:一个使用Rust语言来优化Python性能的案例>要点: 本文介绍了从20秒到0.5秒:一个使用Rust语言来优化Python性能的案例,希望对您有用.如果有疑问,可 ...
- 转 从20秒到0.5秒:一个使用Rust语言来优化Python性能的案例
注: 转自 微信公众号"高可用架构":从20秒到0.5秒:一个使用Rust语言来优化Python性能的案例 导读:Python 被很多互联网系统广泛使用,但在另外一方面,它也存在一 ...
- 【Linux 性能优化系列】Linux 性能优化 -- CPU 性能篇(三) Linux 软中断
[Linux 性能优化系列]Linux 性能优化 -- CPU 性能篇(三) Linux 软中断 [1]相关概念 [1.1]中断 中断其实是一种异步的事件处理机制,可以提高系统的并发处理能力:为了减少 ...
- 【Linux 性能优化系列】Linux 性能优化 -- CPU 性能篇(一) 平均负载、上下文切换、CPU 使用率
[Linux 性能优化系列]Linux 性能优化 -- CPU 性能篇(一) 平均负载.上下文切换.CPU 使用率 [1]相关概念 [1.1]平均负载 平均负载是指单位时间内,系统处于可运行状态和不可 ...
- rust python扩展_Rust语言优化Python性能案例
原标题:Rust语言优化Python性能案例 导读:Python 被很多互联网系统广泛使用,但在另外一方面,它也存在一些性能问题,不过 Sentry 工程师分享的在关键模块上用另外一门语言 Rust ...
- Android进阶:性能优化篇
Android进阶:性能优化篇
Android进阶:性能优化篇 分类:Android 性能优化2011-08-09 17:06585人阅读评论(0)收藏举报 一.在使用Gallery控件时,如果载入的图片过多,过大,就很容易出现Ou ...
- mui 组件:“div下拉导航”【scroll固定位置】- 案例篇
(含代码.效果图)侧滑导航:"div下拉导航" 截图如下: 重要代码 · 如下: //下拉菜单定位:动态锁定 window.onscroll = function(){let sc ...
- 一篇读懂分布式架构下的负载均衡技术:分类、原理、算法、常见方案等
1.引言 关于"负载均衡"的解释,百度词条里:负载均衡,英文叫Load Balance,意思就是将请求或者数据分摊到多个操作单元上进行执行,共同完成工作任务. 负载均衡(Load ...
最新文章
- solidworks重建模型好慢_兄弟只能帮你到这了,SOLIDWORKS卡顿或许秘密就在这些选项里...
- java.lang.UnsatisfiedLinkError: org.apache.hadoop.util.NativeCrc32.nativeComputeChunkedSumsByteArray
- FPGA车牌数字识别系统设计verilog实现(带上板录制视频)
- 2017-12-07 socket 读取问题
- python 跳过_python-pytest学习(九)-跳过用例skip
- php游戏怎么设置fms,[FMS]FMS使用需要注意的几种问题总结说明
- 一个ip对应多个域名多个ssl证书配置-Nginx实现多域名证书HTTPS
- L2-010. 排座位-PAT团体程序设计天梯赛GPLT(并查集)
- cmd命令不识别exp_sqlplus、exp、imp不是内部或外部命令,也不是可运行的程序
- Java程序员不容错过的开发趋势
- SVN比较两个文件差异
- 软件工程专业如何论文选题?
- 【Windows Server 2019】存储服务器的配置和管理——iSCSI的安装和配置(下)
- 荣耀9igoogle模式_将您的iGoogle主页导出到另一个帐户
- 有实用简单的PS小技巧吗?下面几个小技巧你知道几个呢?
- MP4视频转换器怎么样将FLV转MP4
- android+怎么分享图片大小,Android微信分享图片大于32k进行压缩
- 新浪微博搜索 s.weibo.com [已失效]
- 6000字长文,终于将数据中台架构体系讲明白了
- 如何使用netsh advfirewall firewall而不是netsh firewall控制Windows Server 2008的防火墙行为
热门文章
- xmind快捷键_XMind思维导图软件最全面的使用教程!
- 计算机课例,计算机的基本组成教学课例
- linux 查看内核属性,怎么查看linux操作系统
- linux 限制连接时间,linux抵御DDoS攻击方法 通过iptables限制TCP连接和频率
- SparkSQL之thriftserver/beeline的使用
- Python IDE 详细攻略,拿来吧你~
- 聊一聊大学做过的 7 种兼职以及收获感悟。
- 肝!Python 教程:从零到大师
- 批处理 批量s扫1433_申报资料 | 批量整理图谱(续)
- android工程创建,3.2.1 创建Android 项目(2)