【Base】Linux负载问题排查记录

前言 & 背景


💡Tips:下面的我只是用于临时记录,如果想要整个系统的稳定性得到保障和比较快速清晰定位到问题:还是需要比较完整风控告警机制 我后面是采用了:elk 做日志收集和分析 + python自动脚本 + elastalert 进行了告警

背景:

Linux 服务负载在某段时段突然出现较高的负载 :

排查思路:

  1. 某个时段的访问量暴增导致(业务驱动的正常情况)
  2. 定时任务的触发触发 (导致也性能突然拉高–> eg: a 其他服务的定时任务触发导致,可以通过服务调用的方式排查,普遍是 RPC 和 Http 接口调用导致; b 本机上的定时任务,查看定时任务列表,查看 Cpu, 网络,io 等资源最高占用程序)
  3. 某个服务的异常导致业务阻塞 ,导致大量的接口阻塞 (mysql, redis, 微服务中的其他服务。。等出现连接异常,死锁,负载过高,导致另外服务等待阻塞,从而负载过高)
  4. 被攻击ddos等(通过 ip 和 nginx 日志排查)

排查日志准备:

主要以 Nginx 日志为主:

  1. 每个项目 Nginxaccesserror 日志最好单独保存,按照每日分割,这可以方便以后每次排查快速定位,也可以方便日志的归档和清理;
1
2
3
4
5
6
7
8
http{
	...
	map $time_iso8601 $logdate {
    		'~^(?<ymd>\d{4}-\d{2}-\d{2})' $ymd;
    		default    'date-not-found';
  }
	...
}
  1. Nginx 日志适当加入更多的信息:eg : request_time 等
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
http{
	...
	log_format log_main '$remote_addr - $remote_user [$time_local] '
			    						'"$request" $status $body_bytes_sent '
			    						'"$http_referer" "$http_user_agent" '
			    						'"$request_time" "$upstream_response_time" '
			    						'"$upstream_connect_time" "$upstream_header_time" '
			    						'"$http_x_forwarded_for" ';
	...
}

Nginx 日志分析和常用统计:包括IP相关统计、页面访问统计、性能分析、TCP连接统计等相关命令的总结

Linux 基础排查

linux下获取占用内存资源最多的10个进程,可以使用如下命令组合:

1
ps aux|head -1;ps aux|grep -v PID|sort -rn -k +4|head

linux 下获取php-fpm 子进程数量:

1
ps -ef | grep "php-fpm" | grep "pool" | wc -l

linux统计tcp的各种状态情况 :

1
netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'

linux下获取占用CPU资源最多的10个进程,可以使用如下命令组合:

1
ps aux|head -1;ps aux|grep -v PID|sort -rn -k +3|head

linux CURL 分析请求各阶段消耗时间:

准备文件模版(curl.txt)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
\n
time_namelookup:  %{time_namelookup}\n
time_connect:  %{time_connect}\n
time_appconnect:  %{time_appconnect}\n
time_pretransfer:  %{time_pretransfer}\n
time_redirect:  %{time_redirect}\n
time_starttransfer:  %{time_starttransfer}\n
----------\n
time_total:  %{time_total}\n
\n

使用curl带以下参数请求

1
curl -w "@curl.txt" -o /dev/null -s https://www.sogo.com

参数说明

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
    NAMELOOKUP:从开始计算,域名解析完成的耗时

  CURLINFO_NAMELOOKUP_TIME. The time it took from the start until the name resolving was completed.

  CONNECT:从开始计算,TCP建立完成的耗时

  CURLINFO_CONNECT_TIME. The time it took from the start until the connect to the remote host (or proxy) was completed.

  APPCONNECT:从开始计算,应用层(SSL,在TCP之上的应用层)连接/握手完成的耗时

  CURLINFO_APPCONNECT_TIME. The time it took from the start until the SSL connect/handshake with the remote host was completed. (Added in in 7.19.0)

  PRETRANSFER:从开始计算,准备开始传输数据的耗时

  CURLINFO_PRETRANSFER_TIME. The time it took from the start until the file transfer is just about to begin. This includes all pre-transfer commands and negotiations that are specific to the particular protocol(s) involved.

  STARTTRANSFER:从开始计算,开始传输数据的耗时(libcurl接收到第一个字节)

  CURLINFO_STARTTRANSFER_TIME. The time it took from the start until the first byte is received by libcurl.

  TOTAL:总的耗时

  CURLINFO_TOTAL_TIME. Total time of the previous request.

  REDIRECT:整个过程重定向的耗时,如果整个过程没有重定向,这个时间为0

IP 统计

ip访问量统计

1
awk '{print $1}' access.log | sort -n | uniq | wc -l

查看某一段时间段的IP访问量(5-6点)

1
grep "07/Jan/2019:0[5-6]" access.log | awk '{print $1}' | sort | uniq -c| sort -nr | wc -l

查看访问量最频繁的10个IP

1
awk '{print $1}' access.log | sort -n |uniq -c | sort -rn | head -n 10

查看某个IP的访问情况,按照访问量排序

1
grep '172.168.1.10' access.log |awk '{print $7}'|sort |uniq -c |sort -rn |head -n 10

页面统计访问

查看访问最频繁的页面(Top10)

1
awk '{print $7}' access.log | sort |uniq -c | sort -rn | head -n 10

查看访问最频繁的页面(排除php页面)(Top10)

1
grep -v ".php" access.log | awk '{print $7}' | sort |uniq -c | sort -rn | head -n 10

查看页面访问次数超过100次的页面

1
cat access.log | cut -d ' ' -f 7 | sort |uniq -c | awk '{if ($1 > 100) print $0}' | less

查看最近1000条记录,访问量最高的页面

1
tail -1000 access.log |awk '{print $7}'|sort|uniq -c|sort -nr|less

请求量统计

统计每秒的请求数,top10的时间点(精确到秒)

1
awk '{print $4}' access.log |cut -c 14-21|sort|uniq -c|sort -nr|head -n 100

统计每分钟的请求数,top100的时间点(精确到分钟)

1
awk '{print $4}' access.log |cut -c 14-18|sort|uniq -c|sort -nr|head -n 100

统计每小时的请求数,top100的时间点(精确到小时)

1
awk '{print $4}' access.log |cut -c 14-15|sort|uniq -c|sort -nr|head -n 100

性能分析

列出传输时间超过3秒的页面,显示前20条

1
cat access.log|awk '($9 > 3){print $7}'|sort -n|uniq -c|sort -nr|head -20

列出php页面请求时间超过3秒的页面,并统计其出现的次数,显示前100条

1
cat access.log|awk '($9 > 1 && $7~/.php/){print $7}'|sort -n|uniq -c|sort -nr|head -100

TCP链接统计

查看当前TCP连接数

1
netstat -tan | grep "ESTABLISHED" | grep ":80" | wc -l

用tcpdump嗅探80端口的访问看看谁最高

1
tcpdump -i eth0 -tnn dst port 80 -c 1000 | awk -F"." '{print $1"."$2"."$3"."$4}' | sort | uniq -c | sort -nr
0%