Open lzh2nix opened 4 years ago
整个服务端微服务化尤其是serverless化肯定是趋势, serverless就更容易上云(想想就很美)。下半年也有计划好好学习一下k8s相关的知识。
docker/java 在实际工作中接触比较少,这里有些知识点还得回头补下。不过里面排查我问题的思路可以学习一下(看案例并不是背命令/答案,而是要学习作者在案例中的分析步骤和思路):
首先看到的现象是:
两次 reset by peer,
一次反应很慢
一次 connect refused
从抓包来看的话,第一次reset by peer 是由于socket监听了,但是服务没有启动导致的,最后一次 connect refused 可以知道这里连监听哪里都已经挂了(应该是整体重启了)。 之后可以通过dmsg来查看确实服务是OOM掉了,进一步分析docker inspect 可以确认是被OOM干掉了
$:docker inspect tomcat -f '{{json .State}}' | jq
{
"Status": "exited",
"Running": false,
"Paused": false,
"Restarting": false,
"OOMKilled": true,
"Dead": false,
"Pid": 0,
"ExitCode": 137,
"Error": "",
"StartedAt": "2020-07-06T14:14:13.245204198Z",
"FinishedAt": "2020-07-06T14:17:06.774133262Z"
}
然后是就是进一步分析服务为何OOM掉了?
这里最关键的就是check docker的启动命令了 和 check应用中java的内存分配情况了,java是最不熟悉的语言,所以就不在这里班门弄斧了,不过有一个和docker相关的知识还是需要去整理一下:
丢包了----这个估计是最常听到的一句话, 而且往往是从客户端的角度来看的,丢包的时候真实发生了什么是需要继续挖掘的。这一篇里内容实在是太夯实了,可以作为丢包问题的最佳实践,来不断的锻炼自己的思维模式。 作者这张图总结的太好了,把每一层可能发生的丢包都分析了一下,然后可以按照这个思路去分析。
链路层: 由于是docker环境check了一下宿主机和docker里面的收包情况 宿主机 docker 保证不是宿主机NAT转包的时候发生了丢包,按照经验可以怀疑这里的MTU了,不过hping3的话看不出效果。
tc Qdisc
tc这个看到过别人分享来做丢包测试的, 实际环境中还是第一次见:
tc -s qdisc show dev eth0
qdisc netem 8002: root refcnt 2 limit 1000 loss 30%
Sent 818 bytes 15 pkt (dropped 5, overlimits 0 requeues 0)
backlog 0b 0p requeues 0
这种就是最怕是前人测试完忘了删除。从这里可以看出制定了30%的丢包。可以
tc qdisc del dev eth0 root netem loss 30%
删除之。
网络传输层
分析完链路层可以继续往上走,可以通过netstat -s 来看下TCP层面的统计,评论里很多人说实际中可能有大量的包收发这样分析不太现实,这里其实就是看下大概的规律,如果发现确实丢包了可以tcpdump 指定ip地址抓包继续分析。
iptables层面
通过上面的分析可以看到tcp层面并没有发生丢包,那就check iptables层面的东西了。
root@nginx:/# iptables -vnL
Chain INPUT (policy ACCEPT 32 packets, 2408 bytes)
pkts bytes target prot opt in out source destination
10 400 DROP all -- * * 0.0.0.0/0 0.0.0.0/0 statistic mode random probability 0.29999999981
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 19 packets, 852 bytes)
pkts bytes target prot opt in out source destination
6 280 DROP all -- * * 0.0.0.0/0 0.0.0.0/0 statistic mode random probability 0.29999999981
可以看到这里设置了30%的丢包,然后删除掉drop rule
root@nginx:/# iptables -t filter -D INPUT -m statistic --mode random --probability 0.30 -j DROP
root@nginx:/# iptables -t filter -D OUTPUT -m statistic --mode random --probability 0.30 -j DROP
这样hping3就没有丢包了。继续http请求的时候又发生了丢包,所以这里又要做一次从下到上的分析。
而这次很明显链路层就发生了丢包,mtu太小了。
有那么点刻意设计的意思,但是显示环境就是这么复杂,有时候你不知道前人留下了什么坑的,所以这里一定要形成自己的分析体系。
这里case之前在cpu篇的时候也分析过,主要是hping3 发送大量的SYN包导致服务端收到大量的下包之后softirq升高。之前的排查思路是:
top(softirq升高)------->watch -d |cat /proc/softirqs 收到了大量的包------>wireshark 分析认识是收到大量的包(确定服务端口)
这一节通过perf 调用栈+火焰图来分析这里的问题。这种方式其实更直接能看到执行的函数名称,然后通过这个名称大概就能知道是哪里的问题了。后面作者通过perf record文件导入到火焰图的方式来做了进一步的分析。使用火焰图确实比原生的perf report好看很多:
生成方式:
$ perf record -a -g -p 9 -- sleep 30
➜ ~ perf script -i ./code/clang/perf.data | ./proj/linux-perf/FlameGraph/stackcollapse-perf.pl --all | ./proj/linux-perf/FlameGraph/flamegraph.pl > ksoftirqd.svg
通过这个可以看出分析问题可以有N种方法,选择自己最熟悉的方式就好(记得svg图片用浏览器打开,这样才能一层层点击展示)
这一讲主要把Linux下的动态追踪技术梳理了一遍,这两节的内容实在是太多了,不知道从哪里开始总结,这里就简单过一下Linux各种的动态追踪技术,后面有需要了再回过头来去深入的了解一下这里的各种工具。
ftrace 和perf应该是对linux内核版本没有太多要求的动态追踪技术,当发现系统top sys站比比较高时可以通过动态追逐技术来查看具体的内核线程的运行情况,
ftrace trace-cmd可以追踪内核函数的调用关系:
$ trace-cmd record -p function_graph -g do_sys_open -O funcgraph-proc ls
这里表示追踪ls命令的 do_sys_open 函数调用,-p 表示支持的tracer 可以在 trace-cmd-list查看支持的tracer和事件。详细的可以直接man 查看:
perf 追踪某个进程的行为时可以直接:
perf trace -p 20325
perf 最大的特点就是可以直接诶追踪用户栈的调用,这里可以看到调用了那些函数已经返回值:
这个是我们之前用过的老朋友了, eBPF: SystemTap: BCC: http://www.brendangregg.com/ebpf.html#bcc, 这里是大神对eBPF的一个介绍,看的云里雾里。
参考:
又是一个很好的优化案例, 针对服务吞吐量给出了很好的优化思路,依然采用47讲中采用的分析步骤。
1.在NAT环境里首先checkNAT的配置:
$ sysctl net.netfilter.nf_conntrack_max
net.netfilter.nf_conntrack_max = 200
$ sysctl net.netfilter.nf_conntrack_count
net.netfilter.nf_conntrack_count = 200
这里可以看出是最大链接书限制在了200, 这也和我们第一次wrk后的结果一致。在这里将max 增大到1048576。
2. check iptables/tc的配置 很可惜这次作者的docker里没有这两个配置,不过在实际环境中这方面也可以作为一个check项。
3. 传输层的优化
通过netstat -s |grep socket
check socket overflowed
和 sockets dropped
确认有大量的套接字溢出导致的丢包,之后check套接字的队列大小:
$ ss -ltnp
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 10 10 0.0.0.0:80 0.0.0.0:* users:(("nginx",pid=10491,fd=6),("nginx",pid=10490,fd=6),("nginx",pid=10487,fd=6))
LISTEN 7 10 *:9000 *:* users:(("php-fpm",pid=11084,fd=9),...,("php-fpm",pid=10529,fd=7))
同时check 系统的 somaxconn
$ sysctl net.core.somaxconn
net.core.somaxconn = 10
这里nginx 和 php-fpm 的队列长度增大到 8192,而把 somaxconn 增大到 65536。
下面这个优化挺重要的, 现在系统中一个服务都是通过http client来请求其他服务的,如果这里有大量的请求的话,client服务所在的机器端口使用有可能很快达到上限,这里很容易成为瓶颈。 首先check tcp临时端口的配置情况。
$ sysctl net.ipv4.ip_local_port_range
net.ipv4.ip_local_port_range=20000 20050
$ sysctl -w net.ipv4.ip_local_port_range="10000 65535"
net.ipv4.ip_local_port_range = 10000 65535
很明显上面50个临时端口很容易达到上限。这里还有一个优化就是使用tcp链接的复用:
$ sysctl net.ipv4.tcp_tw_reuse
net.ipv4.tcp_tw_reuse = 0
$ sysctl -w net.ipv4.tcp_tw_reuse=1
4.应用层的优化 通过增加工作进程的方式突破应用层面的限制,在本次实验中通过增大php工作线程数目大大的提高了系统的吞吐量。
这种整体系能的优化太难了,需要对网络收发包所有路径都很熟悉,这需要在现实环境中大量的练习。 还有一点就是系统log一定要多去看看,哪里都有最直接的源头。
套路篇是作为之前几章的一个整体总结,所以把这部分放到一起来总结,这一部分很难一次消化,这种总结性的文章适合不断的来看。
USE 方法监控系能性能:
各模块的USE性能指标:
监控系统 promethous/alerm manager来一套
全链路追踪,日志监控。RED方法: RED 方法,是 Weave Cloud 在监控微服务性能时,结合 Prometheus 监控,所提出的一种监控思路——即对微服务来说,监控它们的请求数(Rate)、错误数(Errors)以及响应时间(Duration)。所以,RED 方法适用于微服务应用的监控,而 USE 方法适用于系统资源的监控。
这个后面单独整理一个图出来,按照命令去定位一个问题
终篇
最后一章啦,这一章全是案例,也是最重要的一章,网络一章还是不够深入(看完之后又感觉忘的差不多了)。 也许这个课程的结束才是整个性能分析优化路程的开始。
目录
第四十六讲 案例篇:为什么应用容器化后,启动慢了很多(2020.07.06) 第四十七讲 案例篇:服务器总是时不时丢包,我该怎么办(2020.07.07) 第四十九讲 案例篇:内核线程 CPU 利用率太高,我该怎么办(2020.07.11) 第五十讲 案例篇:动态追踪怎么用(2020.07.11) 第五十二讲 套路篇(2020.7.12)