原文3年多前發(fā)表在私人站點(diǎn)撒轮,現(xiàn)遷移到簡(jiǎn)書
最近搭了nginx作為日志服務(wù)器來做性能和操作分析,記錄一下過程和遇到的一些問題
日志
按天滾動(dòng)
按天滾動(dòng)一開始配置了logrotate實(shí)現(xiàn),執(zhí)行時(shí)間配置為0點(diǎn)0分祸憋,但實(shí)際真正執(zhí)行時(shí)間是0點(diǎn)1分,一開始懷疑是其他cron.daily的其他任務(wù)影響,畢竟cron.daily會(huì)處理很多東西
在cron.daily其他腳本上加了個(gè)日志唉工,統(tǒng)計(jì)開始時(shí)間和結(jié)束時(shí)間,確實(shí)發(fā)現(xiàn)logrotate因?yàn)閒reshclam的影響延遲了
start freshclam 00:01:04
end freshclam 00:01:16
start logrotate 00:01:17
但是還是不能解釋為什么不是0分開始汹忠,最后老老實(shí)實(shí)配置了一個(gè)獨(dú)立的任務(wù)
0 0 * * * ~/tengine/logrotate.sh
分隔符
默認(rèn)格式的分隔符比較混亂淋硝,因此采用了0x01,就是用vim編輯的時(shí)候要注意不是0x01宽菜,而是ctrl+v,ctrl+a
響應(yīng)時(shí)間
日志里面和時(shí)間相關(guān)的變量主要是2個(gè)谣膳,upstream_response_time
$request_time就是從接請(qǐng)求的第一個(gè)字節(jié)到發(fā)送完響應(yīng)數(shù)據(jù)的時(shí)間,即包括接收請(qǐng)求數(shù)據(jù)時(shí)間铅乡、程序響應(yīng)時(shí)間继谚、輸出響應(yīng)數(shù)據(jù)時(shí)間。
$upstream_response_time指從Nginx向后端建立連接開始到接受完數(shù)據(jù)然后關(guān)閉連接為止的時(shí)間隆判。
upstream_response_time值大犬庇,特別是使用POST方式傳遞參數(shù)時(shí),因?yàn)镹ginx會(huì)把request body緩存住侨嘀,接受完畢后才會(huì)把數(shù)據(jù)一起發(fā)給后端臭挽。所以如果用戶網(wǎng)絡(luò)較差,或者傳遞數(shù)據(jù)較大時(shí)咬腕,upstream_response_time大很多
日志分析
我們的模式是將日志定時(shí)同步到hadoop集群再進(jìn)行分析欢峰,不過也發(fā)現(xiàn)goaccess這個(gè)工具,可以比較好的分析日志,唯一的缺點(diǎn)是日志比較大的時(shí)間cpu飆高纽帖。宠漩。所以要分析最好換一臺(tái)機(jī)器
goaccess -f tengine/logs/a.log -a --date-format=%F --time-format=%T --log-format="%h %d %t %U %s %b %R %u %^ %^ %L"
referer CFNetwork
發(fā)現(xiàn)很多ua是 CFNetwork/672.X.X Darwin/14.X.X的沒有referer,懷疑是某些網(wǎng)絡(luò)環(huán)境下客戶端不是webview而是用的CFNetwork庫(kù)l來請(qǐng)求
性能配置
進(jìn)程數(shù)和連接數(shù)配置
worker_processes 3;
events {
use epoll;
multi_accept on;
worker_connections 4024;
}
長(zhǎng)連接和超時(shí)
我們的服務(wù)簡(jiǎn)單懊直,量還比較大扒吁,所以就把這個(gè)時(shí)間配置的盡量小,實(shí)際操作中發(fā)現(xiàn)基本維持在400來個(gè)連接室囊,連接數(shù)基本是請(qǐng)求量的1/2
keepalive_timeout 12;
curl 'http://127.0.0.1/nginx-status'
Active connections: 418
server accepts handled requests request_time
14168862 14168862 25943492 226096881
Reading: 1 Writing: 1 Waiting: 416
## 下面的兩個(gè)timeout一開始配置成10s雕崩,發(fā)現(xiàn)有部分http狀態(tài)碼是408的日志,就是因?yàn)?0s超時(shí)融撞,1分鐘還是會(huì)有幾條這樣的錯(cuò)誤盼铁,最重要的是錯(cuò)誤了以后這個(gè)日志會(huì)打到根的access.log,后面把這個(gè)值調(diào)大到30
client_header_timeout 30;
client_body_timeout 30;
sendfile尝偎、nopush饶火、nodelay
sendfile on;
tcp_nopush on;
tcp_nodelay on;
TCP 傳輸?shù)腗SS有1460字節(jié),為了提升網(wǎng)絡(luò)利用率致扯,避免擁塞肤寝,Nagle算法在發(fā)現(xiàn)要發(fā)送的數(shù)據(jù)太小的時(shí)候,會(huì)延時(shí)超過200ms再發(fā)送或者等數(shù)據(jù)超過MSS再發(fā)送急前,通過tcp_nodelay on可以關(guān)閉這個(gè)算法醒陆。當(dāng)然這個(gè)選項(xiàng)是在長(zhǎng)連接的情況下才有效的
tcp_nopush實(shí)際上對(duì)應(yīng)的是linux tcp棧的TCP_CORK選項(xiàng),他會(huì)禁止小包的發(fā)送裆针,直到超過MSS刨摩。在nginx他,他在sendfile on的情況下才有效世吨。sendfile可以讓靜態(tài)數(shù)據(jù)在內(nèi)核態(tài)直接發(fā)送數(shù)據(jù)澡刹,而不用上下文切換進(jìn)入用戶態(tài)再發(fā)送。
tcp_nodelay和tcp_nopush結(jié)合的時(shí)候耘婚,首先tcp_nopush會(huì)堆積數(shù)據(jù)直到MSS才發(fā)送罢浇,之后移除tcp_nopush,剩下的最后1個(gè)包會(huì)因?yàn)閠cp_nodelay馬上發(fā)送沐祷。
其他
gzip壓縮嚷闭、文件緩存等,不過在我們場(chǎng)景下并沒有啟用
tcp協(xié)議棧
協(xié)議棧主要是調(diào)整下滑動(dòng)窗口大小赖临,端口范圍胞锰,backlog等
# accept的隊(duì)列長(zhǎng)度
net.core.somaxconn = 3240000
# 所有進(jìn)程打開的文件總數(shù)
# 設(shè)置echo 6553560 > /proc/sys/fs/file-max
# 或修改 /etc/sysctl.conf, 加入
# fs.file-max = 6553560 重啟生效
sys.fs.file_max
#向外連接的端口范圍
net.ipv4.ip_local_port_range = 2000 65000
# 支持更大的TCP窗口. 如果TCP窗口最大超過65535(64KB), 必須設(shè)置該數(shù)值為1
net.ipv4.tcp_window_scaling = 1
# 同時(shí)所處理的最大timewait數(shù)量
net.ipv4.tcp_max_tw_buckets = 6000
# 接收緩沖區(qū)默認(rèn)值
net.core.rmem_default = 8388608
# 發(fā)送緩沖區(qū)默認(rèn)值
net.core.wmem_default = 8388608
# 接收緩沖區(qū)最大值
net.core.rmem_max = 16777216
# 發(fā)送緩沖區(qū)最大值
net.core.wmem_max = 16777216
# TCP接收緩沖區(qū),min default max
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216
ulimit
ulimit 設(shè)置當(dāng)前shell以及由它啟動(dòng)的進(jìn)程的資源限制兢榨,修改/etc/security/limits.conf
* soft nofile 65535
* hard nofile 65535
參考
1.被遺忘的Logrotate
2.使用nginx記日志
3.Tuning NGINX for Performance
4.神秘的40毫秒延遲與 TCP_NODELAY
5.Nginx 配置之性能篇
6.UNDERSTANDING SENDFILE, TCP_NODELAY AND TCP_NOPUSH
7.為最佳性能調(diào)優(yōu) Nginx