日B视频 亚洲,啪啪啪网站一区二区,91色情精品久久,日日噜狠狠色综合久,超碰人妻少妇97在线,999青青视频,亚洲一区二卡,让本一区二区视频,日韩网站推荐

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Linux服務(wù)器性能問題的排查指南

馬哥Linux運(yùn)維 ? 來源:馬哥Linux運(yùn)維 ? 2026-05-12 09:56 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

問題背景與核心思路

服務(wù)器性能問題通常歸結(jié)為四類資源瓶頸:CPU、內(nèi)存、磁盤 IO、網(wǎng)絡(luò)。任何性能下降、業(yè)務(wù)卡頓、響應(yīng)變慢的背后,都可以追溯到這四個(gè)維度的某一個(gè)(或多個(gè))達(dá)到了瓶頸。

很多工程師排查性能問題時(shí)的困境不是不知道命令,而是不知道什么情況該用什么命令、命令輸出的指標(biāo)代表什么含義、以及多個(gè)指標(biāo)之間如何交叉驗(yàn)證。比如 CPU idle 很低一定說明 CPU 是瓶頸嗎?free 內(nèi)存很少一定說明內(nèi)存不夠嗎?iostat 顯示 await 高一定是磁盤慢嗎?這些問題的答案都是"不一定"。本篇文章的目標(biāo),就是把 CPU、內(nèi)存、磁盤、網(wǎng)絡(luò)四個(gè)維度的原理、指標(biāo)、判斷方法和排查命令講透,讓你拿到一套指標(biāo)就能形成判斷。

每個(gè)維度的內(nèi)容結(jié)構(gòu)是統(tǒng)一的:先講清楚這個(gè)資源在 Linux 中是如何工作的,再講關(guān)鍵指標(biāo)是什么含義,最后給出具體排查命令和場(chǎng)景案例。

CPU:計(jì)算資源的調(diào)度

CPU 在 Linux 中的工作原理

Linux 的 CPU 調(diào)度以進(jìn)程為基本單位。每個(gè)進(jìn)程在創(chuàng)建時(shí)會(huì)被分配一個(gè)時(shí)間片(timeslice),時(shí)間片用完后被掛起,調(diào)度器選擇下一個(gè)要運(yùn)行的進(jìn)程。對(duì)于支持多核的 CPU,Linux 會(huì)把進(jìn)程分配到不同的核心上運(yùn)行,并通過負(fù)載均衡機(jī)制確保各核心的負(fù)載大致均衡。

CPU 有幾個(gè)核心概念需要理解:

用戶態(tài)(User Mode)和內(nèi)核態(tài)(Kernel Mode)。CPU 執(zhí)行指令時(shí)處于兩種模式:用戶態(tài)只能執(zhí)行普通指令,無法直接訪問硬件和內(nèi)核數(shù)據(jù)結(jié)構(gòu);內(nèi)核態(tài)可以執(zhí)行特權(quán)指令、訪問任意內(nèi)存區(qū)域、操控硬件。應(yīng)用程序運(yùn)行在用戶態(tài),系統(tǒng)調(diào)用和內(nèi)核代碼運(yùn)行在內(nèi)核態(tài)。當(dāng)應(yīng)用程序執(zhí)行系統(tǒng)調(diào)用(如讀寫文件、網(wǎng)絡(luò)通信),CPU 會(huì)從用戶態(tài)切換到內(nèi)核態(tài),完成操作后再切換回用戶態(tài)。CPU 在這兩種模式下消耗的時(shí)間比例是排查 CPU 問題的重要線索。

上下文切換(Context Switch)。CPU 在多個(gè)進(jìn)程之間切換時(shí),需要保存當(dāng)前進(jìn)程的狀態(tài)(寄存器、堆棧、程序計(jì)數(shù)器等)并加載下一個(gè)進(jìn)程的狀態(tài),這個(gè)過程叫上下文切換。每次上下文切換有固定的開銷(大約幾微秒)。如果上下文切換過于頻繁,CPU 會(huì)把大量時(shí)間花在這個(gè)開銷上,有效計(jì)算時(shí)間就會(huì)減少。cs(context switch)值很高的vmstat輸出通常是這個(gè)問題。

中斷(Interrupt)。硬件設(shè)備(網(wǎng)卡、磁盤、鍵盤等)需要 CPU 關(guān)注時(shí)會(huì)發(fā)送中斷信號(hào),CPU 停下當(dāng)前工作去處理中斷。中斷分為硬中斷(硬件觸發(fā))和軟中斷(內(nèi)核觸發(fā),用于網(wǎng)絡(luò)協(xié)議棧、調(diào)度等)。如果si(軟中斷)值很高,說明內(nèi)核在花大量時(shí)間處理軟中斷,可能是網(wǎng)絡(luò)流量過大。

運(yùn)行隊(duì)列(Run Queue)。所有就緒狀態(tài)(等待 CPU)的進(jìn)程組成一個(gè)或多個(gè)運(yùn)行隊(duì)列。vmstat中的r列就是運(yùn)行隊(duì)列長度。如果運(yùn)行隊(duì)列長度長期大于 CPU 核心數(shù),說明 CPU 資源嚴(yán)重不足,很多進(jìn)程在排隊(duì)等待。

CPU 關(guān)鍵指標(biāo)詳解

top命令輸出的 CPU 行是排查 CPU 問題的起點(diǎn):

%Cpu(s): 12.5 us, 3.2 sy, 0.0 ni, 82.1 id, 1.2 wa, 0.0 hi, 0.3 si, 0.0 st

us(user):CPU 執(zhí)行用戶態(tài)代碼的時(shí)間比例。值高說明應(yīng)用程序本身在大量計(jì)算。如果 us 很高且單個(gè)進(jìn)程 CPU 占用很高,問題在這個(gè)進(jìn)程自身(代碼算法問題、死循環(huán)等)

sy(system):CPU 執(zhí)行內(nèi)核態(tài)代碼的時(shí)間比例。系統(tǒng)調(diào)用、調(diào)度、內(nèi)存管理、文件系統(tǒng)、網(wǎng)絡(luò)協(xié)議棧都運(yùn)行在內(nèi)核態(tài)。sy 很高說明內(nèi)核處理壓力很大,常見于大量系統(tǒng)調(diào)用(頻繁讀寫文件、網(wǎng)絡(luò)通信)或頻繁的上下文切換

ni(nice):CPU 執(zhí)行被 nice 調(diào)整過的低優(yōu)先級(jí)進(jìn)程的時(shí)間比例。普通進(jìn)程 nice 值為 0,值越大優(yōu)先級(jí)越低。ni 高說明有大量低優(yōu)先級(jí)進(jìn)程在運(yùn)行

id(idle):CPU 空閑時(shí)間比例。id 接近 0 說明 CPU 幾乎沒有空閑,是非常繁忙的狀態(tài)。但 id 低不等于 CPU 是瓶頸——需要結(jié)合r列(運(yùn)行隊(duì)列)和業(yè)務(wù)響應(yīng)時(shí)間來判斷

wa(wait IO):CPU 等待 IO 操作完成的時(shí)間比例。wa 高是 IO 瓶頸的信號(hào),不是 CPU 瓶頸,見下文磁盤 IO 部分

hi(hardirq):CPU 處理硬件中斷的時(shí)間。hi 很高可能是設(shè)備驅(qū)動(dòng)問題或硬件故障

si(softirq):CPU 處理軟中斷的時(shí)間。網(wǎng)絡(luò)流量大、定時(shí)器處理、調(diào)度相關(guān)工作都會(huì)觸發(fā)軟中斷。si 高但其他指標(biāo)正常時(shí),可能只是網(wǎng)絡(luò)流量過載

Load Average是另一組關(guān)鍵指標(biāo):

load average: 5.23, 3.10, 2.15

這三個(gè)數(shù)字分別是 1 分鐘、5 分鐘、15 分鐘的負(fù)載均值。負(fù)載均值 = 運(yùn)行隊(duì)列中的平均進(jìn)程數(shù) + 不可中斷睡眠狀態(tài)的平均進(jìn)程數(shù)(通常是等待 IO 的進(jìn)程)。判斷負(fù)載是否過高,需要結(jié)合 CPU 核心數(shù):

# 查看 CPU 核心數(shù)
nproc
# 或
grep"processor"/proc/cpuinfo | wc -l

如果 CPU 有 8 核心,load average 是 8,說明 CPU 恰好滿載;如果 load 是 16,說明有 8 個(gè)進(jìn)程在排隊(duì)等待 CPU。

CPU 排查命令清單

# 基礎(chǔ)查看
top           # 默認(rèn)視圖,CPU 按占比排序
top -b -n 1 -o %CPU  # 批處理模式,按 CPU 排序,用于腳本采集
top -p       # 只看特定進(jìn)程
top -H -p     # 看進(jìn)程的線程級(jí) CPU 占用

# CPU 持續(xù)監(jiān)控
vmstat 1 10      # 每 1 秒采樣,共 10 次,關(guān)注 r、us、sy、id、wa 列
mpstat -P ALL 1 5   # 每個(gè) CPU 核心的使用率,多路 CPU 服務(wù)器必用
# 關(guān)注每個(gè)核心的 %usr、%sys、%idle,排查負(fù)載不均(某幾個(gè)核心 100%,其他空閑)

# 按進(jìn)程排序
ps aux --sort=-%cpu | head -n 11  # 按 CPU 排序前 10 個(gè)進(jìn)程
ps -eo pid,ppid,%cpu,%mem,comm --sort=-%cpu | head -n 11

# 進(jìn)程的 CPU 時(shí)間分解
pidstat -p  1 5  # 每秒采樣 5 次,顯示 usr/system/wait/cpu
pidstat -w -p  1 5# 上下文切換詳情
pidstat -u -p  1 5# 線程級(jí) CPU 占用(需要 -T ALL)

# 查看運(yùn)行隊(duì)列長度
vmstat 1 | awk'NR>2 {print "runq:", $4, "CPU核數(shù):", $NF}'
# 如果 runq 長期 > CPU 核心數(shù) * 4,說明調(diào)度壓力很大

# 中斷分布(查看是否是某個(gè)硬件設(shè)備在制造大量中斷)
cat /proc/interrupts
# 關(guān)注第二列(CPU0 的中斷數(shù)),如果某個(gè)設(shè)備中斷數(shù)異常高,說明它可能是瓶頸

CPU 瓶頸的判斷標(biāo)準(zhǔn)

判斷 CPU 是否是瓶頸,不能只看單一指標(biāo),需要交叉驗(yàn)證:

第一步:top看 us 和 id。us 高 + id 低 → 用戶代碼問題(多數(shù)情況)。sy 高 + id 低 → 內(nèi)核壓力或大量系統(tǒng)調(diào)用。

第二步:vmstat 1 10看r列。r > CPU 核心數(shù) * 2 持續(xù)多秒,說明運(yùn)行隊(duì)列積壓,確認(rèn) CPU 不足。

第三步:ps aux --sort=-%cpu找到具體進(jìn)程。確認(rèn)是哪個(gè)進(jìn)程吃 CPU。

第四步:結(jié)合業(yè)務(wù)場(chǎng)景判斷。如果這個(gè)進(jìn)程本來就該吃 CPU(如壓縮、加密、數(shù)據(jù)計(jì)算),CPU 100% 可能是正常的,問題在其他地方(架構(gòu)優(yōu)化、算法優(yōu)化、資源擴(kuò)展)。如果這個(gè)進(jìn)程不應(yīng)該吃這么多 CPU(如一個(gè) Web 服務(wù)進(jìn)程,平時(shí) 5% 突然變 90%),才需要進(jìn)一步分析。

常見誤區(qū):vmstat 顯示 CPU idle 為 0,不一定說明 CPU 是瓶頸。如果 r 列也很?。ń咏?0),可能是進(jìn)程在等待 IO(wa 高)。CPU idle 為 0 但 r 很小,說明 CPU 幾乎沒閑著但也沒多少事干——這種情況通常說明是大量短時(shí)進(jìn)程在輪轉(zhuǎn),每個(gè)只占用一點(diǎn)點(diǎn)時(shí)間,但 CPU 在不斷切換,sy 可能很高。

場(chǎng)景案例:Nginx 突然變慢

現(xiàn)象:Nginx 服務(wù)器響應(yīng)時(shí)間從 10ms 突然上升到 200ms,但業(yè)務(wù)請(qǐng)求量沒有明顯變化。

排查步驟:

# 1. 看 CPU 各維度指標(biāo)
top -b -n 1
# 發(fā)現(xiàn): us=25%, sy=70%, id=5% —— sy 非常高,說明內(nèi)核態(tài)壓力大

vmstat 1 5
# 發(fā)現(xiàn): r=2, cs=15000, us=20%, sy=65%
# cs=15000(每秒 15000 次上下文切換)遠(yuǎn)高于正常值(通常幾百)
# 大量上下文切換是 sy 高的根因

# 2. 找是誰在制造上下文切換
ps aux --sort=-%cpu | head -n 15
# 沒有進(jìn)程 CPU 占用特別高

# 3. 查看網(wǎng)絡(luò)連接狀態(tài)(可能是網(wǎng)絡(luò)請(qǐng)求碎片化)
ss -s
# 發(fā)現(xiàn): TCP: 50000(estab 49500, timewait 500)
# 有 500 個(gè) TIME_WAIT 連接,每秒創(chuàng)建和銷毀的短連接很多

# 4. 查看系統(tǒng)調(diào)用頻率
strace -c -p  5 2>&1
# 運(yùn)行 5 秒后 Ctrl+C,輸出各系統(tǒng)調(diào)用的次數(shù)和時(shí)間
# 如果 close() 和 accept() 次數(shù)異常高,說明是連接頻繁建立和關(guān)閉

# 5. 結(jié)論
# Nginx 的 worker 進(jìn)程在頻繁 accept() 和 close() 短連接,導(dǎo)致大量上下文切換
# 內(nèi)核把大量時(shí)間花在了進(jìn)程調(diào)度上,有效處理請(qǐng)求的時(shí)間變少

修復(fù)方案:啟用 Nginx 的 keepalive 長連接,減少連接建立和關(guān)閉的頻率;調(diào)整內(nèi)核的 tcp_fin_timeout 和 tcp_tw_reuse 參數(shù)。

內(nèi)存:物理資源的消耗

內(nèi)存管理原理

Linux 的內(nèi)存管理遠(yuǎn)比"應(yīng)用程序申請(qǐng),內(nèi)核分配"復(fù)雜。理解以下概念是排查內(nèi)存問題的基礎(chǔ)。

物理內(nèi)存和虛擬內(nèi)存。每個(gè)進(jìn)程有獨(dú)立的虛擬地址空間(32 位系統(tǒng)是 4GB,64 位系統(tǒng)是巨大的地址空間)。虛擬地址通過內(nèi)存管理單元(MMU)和頁表映射到物理地址。應(yīng)用程序不需要關(guān)心物理內(nèi)存是否夠用,內(nèi)核通過缺頁中斷按需將虛擬頁映射到物理頁。

Buddy 分配算法。內(nèi)核以頁(page)為單位管理物理內(nèi)存,每頁 4KB。Buddy 系統(tǒng)把物理內(nèi)存按 2 的冪次方分成塊(1 頁、2 頁、4 頁、8 頁……),當(dāng)應(yīng)用程序申請(qǐng)內(nèi)存時(shí),內(nèi)核從最接近的塊中分配。Buddy 系統(tǒng)的優(yōu)點(diǎn)是沒有內(nèi)存碎片,缺點(diǎn)是內(nèi)部碎片(分配了 8 頁但只用了 1 頁,浪費(fèi) 7 頁)。

Slab 分配器。內(nèi)核的很多數(shù)據(jù)結(jié)構(gòu)(如進(jìn)程描述符、文件描述符、inode)大小固定且頻繁創(chuàng)建銷毀,Buddy 系統(tǒng)無法高效管理這些固定大小的對(duì)象。Slab 分配器為每種對(duì)象類型維護(hù)一個(gè)緩存池,提前創(chuàng)建并緩存這些對(duì)象,用完立即放回緩存而不是歸還給 Buddy 系統(tǒng)。

Page Cache。磁盤上的文件被讀取時(shí),內(nèi)核會(huì)把數(shù)據(jù)緩存在物理內(nèi)存的 Page Cache 中,下次讀取同一文件時(shí)直接從內(nèi)存返回,不需要再讀磁盤。寫入文件時(shí),數(shù)據(jù)先寫到 Page Cache,然后由內(nèi)核的 flusher 線程異步刷寫到磁盤(write-back 策略)。Page Cache 是 Linux 用空閑內(nèi)存提升 IO 性能的核心機(jī)制。

Swap。當(dāng)物理內(nèi)存不足時(shí),內(nèi)核會(huì)把最近很少使用的物理頁寫入磁盤的 swap 空間(通常是獨(dú)立的 swap 分區(qū)或 swap 文件),然后把騰出來的物理頁分配給需要的進(jìn)程。這個(gè)過程叫換出(swap out)。被換出的頁在程序訪問時(shí)會(huì)被換入(swap in),換入需要一次磁盤 IO。如果 swap 被頻繁觸發(fā),磁盤 IO 會(huì)急劇增加,系統(tǒng)會(huì)明顯變慢。

OOM Killer。當(dāng)物理內(nèi)存和 swap 都耗盡時(shí),內(nèi)核的 Out-of-Memory Killer 會(huì)啟動(dòng),它會(huì)選擇占用內(nèi)存最多且評(píng)分最高的進(jìn)程,將其殺死并釋放內(nèi)存。這是 Linux 防止系統(tǒng)完全崩潰的最后防線,但被 kill 的可能是關(guān)鍵服務(wù)。

內(nèi)存關(guān)鍵指標(biāo)詳解

free是查看內(nèi)存最直接的命令:

free -h

# 輸出示例:
#        total    used    free   shared buff/cache  available
# Mem:      31Gi    28Gi    1.2Gi    200Mi    2.5Gi    2.8Gi
# Swap:     8.0Gi    500Mi    7.5Gi

不要看 free 列,要看 available 列。Linux 會(huì)把空閑內(nèi)存用于 Page Cache(buff/cache 列),但 Page Cache 在需要時(shí)可以被回收,所以 available 才是真正可以被應(yīng)用程序使用的內(nèi)存。free 很少但 available 還有很多是正常狀態(tài),不是內(nèi)存不足。

MemAvailable的計(jì)算方式:MemFree + 可回收的 Page Cache + 可回收的 SReclaimable(Slab 中可回收的部分)。在/proc/meminfo中可以看更詳細(xì)的數(shù)據(jù):

cat /proc/meminfo

# 關(guān)鍵字段解讀:
# MemTotal:    32880324 kB  物理內(nèi)存總量
# MemFree:     1254784 kB  未被分配的內(nèi)存
# MemAvailable:  2897344 kB  真正可用的內(nèi)存(推薦關(guān)注)
# Buffers:     198732 kB  塊設(shè)備直接讀寫的緩存(小,主要用于裸設(shè)備)
# Cached:     2156784 kB  文件系統(tǒng) Page Cache(大,是 buff/cache 的主要部分)
# SwapCached:     1234 kB   已在 swap 中但又被換入物理內(nèi)存的頁(避免二次 IO)
# Active:     1234567 kB  最近使用過的內(nèi)存頁,不能輕易回收
# Inactive:     876543 kB  最近未使用的內(nèi)存頁,可以回收
# SReclaimable:   234567 kB  Slab 中可回收的部分(如 dentry cache、inode cache)
# SwapTotal:    8388604 kB  swap 總大小
# SwapFree:    7886040 kB  swap 剩余空間
# Mapped:      345678 kB  mmap 映射到內(nèi)存的文件(如動(dòng)態(tài)庫、mmap 文件)
# VmallocUsed:   123456 kB  vmalloc 區(qū)域使用量(通常很小)

判斷內(nèi)存是否真的不足:

available < total * 0.2?且?swapfree?持續(xù)下降 → 內(nèi)存壓力

si(swap in)和so(swap out)在vmstat中持續(xù)不為 0 → 物理內(nèi)存不夠

OOMKiller啟動(dòng):dmesg | grep -i "out of memory"或dmesg | grep -i "killed process"

Slab 內(nèi)存占用:SReclaimable和SUnreclaim加起來是 Slab 分配器的總占用。如果SUnreclaim很大(不可回收的 Slab),可能是內(nèi)核內(nèi)存泄漏:

# 查看 Slab 占用最大的對(duì)象類型
cat /proc/slabinfo | awk'{print $1, $3, $4}'| sort -k3 -rn | head -20
# 或者用 slabtop(類似 top 的界面)
slabtop -s c | head -20

內(nèi)存排查命令清單

# 基礎(chǔ)查看
free -h             # 概況,重點(diǎn)看 available
cat /proc/meminfo         # 詳細(xì)內(nèi)存數(shù)據(jù)
vmstat 1 5            # 關(guān)注 si/so(swap 換入換出)

# 查看進(jìn)程的內(nèi)存占用
ps aux --sort=-%mem | head -n 11 # 按內(nèi)存排序前 10
ps -eo pid,ppid,%mem,%cpu,rss,vsz,comm --sort=-%mem | head -n 11
# RSS:進(jìn)程實(shí)際占用的物理內(nèi)存(Resident Set Size)
# VSZ:進(jìn)程申請(qǐng)的虛擬內(nèi)存大?。ú灰欢▽?shí)際占用)

# 使用 ps_mem.py 精確查看每個(gè)進(jìn)程的內(nèi)存占用(按進(jìn)程合并)
python3 ps_mem.py
# 輸出:每行一個(gè)進(jìn)程,顯示 Private RAM + Shared RAM = Total RAM

# 查看某個(gè)進(jìn)程的內(nèi)存映射(查看加載了哪些庫、mmap 文件等)
cat /proc//maps

# 查看進(jìn)程的內(nèi)存詳情(smaps 格式更詳細(xì))
cat /proc//smaps | head -n 30
# 每個(gè)映射區(qū)域的大小、RSS、共享狀態(tài)

# 查看 Vmalloc 區(qū)域使用(內(nèi)核內(nèi)存泄漏的信號(hào))
cat /proc/vmstat | grep -E"nr_vmalloc_pages|vmalloc"

# 查看 OOM Killer 日志
dmesg | grep -i"out of memory"
dmesg | grep -i"killed process"

# 持續(xù)監(jiān)控內(nèi)存變化(采樣 60 秒)
watch -n 1'cat /proc/meminfo | grep -E "MemAvailable|SwapFree|Cached|Buffers"'

判斷內(nèi)存是否是瓶頸

內(nèi)存不足和內(nèi)存緊張的區(qū)分:內(nèi)存不足是指物理內(nèi)存完全耗盡,OOM Killer 啟動(dòng)。內(nèi)存緊張是指 available 偏低但還沒有觸發(fā) swap 或 OOM。兩者都值得關(guān)注,但緊迫程度不同。

vmstat 中 si/so 的判斷:如果so(swap out)持續(xù)每秒幾百 KB 到幾 MB,說明系統(tǒng)在把內(nèi)存頁換出磁盤。偶爾一點(diǎn) swap 是正常的(內(nèi)存分配高峰后的正常回收),但如果so持續(xù)不斷,說明物理內(nèi)存確實(shí)不夠用了。

判斷是應(yīng)用內(nèi)存泄漏還是正常高負(fù)載:如果內(nèi)存占用持續(xù)增長且不回落,有幾種可能:

應(yīng)用正常緩存(緩存命中率提升后內(nèi)存占用會(huì)穩(wěn)定)

應(yīng)用內(nèi)存泄漏(內(nèi)存只增不減,最終 OOM)

Slab 內(nèi)存泄漏(內(nèi)核 bug,Slab 只增不減)

用ps_mem.py或ps持續(xù)觀察是哪個(gè)進(jìn)程在增長。如果所有進(jìn)程內(nèi)存都在增長但沒有單個(gè)進(jìn)程特別突出,可能是 Slab 問題。

Java 進(jìn)程的內(nèi)存要注意堆外內(nèi)存:JVM 進(jìn)程的內(nèi)存占用 = 堆內(nèi)存 + 元空間(Metaspace)+ 直接內(nèi)存(DirectByteBuffer)+ Native 內(nèi)存(JNI、mmap、JVM 自身)。只看 JVM 的-Xmx參數(shù)不能反映進(jìn)程的真實(shí)物理內(nèi)存占用。用jcmd VM.native_memory或jmap -heap查看詳細(xì)分布。

場(chǎng)景案例:服務(wù)器突然開始 swap

現(xiàn)象:監(jiān)控告警 swap 使用量從 0 增長到 2GB,服務(wù)器開始變慢。

# 1. 查看內(nèi)存和 swap 概況
free -h
# Mem: total=31G used=30G available=1.5G buff/cache=2G
# Swap: total=8G used=2G free=6G
# 物理內(nèi)存 used 30G / 31G,available 只有 1.5G,確實(shí)緊張

# 2. 查看哪些進(jìn)程在用 swap
forfin/proc/*/status;do
  awk'/VmSwap/{s=$2}/Name/{n=$2}END{if(s+0>0) print n, s}'"$f"
done| sort -k2 -rn | head -10
# 輸出:
# mysqld  1024000 kB  約 1GB
# java   614400 kB  約 600MB
# redis   307200 kB   約 300MB

# 3. 看這三個(gè)進(jìn)程的內(nèi)存總量是否合理
ps aux | awk'/mysqld|java|redis/{print $2, $6, $11}'
# mysqld: RSS=28GB(它本來就這么大,業(yè)務(wù)數(shù)據(jù)庫)
# java:  RSS=6GB
# redis: RSS=4GB
# 三個(gè)加起來 = 38GB,超過了 31GB 物理內(nèi)存

# 4. 判斷根因
# mysqld 28GB 是正常的(配置了很大的 Buffer Pool)
# 但 mysqld 已經(jīng)占用了 28GB,物理內(nèi)存只有 31GB
# Java 和 Redis 被擠到 swap 里去了

# 5. 查看 mysqld 配置
mysql -u root -p -e"SHOW VARIABLES LIKE 'innodb_buffer_pool_size';"
# +------------------------+----------+
# | Variable_name     | Value  |
# +------------------------+----------+
# | innodb_buffer_pool_size | 28730992640 | 約 26.7GB

結(jié)論:MySQL 的 Buffer Pool 配置為 27GB,加上操作系統(tǒng)和其他進(jìn)程的內(nèi)存占用,物理內(nèi)存剛好夠用甚至略不足。當(dāng) Java 或 Redis 也需要內(nèi)存時(shí),OS 沒有足夠的 available 內(nèi)存,就把其他進(jìn)程的頁換到 swap。

修復(fù)方案:減小 MySQL 的innodb_buffer_pool_size,留出 2~3GB 給 OS 和其他進(jìn)程;或者增加物理內(nèi)存。swap 本身是 Linux 的正常工作機(jī)制,但如果 swap 使用量持續(xù)增長且影響業(yè)務(wù)響應(yīng)時(shí)間,就必須解決。

磁盤 IO:持久化性能的瓶頸

磁盤 IO 原理

磁盤 IO 是服務(wù)器性能問題中最復(fù)雜的一類,因?yàn)?IO 路徑長、涉及的內(nèi)核層次多、可優(yōu)化空間大。理解 IO 路徑是排查 IO 問題的基礎(chǔ)。

Linux 存儲(chǔ) IO 棧(從上到下):

應(yīng)用程序:發(fā)起 read()/write() 系統(tǒng)調(diào)用

VFS 層(Virtual File System Switch):統(tǒng)一抽象了文件系統(tǒng)接口,不管下層是 ext4、xfs 還是 btrfs

文件系統(tǒng)層:ext4/xfs 等,在文件系統(tǒng)和頁緩存之間協(xié)調(diào)寫入。寫操作首先寫入頁緩存(Page Cache),然后由 flusher 線程異步刷寫到磁盤

塊設(shè)備層(Block Layer):管理磁盤請(qǐng)求隊(duì)列,對(duì)請(qǐng)求排序和合并(電梯調(diào)度算法)

調(diào)度器:如 cfq、deadline、noop,按策略決定請(qǐng)求的順序和時(shí)機(jī)

控制器驅(qū)動(dòng):SCSI/SATA/NVMe 控制器

磁盤介質(zhì):機(jī)械硬盤(HDD)或固態(tài)硬盤(SSD/NVMe)

Page Cache 對(duì) IO 的影響。Linux 默認(rèn)對(duì)所有文件 IO 做緩存(寫時(shí)是 write-back,先寫緩存再異步刷盤)。讀操作:如果數(shù)據(jù)在 Page Cache 中(cache hit),直接返回內(nèi)存,不需要磁盤 IO;如果 cache miss,需要從磁盤讀取并緩存到 Page Cache。這意味著free命令顯示的內(nèi)存占用,有相當(dāng)一部分是 Page Cache。

同步寫(O_SYNC)和直接 IO(O_DIRECT)。有些場(chǎng)景需要繞過 Page Cache:數(shù)據(jù)庫的redo log 通常使用 O_SYNC(每次寫入必須等到磁盤確認(rèn));有些數(shù)據(jù)庫使用 O_DIRECT 繞過 Page Cache 直接讀寫磁盤,以實(shí)現(xiàn)自己更精確的緩存控制。

IO 調(diào)度器。機(jī)械硬盤的讀寫速度遠(yuǎn)慢于磁頭移動(dòng)時(shí)間,調(diào)度器通過排序和合并請(qǐng)求來減少磁頭移動(dòng)距離。常見調(diào)度器:

cfq(Completely Fair Queuing):為每個(gè)進(jìn)程維護(hù)一個(gè) IO 隊(duì)列,盡量公平分配 IO 帶寬。適合桌面和通用 Linux 發(fā)行版

deadline:每個(gè)請(qǐng)求有截止時(shí)間,優(yōu)先處理即將超時(shí)的請(qǐng)求。最適合數(shù)據(jù)庫場(chǎng)景,因?yàn)閿?shù)據(jù)庫的 IO 有明顯的順序特征和延遲敏感特性

noop:簡單 FIFO,不做排序,適合 SSD(SSD 沒有磁頭移動(dòng),排序無意義)和虛擬化 IO

磁盤 IO 關(guān)鍵指標(biāo)

iostat是查看磁盤 IO 的核心工具:

iostat -xz 1 5

# 輸出:
# Device rrqm/s  wrqm/s   r/s   w/s  rkB/s  wkB/s avgrq-sz avgqu-sz  await r_await w_await svctm %util
# sda    0.00   1.23  2.10  8.45  120.00  540.00  62.78   0.45  4.23  1.20  5.10  2.10  8.50
# dm-0   0.00   0.00  2.00  9.00  118.00  542.00  65.00   0.50  4.50  1.10  5.20  2.20  9.00

rrqm/s和wrqm/s:每秒合并的讀寫請(qǐng)求數(shù)。調(diào)度器把多個(gè)相鄰扇區(qū)的請(qǐng)求合并成一個(gè),可以減少 IO 次數(shù)

r/s和w/s:每秒實(shí)際發(fā)生的讀寫次數(shù)(IOPS)。機(jī)械硬盤 IOPS 約 100~200;SAS 15000轉(zhuǎn)約 200~300;SATA SSD 約 10,000~100,000;NVMe 可達(dá) 100,000~1,000,000

rkB/s和wkB/s:每秒讀寫的數(shù)據(jù)量(吞吐量,KB/s)。機(jī)械硬盤吞吐量約 100~200MB/s;SATA SSD 約 500MB/s;NVMe 可達(dá)數(shù) GB/s

avgrq-sz:平均每個(gè) IO 請(qǐng)求的大小(扇區(qū)數(shù))。值大說明是順序讀寫,值小說明是隨機(jī)讀寫

avgqu-sz:平均等待處理的請(qǐng)求隊(duì)列長度。這個(gè)值持續(xù)大于 1,說明磁盤請(qǐng)求開始積壓;大于 10 說明嚴(yán)重?fù)砣?/p>

await:平均每次 IO 請(qǐng)求的等待時(shí)間(毫秒),包括排隊(duì)時(shí)間和實(shí)際 IO 時(shí)間。判斷 IO 性能的黃金指標(biāo)

r_await和w_await:讀寫各自的平均等待時(shí)間

svctm:平均服務(wù)時(shí)間(不包含排隊(duì)時(shí)間),這個(gè)值接近實(shí)際 IO 速度的極限

%util:磁盤利用率。接近 100% 說明磁盤已經(jīng)飽和。但如果是 RAID 卡或 SSD,100% util 不一定是瓶頸,因?yàn)樗鼈兛梢圆⑿刑幚矶鄠€(gè)請(qǐng)求

判斷 IO 瓶頸的標(biāo)準(zhǔn)(機(jī)械硬盤):

util > 80%+await > 50ms→ 磁盤飽和

avgqu-sz > 2持續(xù) → 請(qǐng)求積壓

svctm接近磁盤標(biāo)稱 IO 延遲(如 7200 轉(zhuǎn) HDD 約 9ms)→ 磁盤處理時(shí)間已達(dá)極限

SSD/NVMe 的判斷標(biāo)準(zhǔn)不同:SSD 的 IO 延遲是微秒級(jí)(0.1~1ms),await > 10ms才算異常。SSD 的util接近 100% 通常是因?yàn)檫_(dá)到了并發(fā)上限,而不是隊(duì)列積壓。

磁盤 IO 排查命令清單

# iostat 查看磁盤 IO 概況(必用)
iostat -xz 1 5          # -x 顯示擴(kuò)展信息,-z 隱藏沒有 IO 的設(shè)備
iostat -d -p sda 1 5       # 只看特定磁盤和它的分區(qū)
iostat -n 2 5          # -n 顯示 NFS 等網(wǎng)絡(luò)文件系統(tǒng)

# 查看各分區(qū)的 IO
iostat -p ALL 1 5

# 查看 IO 和 CPU 的關(guān)系(判斷是否 CPU 在等 IO)
vmstat 1 5
# wa 列高 + id 列高(CPU 空閑但 IO 高)= 等待 IO
# wa 列高 + id 列低 = CPU 和 IO 都緊張

# 查看是哪個(gè)進(jìn)程在制造 IO(需要 root)
iotop             # 交互式,按 IO 排序
iotop -b -n 10         # 批處理模式,用于腳本
iotop -p          # 只看特定進(jìn)程
iotop -a            # 顯示累計(jì) IO 總量(可以看到誰從開始到現(xiàn)在 IO 最多)
iotop -o            # 只顯示有 IO 活動(dòng)的進(jìn)程

# pidstat 查看進(jìn)程級(jí) IO
pidstat -d -p  1 5    # 每秒采樣,顯示 kB_rd/s, kB_wr/s
pidstat -d 1 5         # 所有進(jìn)程的 IO

# 查看進(jìn)程打開了哪些文件(結(jié)合 lsof 理解 IO 來源)
lsof -p 

# 查看文件系統(tǒng)的掛載選項(xiàng)(有些性能問題來自不恰當(dāng)?shù)膾燧d選項(xiàng))
mount | grep ^/dev
# 比如 noatime 掛載可以減少不必要的寫 IO(Linux 默認(rèn)會(huì)更新文件的 access time)
# 如果 /var/log 是 noatime,說明訪問日志文件不會(huì)觸發(fā)額外的元數(shù)據(jù)寫

# 查看磁盤剩余空間和 inode 使用率
df -h             # 查看各分區(qū)空間
df -i             # 查看各分區(qū) inode 使用率(inode 耗盡也會(huì)導(dǎo)致無法創(chuàng)建文件)

# 查看目錄的 IO 壓力來源
# 使用 blktrace 分析 IO 請(qǐng)求的來源(需要安裝 blktrace 包,高級(jí)用法)

IO 瓶頸的判斷邏輯

第一步:iostat看util和await。util 接近 100% 且 await > 50ms(HDD),確認(rèn)是 IO 瓶頸。

第二步:iotop找到制造 IO 的進(jìn)程,確認(rèn)是哪個(gè)進(jìn)程。數(shù)據(jù)庫(mysqld、postgres)寫入量大是正常的;如果某個(gè)不明進(jìn)程在大量寫盤,需要排查。

第三步:分析是順序 IO 還是隨機(jī) IO??碼vgrq-sz(平均請(qǐng)求大?。┖蛂/s/w/s的比值。數(shù)據(jù)庫的 data file 讀寫通常是 4K~16K 的隨機(jī)讀寫;順序讀寫的大文件(備份、日志收集)請(qǐng)求大小會(huì)更大。

第四步:如果是數(shù)據(jù)庫 IO 異常,看是讀寫比例、IO 量、還是 IO 延遲問題。調(diào)整調(diào)度器、啟用 O_DIRECT、配置 InnoDB 日志文件大小等都是常見的數(shù)據(jù)庫 IO 優(yōu)化方向。

常見誤區(qū):util高一定是磁盤慢嗎?不一定。如果一塊 RAID 卡有 8 塊磁盤組成,RAID 控制器的util是所有磁盤的平均利用率,可能 8 塊盤只有 2 塊滿載但 RAID 卡顯示 100% util。應(yīng)該同時(shí)看avgqu-sz(隊(duì)列長度)來判斷是否有請(qǐng)求積壓。

場(chǎng)景案例:寫入日志文件導(dǎo)致 IO 100%

現(xiàn)象:服務(wù)器 load 很高,但 CPU idle 也不低,vmstat 顯示b列(不可中斷進(jìn)程)大于 0。

# 1. 用 iostat 確認(rèn)是 IO 問題
iostat -xz 1 3
# sda: util=98%, await=85ms, avgqu-sz=45
# 98% util 且 await 85ms,確認(rèn)是 sda 的 IO 瓶頸

# 2. 用 iotop 找制造 IO 的進(jìn)程
iotop -b -n 10 | head -30
# 發(fā)現(xiàn):rsyslogd 進(jìn)程每秒寫盤 50MB,排名第一

# 3. 確認(rèn)是日志寫入導(dǎo)致的
lsof | grep rsyslog
# /var/log/messages
# /var/log/secure
# /var/log/nginx/access.log
# ...

# 4. 查看日志寫入量大的原因
# /var/log/nginx/access.log 增長非???# 這是因?yàn)闃I(yè)務(wù)量突然增大?還是有人在頻繁訪問?
tail -f /var/log/nginx/access.log

# 5. 評(píng)估影響
# 如果 nginx 日志是業(yè)務(wù)正常流量,寫入量大是合理的
# 解決方案:啟用日志輪轉(zhuǎn)(logrotate),不要讓單個(gè)日志文件無限增長
# 或者把日志目錄掛載到 SSD 上
# 或者調(diào)整 rsyslog 的緩沖策略(減少同步次數(shù))

# 6. 如果是臨時(shí)方案,可以暫時(shí)調(diào)高 rsyslog 的寫入緩沖區(qū)
# 編輯 /etc/rsyslog.conf 或 /etc/rsyslog.d/*.conf
# $ActionFileEnableSync off # 關(guān)閉每條日志強(qiáng)制同步
# $OMFileFlushInterval 1  # 緩沖 1 秒后寫入

網(wǎng)絡(luò):數(shù)據(jù)傳輸?shù)耐ǖ?/p>

網(wǎng)絡(luò)原理與 Linux 網(wǎng)絡(luò)棧

Linux 的網(wǎng)絡(luò)棧從網(wǎng)卡驅(qū)動(dòng)到應(yīng)用程序大致分為:網(wǎng)卡驅(qū)動(dòng) → 驅(qū)動(dòng)層(Ring Buffer)→ 軟中斷處理(IRQ)→ 協(xié)議棧(TCP/UDP/IP)→ Socket 緩沖區(qū) → 應(yīng)用程序。

網(wǎng)卡的 Ring Buffer。網(wǎng)卡收到數(shù)據(jù)包后,先存到 Ring Buffer(環(huán)形緩沖區(qū)),然后觸發(fā) IRQ 通知 CPU。如果數(shù)據(jù)包到達(dá)速度超過 CPU 處理速度,Ring Buffer 會(huì)滿,新數(shù)據(jù)包被丟棄(RX drop)。這個(gè)參數(shù)直接影響網(wǎng)卡在高流量時(shí)的丟包情況。

軟中斷與協(xié)議棧。數(shù)據(jù)包從 Ring Buffer 取出后,進(jìn)入軟中斷(softirq)處理,協(xié)議棧(TCP/UDP)解析數(shù)據(jù)包,更新 Socket 緩沖區(qū)的狀態(tài)。高流量時(shí),軟中斷 CPU 占用(si)可能很高。

Socket 緩沖區(qū)。每個(gè) TCP/UDP 連接在協(xié)議棧中有一個(gè) Socket 緩沖區(qū)。應(yīng)用程序讀數(shù)據(jù)從緩沖區(qū)拿,應(yīng)用程序?qū)憯?shù)據(jù)放到緩沖區(qū)。緩沖區(qū)大小通過net.core.rmem_max/wmem_max控制,太小會(huì)限制吞吐量,太大會(huì)增加內(nèi)存壓力。

TCP 連接狀態(tài)與 TIME_WAIT。TCP 關(guān)閉連接時(shí),主動(dòng)關(guān)閉方會(huì)進(jìn)入 TIME_WAIT 狀態(tài),持續(xù)tcp_fin_timeout(默認(rèn) 60 秒)。在高并發(fā)短連接場(chǎng)景下,TIME_WAIT 連接會(huì)堆積,占用端口號(hào)(ip_local_port_range范圍有限)和內(nèi)存。如果端口號(hào)耗盡,新連接無法建立。tcp_tw_reuse允許 TIME_WAIT 狀態(tài)的端口被新連接復(fù)用,是解決這個(gè)問題的常用手段。

網(wǎng)絡(luò)關(guān)鍵指標(biāo)

# 查看網(wǎng)絡(luò)接口流量
cat /proc/net/dev
# Interface: bytes received, packets received, err/drop, bytes transmitted, packets transmitted
# 重點(diǎn)看 err(錯(cuò)誤數(shù))和 drop(丟棄數(shù)),不為 0 說明有硬件或驅(qū)動(dòng)問題

# 更友好的方式
watch -n 1'cat /proc/net/dev'

# 用 ip 或 ifstat 查看流量
ip -s link show
ifstat -a 1 5

# 查看 TCP 連接狀態(tài)統(tǒng)計(jì)
ss -s
# 輸出:
# Total: 156 (kernel 180)
# TCP:  1234 (estab 1000, closed 12, orphan 5, timewait 8)
# 關(guān)注 estab(已建立連接數(shù))和 timewait(TIME_WAIT 連接數(shù))

# 查看詳細(xì)的 TCP 指標(biāo)
cat /proc/net/snmp
cat /proc/net/netstat | ip_frag

# 網(wǎng)絡(luò)丟包和錯(cuò)誤統(tǒng)計(jì)(關(guān)鍵)
netstat -s | grep -i"retransmit"-A 2 -B 2
# RetransSegs - 重傳的段數(shù)
# 如果持續(xù)增長,說明網(wǎng)絡(luò)質(zhì)量不好或?qū)Χ藷o法跟上發(fā)送速度

netstat -s | grep -i"drop"-A 2 -B 2
# 丟包統(tǒng)計(jì)

# 查看半連接隊(duì)列(未完成三次握手)和全連接隊(duì)列(已完成三次握手等待 accept)
ss -lntp
# ListenDeq 字段:全連接隊(duì)列長度,如果等于系統(tǒng)上限(通常 128),說明隊(duì)列滿了
# 隊(duì)列滿會(huì)導(dǎo)致新連接被拒絕(connection refused)

網(wǎng)絡(luò)排查命令清單

# 基礎(chǔ)查看
ss -tuln          # 查看監(jiān)聽端口(l=listening, n=numeric, t=tcp, u=udp)
ss -anp | grep     # 查看某進(jìn)程的所有連接
ss -anp | grep :80     # 查看所有 80 端口的連接

# 查看連接狀態(tài)分布
ss -an | awk'/^tcp/{print $1}'| sort | uniq -c | sort -rn
# 或
netstat -an | awk'/^tcp/{print $6}'| sort | uniq -c | sort -rn

# 查看流量最大的連接
cat /proc/net/tcp     # 十六進(jìn)制地址轉(zhuǎn)換,用腳本解析
# 或使用 iftop(類似 top 的界面)
iftop -i eth0       # 實(shí)時(shí)顯示流量最大的連接
nethogs          # 按進(jìn)程顯示網(wǎng)絡(luò)流量

# 測(cè)試網(wǎng)絡(luò)延遲
ping -c 10 <目標(biāo)IP>    # 丟包率和 RTT
mtr <目標(biāo)IP>        # traceroute + ping,持續(xù)顯示每一跳的延遲
tracepath <目標(biāo)IP>     # traceroute 替代工具

# 測(cè)試端口連通性
nc -zv <目標(biāo)IP> <端口> 3
# -z: 只掃描端口不發(fā)送數(shù)據(jù),-v: 詳細(xì)輸出
# 連接成功說明網(wǎng)絡(luò)通且端口開放,連接拒絕說明端口有服務(wù)但拒絕連接(可能是因?yàn)殛?duì)列滿或防火墻)

# 查看網(wǎng)卡 Ring Buffer 和丟包
ethtool -S eth0       # 查看網(wǎng)卡的詳細(xì)統(tǒng)計(jì)
# 關(guān)注 rx_dropped, tx_dropped, rx_errors 等
# 如果 rx_dropped 很高,可能是 Ring Buffer 太小

# 查看網(wǎng)卡 Offload 狀態(tài)
ethtool -k eth0      # 查看網(wǎng)卡 Offload 功能(checksum offload, TSO 等)
ethtool -K eth0 tso off  # 關(guān)閉 TSO(可能解決某些場(chǎng)景下的性能問題)

# 網(wǎng)絡(luò)帶寬壓測(cè)(測(cè)試網(wǎng)絡(luò)設(shè)備本身的極限)
iperf3 -s         # 服務(wù)端
iperf3 -c <服務(wù)端IP> -P 10 # 客戶端,-P 10 表示 10 個(gè)并發(fā)連接

網(wǎng)絡(luò)瓶頸的判斷邏輯

帶寬耗盡:某個(gè)網(wǎng)卡的流量(ip -s link show)接近其帶寬上限(百兆 100Mbps,千兆 1Gbps,萬兆 10Gbps),說明帶寬不足。高帶寬場(chǎng)景要考慮網(wǎng)卡升級(jí)或做流量分片。

連接數(shù)異常:ss -s顯示大量timewait或orphan,可能是短連接場(chǎng)景沒有正確復(fù)用連接。大量orphan(非 orphaned 狀態(tài)的 socket,即未被任何進(jìn)程持有的連接)可能是連接泄漏。

丟包和重傳:netstat -s | grep Retransmit持續(xù)增長,說明網(wǎng)絡(luò)質(zhì)量不好或?qū)Χ颂幚聿患皶r(shí)。如果是從庫復(fù)制延遲,查網(wǎng)絡(luò)質(zhì)量和主從機(jī)器之間的延遲。

端口號(hào)耗盡:ip_local_port_range默認(rèn)是 32768~60999,大約 28000 個(gè)端口。短連接場(chǎng)景下,如果并發(fā)連接創(chuàng)建速度很快,端口號(hào)會(huì)在幾秒內(nèi)耗盡。癥狀是nc或應(yīng)用程序報(bào)"Cannot assign requested address"。解決:tcp_tw_reuse = 1+ip_local_port_range調(diào)大。

軟中斷不均衡:多隊(duì)列網(wǎng)卡(RSS,Receive Side Scaling)可以把不同連接的中斷分配到不同 CPU 核心。如果只有少數(shù)幾個(gè)核心在處理軟中斷(si高),可能需要綁定 IRQ 到不同核心:

# 查看網(wǎng)卡 IRQ 親和性配置
cat /proc/irq/73/smp_affinity
# 十六進(jìn)制掩碼,1 表示 CPU0,3 表示 CPU0+1

# 查看當(dāng)前每個(gè) IRQ 對(duì)應(yīng)的 CPU
cat /proc/interrupts | grep eth0

# 使用 irqbalance 服務(wù)自動(dòng)均衡(生產(chǎn)服務(wù)器建議開啟)
systemctlenableirqbalance
systemctl start irqbalance

場(chǎng)景案例:Web 服務(wù)大量 connection refused

現(xiàn)象:用戶反饋間歇性出現(xiàn) connection refused 錯(cuò)誤,但 ping 服務(wù)器是通的。

# 1. 測(cè)試端口連通性
nc -zv 127.0.0.1 8080
# Ncat: Connection refused.

# 2. 確認(rèn)端口是否在監(jiān)聽
ss -tlnp | grep 8080
# 沒有任何輸出,說明端口沒有進(jìn)程在監(jiān)聽

# 3. 查看進(jìn)程是否還在運(yùn)行
ps aux | grep java | grep -v grep
# 沒有輸出,說明 Java 進(jìn)程可能已經(jīng)崩潰

# 4. 檢查 dmesg 和系統(tǒng)日志
dmesg | tail -n 100 | grep -i java
# [12345.678901] java[12345]: segfault at 7f... ip 00007f... sp 00007f... error 4 in libc-2.17.so

# 5. 查看 JVM crash 日志
ls -lht /var/log/*crash* /var/log/*hs_err* 2>/dev/null
cat /var/log/hs_err_pid12345.log | tail -n 50

# 結(jié)論:Java 進(jìn)程因?yàn)?JVM bug(Segmentation Fault)崩潰了
# 不是網(wǎng)絡(luò)問題,是進(jìn)程存活性的問題

這個(gè)案例說明:connection refused 不一定是網(wǎng)絡(luò)問題,也可能是服務(wù)進(jìn)程本身就沒在運(yùn)行。排查的順序應(yīng)該是先確認(rèn)服務(wù)是否存活,再排查網(wǎng)絡(luò)連通性。

四類資源瓶頸的交叉驗(yàn)證

實(shí)際生產(chǎn)環(huán)境中,四類資源問題往往交織在一起。CPU 高可能是 IO 等待導(dǎo)致的(間接);內(nèi)存不足會(huì)觸發(fā) swap,導(dǎo)致 IO 飆升;IO 瓶頸會(huì)讓進(jìn)程進(jìn)入 D 狀態(tài),推高 load;網(wǎng)絡(luò)問題會(huì)導(dǎo)致連接堆積,影響 CPU 和內(nèi)存。交叉驗(yàn)證是避免誤判的關(guān)鍵。

常見交叉場(chǎng)景

場(chǎng)景一:CPU us 很低但 load 很高。說明進(jìn)程不在 CPU 上運(yùn)行,在等 IO(磁盤或網(wǎng)絡(luò))。查iostat,看磁盤是否擁塞;查vmstat的b列,看有多少進(jìn)程處于不可中斷睡眠。

場(chǎng)景二:free 內(nèi)存很少但不觸發(fā) swap。這是正常的,Linux 大量使用 Page Cache 加速 IO。如果available足夠且業(yè)務(wù)正常,不用管 free 少。

場(chǎng)景三:iostat 顯示 IO 正常但應(yīng)用響應(yīng)慢。可能是數(shù)據(jù)庫慢查詢(CPU 計(jì)算瓶頸)、網(wǎng)絡(luò)延遲、對(duì)端服務(wù)響應(yīng)慢等。IO 正常不代表整個(gè) IO 路徑?jīng)]有問題——可能是應(yīng)用層的問題,比如 SQL 沒有索引導(dǎo)致全表掃描,消耗的是 CPU 而不是 IO。

場(chǎng)景四:CPU sys 高 + 網(wǎng)絡(luò)流量大。通常是軟中斷處理壓力太大。檢查si列是否異常高,可以用mpstat -I SUM查看每個(gè) CPU 的中斷處理負(fù)載。如果只有少數(shù)核心在處理軟中斷,考慮開啟 irqbalance 或手動(dòng)調(diào)整 IRQ 親和性。

性能問題排查決策樹

服務(wù)器慢/卡
 │
 ├─ vmstat 1 3
 │   │
 │   ├─ r > CPU核心數(shù) * 2 且 us 高 ──────→ CPU 計(jì)算瓶頸 ──→ ps 找進(jìn)程 ──→ top -Hp 找線程 ──→ jstack/strace
 │   │
 │   ├─ b > 0 ──────────────────────────→ IO 阻塞 ──→ iostat -x 1 ──→ iotop 找進(jìn)程 ──→ 評(píng)估是讀還是寫
 │   │
 │   ├─ si/so > 0 持續(xù) ─────────────────→ 內(nèi)存不足 ──→ free -h ──→ 找吃內(nèi)存進(jìn)程 ──→ 調(diào)參或加內(nèi)存
 │   │
 │   └─ cs 很高 + sy 高 ────────────────→ 上下文切換過多 ──→ ss/ss -s 查連接 ──→ 優(yōu)化連接復(fù)用
 │
 ├─ top -b -n 1
 │   │
 │   ├─ us 高 ───────────────────────────→ 應(yīng)用層問題(代碼死循環(huán)、算法差)
 │   ├─ sy 高 ───────────────────────────→ 系統(tǒng)調(diào)用過多(頻繁讀寫文件、網(wǎng)絡(luò)通信)
 │   ├─ si 高 ───────────────────────────→ 軟中斷壓力(網(wǎng)絡(luò)流量、頻繁定時(shí)器)
 │   └─ wa 高 ───────────────────────────→ 磁盤/網(wǎng)絡(luò) IO 等待
 │
 └─ iostat -xz 1 3
    │
    ├─ util > 80% + await > 閾值 ────────→ 磁盤 IO 瓶頸
    ├─ avgqu-sz > 2 持續(xù) ─────────────────→ IO 隊(duì)列積壓
    └─ w/s 遠(yuǎn)大于 r/s ───────────────────→ 寫入為主(可能是日志、數(shù)據(jù)庫刷盤)

系統(tǒng)參數(shù)調(diào)優(yōu)匯總

根據(jù)前面四個(gè)維度的排查結(jié)論,對(duì)常見場(chǎng)景的調(diào)優(yōu)參數(shù)匯總?cè)缦拢?/p>

CPU 調(diào)優(yōu)

# 綁定進(jìn)程到特定 CPU 核心(減少調(diào)度開銷,適合 CPU 密集型固定任務(wù))
taskset -c 0-7      # 綁定到 0~7 核

# 調(diào)整進(jìn)程優(yōu)先級(jí)(適合有明確優(yōu)先級(jí)的多服務(wù)場(chǎng)景)
renice +10        # 降低某進(jìn)程的調(diào)度優(yōu)先級(jí)
# 或者啟動(dòng)時(shí)用 nice 命令
nice -n 10 /path/to/program

# 關(guān)閉透明大頁(transparent hugepage,某些數(shù)據(jù)庫場(chǎng)景下會(huì)有性能問題)
echonever > /sys/kernel/mm/transparent_hugepage/enabled
echonever > /sys/kernel/mm/transparent_hugepage/defrag
# 永久關(guān)閉:編輯 /etc/rc.local 或使用 systemd 服務(wù)

內(nèi)存調(diào)優(yōu)

# 調(diào)整 swappiness(建議值:數(shù)據(jù)庫服務(wù)器 10~30,其他服務(wù)器 30~60)
echo10 > /proc/sys/vm/swappiness
echo"vm.swappiness=10">> /etc/sysctl.conf

# 調(diào)整臟頁回寫策略(減少頻繁小數(shù)據(jù)量寫盤)
echo80 > /proc/sys/vm/dirty_ratio     # 觸發(fā)強(qiáng)制回寫之前,臟頁占可用內(nèi)存的比例
echo20 > /proc/sys/vm/dirty_background_ratio# 觸發(fā)后臺(tái)回寫之前,臟頁占可用內(nèi)存的比例

# 調(diào)整文件描述符限制(高并發(fā)服務(wù)必改)
echo"root soft nofile 655350">> /etc/security/limits.conf
echo"root hard nofile 655350">> /etc/security/limits.conf
ulimit-n 655350

# 調(diào)整 mmap 限制(某些 Java 應(yīng)用需要)
echo655350 > /proc/sys/vm/max_map_count

IO 調(diào)優(yōu)

# 調(diào)整 IO 調(diào)度器(SSD 用 deadline 或 noop,數(shù)據(jù)庫服務(wù)器用 deadline)
# 查看當(dāng)前調(diào)度器
cat /sys/block/sda/queue/scheduler
# 臨時(shí)修改
echodeadline > /sys/block/sda/queue/scheduler
# 永久修改:/etc/default/grub 的 GRUB_CMDLINE_LINUX 添加 elevator=deadline

# 調(diào)整請(qǐng)求隊(duì)列深度(高 IOPS 場(chǎng)景)
echo2048 > /sys/block/sda/queue/nr_requests
# 默認(rèn) 128,太小會(huì)導(dǎo)致高 IO 場(chǎng)景下請(qǐng)求堆積

# 調(diào)整預(yù)讀大?。樞蜃x寫多可增大,隨機(jī)讀寫多保持默認(rèn)或減小)
blockdev --setra 8192 /dev/sda # 設(shè)置預(yù)讀扇區(qū)數(shù)(8192 * 512 = 4MB)

# 開啟 IO 優(yōu)先級(jí)(適合多業(yè)務(wù)共用磁盤的場(chǎng)景)
ionice -c 2 -n 0 -p  # 實(shí)時(shí)調(diào)度(最高優(yōu)先級(jí))
ionice -c 3 -p     # 空閑調(diào)度(后臺(tái)任務(wù)用,不影響其他 IO)

網(wǎng)絡(luò)調(diào)優(yōu)

# /etc/sysctl.conf 中添加并執(zhí)行 sysctl -p

# 連接隊(duì)列和緩沖
net.core.somaxconn = 655350
net.core.netdev_max_backlog = 655350
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.core.rmem_default = 262144
net.core.wmem_default = 262144

# TCP 連接優(yōu)化
net.ipv4.tcp_max_syn_backlog = 655350
net.ipv4.tcp_fin_timeout = 15
net.ipv4.tcp_keepalive_time = 300
net.ipv4.tcp_keepalive_probes = 3
net.ipv4.tcp_keepalive_intvl = 15
net.ipv4.tcp_tw_reuse = 1    # TIME_WAIT 端口復(fù)用(高并發(fā)短連接必開)
net.ipv4.tcp_tw_recycle = 1    # 快速回收 TIME_WAIT(NAT 環(huán)境下慎用,可能導(dǎo)致連接異常)
net.ipv4.tcp_slow_start_after_idle = 0 # 關(guān)閉 idle 后的擁塞窗口收縮

# 本地端口范圍
net.ipv4.ip_local_port_range = 1024 65535

# TCP 擁塞控制(高帶寬高延遲網(wǎng)絡(luò)選用)
net.ipv4.tcp_congestion_control = bbr
# 開啟 BBR 需要內(nèi)核 4.9+,確認(rèn)系統(tǒng)支持:modprobe tcp_bbr

監(jiān)控與基線

指標(biāo)采集工具:

sar(sysstat 包):系統(tǒng)活動(dòng)報(bào)告工具,可以記錄歷史數(shù)據(jù)

node_exporter+Prometheus+Grafana:現(xiàn)代監(jiān)控體系

netdata:輕量級(jí)實(shí)時(shí)監(jiān)控,安裝簡單

# 安裝 sar 并啟用歷史數(shù)據(jù)采集
yum install -y sysstat
systemctlenablesysstat
systemctl start sysstat

# sar 歷史數(shù)據(jù)位置:/var/log/sa/
# 查看 CPU 歷史(每 10 分鐘一條)
sar -u -f /var/log/sa/sa$(date +%d)
# 查看內(nèi)存歷史
sar -r -f /var/log/sa/sa$(date +%d)
# 查看 IO 歷史
sar -b -f /var/log/sa/sa$(date +%d)
# 查看網(wǎng)絡(luò)歷史
sar -n DEV -f /var/log/sa/sa$(date +%d)

告警閾值建議(生產(chǎn)環(huán)境應(yīng)結(jié)合業(yè)務(wù)基線調(diào)整):

指標(biāo) 警告閾值 嚴(yán)重閾值
CPU 使用率 > 80% 持續(xù) 5min > 95% 持續(xù) 2min
Load Average > CPU 核心數(shù) * 0.7 > CPU 核心數(shù) * 1.5
可用內(nèi)存 < 20% total < 10% total
Swap 使用 > 0 持續(xù) > total * 10%
磁盤使用率 > 85% > 95%
磁盤 await > 50ms (HDD) > 100ms
磁盤 util > 80% > 95%
網(wǎng)絡(luò)帶寬 > 70% 峰值 > 90%
TCP TIME_WAIT > 10000 > 30000
TCP 重傳率 > 0.1% > 1%

總結(jié)

服務(wù)器四類資源(CPU、內(nèi)存、磁盤 IO、網(wǎng)絡(luò))的問題排查,有一個(gè)共同的核心思路:先找到瓶頸在哪,再找制造瓶頸的進(jìn)程或代碼。vmstat、iostat、netstat、ss、top、free 這些工具是排查的起點(diǎn),熟練使用它們并理解每個(gè)指標(biāo)的真正含義,是形成判斷能力的基礎(chǔ)。

交叉驗(yàn)證是避免誤判的關(guān)鍵。CPU idle 低不一定是 CPU 的問題,也可能是 IO 等待導(dǎo)致的;內(nèi)存不足不一定是應(yīng)用泄漏,也可能是 Page Cache 的正?;厥昭舆t。拿到一組指標(biāo)后,先用決策樹排除明顯不相關(guān)的維度,再深入分析。

最后,監(jiān)控和基線比排查更重要。再好的排查能力也不如在問題影響業(yè)務(wù)之前就發(fā)現(xiàn)它。每個(gè)工程師都應(yīng)該為自己的生產(chǎn)服務(wù)器建立基線數(shù)據(jù)(正常狀態(tài)下的指標(biāo)),并配置合理的告警閾值。當(dāng)告警觸發(fā)時(shí)去排查,是主動(dòng)防御;當(dāng)業(yè)務(wù)投訴后再去排查,是被動(dòng)救火。兩者的工作量和影響范圍差距極大。

補(bǔ)充:常見性能問題的快速索引

為便于在緊急情況下快速查閱,以下整理了常見癥狀與對(duì)應(yīng)排查方向的映射關(guān)系:

服務(wù)器 load 高但 CPU idle 也高。這是最容易被誤判的場(chǎng)景。load 高說明有進(jìn)程在等待資源,但 CPU idle 高說明 CPU 本身并不繁忙,所以等待的不是 CPU 資源。常見原因:磁盤 IO 阻塞(大量進(jìn)程在等待磁盤)、網(wǎng)絡(luò) IO 阻塞(進(jìn)程在等待網(wǎng)絡(luò)響應(yīng))、進(jìn)程在等待鎖或同步點(diǎn)。排查命令:iostat -xz 1看磁盤、vmstat 1看 b 列。

服務(wù)器 load 高且 CPU sy 高。sy(內(nèi)核態(tài) CPU)高說明系統(tǒng)在花大量時(shí)間處理系統(tǒng)調(diào)用和上下文切換。常見原因:大量短時(shí)進(jìn)程頻繁創(chuàng)建和銷毀(如 PHP-FPM 頻繁啟停)、頻繁的文件操作(如日志寫入)、網(wǎng)絡(luò)連接頻繁建立和關(guān)閉(TIME_WAIT 堆積)。排查命令:vmstat 1看 cs 列、ss -s看連接狀態(tài)。

內(nèi)存使用率高但沒有觸發(fā) swap。這是正常的,Linux 會(huì)盡可能利用空閑內(nèi)存作為 Page Cache 來加速 IO。只要 available 足夠且沒有 OOM,說明內(nèi)存使用是健康的。但如果內(nèi)存使用率長期接近 100% 且 available 很小,說明內(nèi)存已經(jīng)緊張,隨時(shí)可能觸發(fā) swap 或 OOM。

磁盤寫入量大但 iostat 顯示 util 正常。說明磁盤本身處理能力沒問題,寫入量大可能只是正常業(yè)務(wù)流量。需要結(jié)合吞吐量(wkB/s)和 IOPS(w/s)來判斷是否接近磁盤極限。如果兩者都遠(yuǎn)低于磁盤標(biāo)稱值,說明是應(yīng)用層的寫入邏輯問題(如日志級(jí)別設(shè)置不當(dāng)、頻繁刷盤而沒有緩沖)。

應(yīng)用響應(yīng)慢但所有系統(tǒng)指標(biāo)都正常。這種情況最難排查,通常說明問題不在操作系統(tǒng)層面,而在應(yīng)用自身:SQL 查詢低效(缺少索引、全表掃描)、外部依賴響應(yīng)慢(下游服務(wù)延遲)、應(yīng)用自身死鎖或超時(shí)設(shè)置不當(dāng)。應(yīng)該查看應(yīng)用的日志、慢查詢?nèi)罩荆ㄈ?MySQL 的 slow query log)、以及應(yīng)用層的性能剖析工具。

網(wǎng)絡(luò)丟包但網(wǎng)卡流量未滿。丟包發(fā)生在協(xié)議棧層面而不是物理鏈路層面。常見原因:Ring Buffer 溢出(ethtool -S查看 rx_dropped)、TCP 重傳過多(netstat -s | grep Retransmit)、 Socket 緩沖區(qū)不足(ss -m查看rcv_space/snd_space)。對(duì)于高并發(fā)服務(wù),調(diào)大net.core.rmem_max/wmem_max是常見的優(yōu)化步驟。

服務(wù)器周期性變慢(每隔固定時(shí)間卡一次)。周期性是重要的線索。常見原因:定時(shí)任務(wù)(如 logrotate、備份腳本、統(tǒng)計(jì)腳本)在執(zhí)行時(shí)占用大量資源;Cron 調(diào)度的健康檢查腳本運(yùn)行時(shí)間過長;數(shù)據(jù)庫的自動(dòng)分析/優(yōu)化任務(wù)(如 MySQL 的 ANALYZE TABLE);定時(shí)推送或批量處理任務(wù)。排查方法:crontab -l查看所有定時(shí)任務(wù),配合iotop和pidstat在問題發(fā)生時(shí)間點(diǎn)采樣。

以上索引在實(shí)際排查時(shí)可以作為入口參考,但具體問題仍需要結(jié)合具體指標(biāo)和業(yè)務(wù)場(chǎng)景來判斷。性能問題的排查沒有萬能公式,只有扎實(shí)的原理理解和豐富的實(shí)戰(zhàn)經(jīng)驗(yàn)才能快速定位根因。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • cpu
    cpu
    +關(guān)注

    關(guān)注

    68

    文章

    11351

    瀏覽量

    226170
  • 服務(wù)器
    +關(guān)注

    關(guān)注

    14

    文章

    10399

    瀏覽量

    91801
  • 內(nèi)存
    +關(guān)注

    關(guān)注

    9

    文章

    3244

    瀏覽量

    76543

原文標(biāo)題:吃透服務(wù)器性能:CPU、內(nèi)存、磁盤、網(wǎng)絡(luò)問題深度解析

文章出處:【微信號(hào):magedu-Linux,微信公眾號(hào):馬哥Linux運(yùn)維】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    linux服務(wù)器和windows服務(wù)器

    ,這在滿足個(gè)性化需求和增強(qiáng)服務(wù)器安全 性上具有優(yōu)勢(shì)。 Linux服務(wù)器還具有出色的性能和穩(wěn)定性。相比之下,Windows服務(wù)器
    發(fā)表于 02-22 15:46

    linux服務(wù)器性能測(cè)試步驟

    linux服務(wù)器性能測(cè)試-服務(wù)器實(shí)時(shí)【磁盤】監(jiān)控
    發(fā)表于 06-02 06:54

    Linux環(huán)境并發(fā)服務(wù)器設(shè)計(jì)技術(shù)研究

    講述并發(fā)服務(wù)器設(shè)計(jì)的主要技術(shù),包括多進(jìn)程服務(wù)器、多線程服務(wù)器和I/ O 復(fù)用服務(wù)器,同時(shí)對(duì)以上服務(wù)器技術(shù)的
    發(fā)表于 04-24 10:02 ?16次下載

    教你linux搭建web服務(wù)器

    教你linux搭建web服務(wù)器和大家分享了一份配置文檔,希望對(duì)您用linux搭建web服務(wù)器有所啟發(fā)。
    發(fā)表于 12-28 14:18 ?9360次閱讀

    基于Linux系統(tǒng)的FTP服務(wù)器的實(shí)現(xiàn)

    為了在Linux系統(tǒng)下實(shí)現(xiàn)安全、高效的FTP服務(wù)器,選擇了具有小巧輕快、安全易用等優(yōu)點(diǎn)的服務(wù)器軟件vsftpd。通過對(duì)Linux平臺(tái)下FTP網(wǎng)絡(luò)服務(wù)
    發(fā)表于 07-24 15:36 ?39次下載

    Linux服務(wù)器性能測(cè)試及分析命令大全

    Linux服務(wù)器性能測(cè)試及分析命令大全
    發(fā)表于 09-05 15:42 ?12次下載
    <b class='flag-5'>Linux</b><b class='flag-5'>服務(wù)器</b><b class='flag-5'>性能</b>測(cè)試及分析命令大全

    提高Linux服務(wù)器性能的20個(gè)技巧

     Linux功能豐富、強(qiáng)大、靈活,你可以用它完成各種任務(wù),在這篇文章中,我們將討論一些提高Linux服務(wù)器性能的技巧。
    的頭像 發(fā)表于 03-11 10:14 ?1979次閱讀

    排查Linux服務(wù)器性能問題工具

    如果你的Linux服務(wù)器突然負(fù)載暴增,告警短信快發(fā)爆你的手機(jī),如何在最短時(shí)間內(nèi)找出Linux性能問題所在?來看Netflix性能工程團(tuán)隊(duì)的這
    的頭像 發(fā)表于 09-16 09:16 ?1702次閱讀

    如何在linux服務(wù)器中打開端口

    有時(shí)我們可能需要在Linux服務(wù)器中打開端口或在Linux服務(wù)器的防火墻中啟用端口來運(yùn)行特定的應(yīng)用程序。在本文中,小編將帶大家分析一下如何在linu
    的頭像 發(fā)表于 10-17 16:22 ?1.4w次閱讀

    如何使用Checkmk監(jiān)控Linux服務(wù)器?

    `Checkmk` 是用于監(jiān)控 Linux 服務(wù)器的最常用和用戶友好的應(yīng)用程序之一。它可以檢查與您的 Linux 服務(wù)器連接的服務(wù)器狀態(tài)、負(fù)
    的頭像 發(fā)表于 02-17 10:46 ?2691次閱讀
    如何使用Checkmk監(jiān)控<b class='flag-5'>Linux</b><b class='flag-5'>服務(wù)器</b>?

    Linux服務(wù)器常見的網(wǎng)絡(luò)故障排查方法

    日常工作中我們有時(shí)會(huì)遇到服務(wù)器網(wǎng)絡(luò)不通問題,導(dǎo)致服務(wù)器無法正常運(yùn)行。要想解決服務(wù)器網(wǎng)絡(luò)故障問題,通常要先進(jìn)行網(wǎng)絡(luò)故障排查,這里以Linux
    的頭像 發(fā)表于 04-14 15:47 ?4107次閱讀

    影響linux服務(wù)器性能的因素

    一般互聯(lián)網(wǎng)的項(xiàng)目都是部署在linux服務(wù)器上的,如果linux服務(wù)器出了問題,那么咱們平時(shí)學(xué)習(xí)的高并發(fā),穩(wěn)定性之類的是沒有任何意義的,所以對(duì)linu
    的頭像 發(fā)表于 10-09 15:29 ?1072次閱讀

    Linux服務(wù)器性能查看方法

    Linux服務(wù)器性能查看是系統(tǒng)管理員和開發(fā)人員在日常工作中經(jīng)常需要進(jìn)行的任務(wù),以確保系統(tǒng)穩(wěn)定運(yùn)行并優(yōu)化資源使用。以下將詳細(xì)介紹多種Linux服務(wù)器
    的頭像 發(fā)表于 09-02 11:15 ?2846次閱讀

    如何優(yōu)化Linux服務(wù)器性能

    優(yōu)化Linux服務(wù)器性能是一個(gè)綜合性的任務(wù),涉及硬件、軟件、配置、監(jiān)控等多個(gè)方面。以下是一個(gè)詳細(xì)的指南,旨在幫助系統(tǒng)管理員和運(yùn)維人員提升Linux
    的頭像 發(fā)表于 09-29 16:50 ?1569次閱讀

    Linux服務(wù)器CPU飆高的排查思路

    CPU 飆高是 Linux 服務(wù)器最常見的性能問題之一。典型表現(xiàn)為:監(jiān)控告警觸發(fā)(CPU 使用率超過 90%)、業(yè)務(wù)響應(yīng)變慢、用戶投訴接口超時(shí)、ssh 操作卡頓。很多運(yùn)維同學(xué)遇到 CPU 飆高的第一反應(yīng)是重啟
    的頭像 發(fā)表于 05-11 16:54 ?269次閱讀
    大邑县| 尖扎县| 成都市| 湘潭市| 长垣县| 鄂尔多斯市| 万载县| 新巴尔虎左旗| 永济市| 鹿邑县| 万源市| 陇川县| 高雄县| 息烽县| 镇原县| 聂拉木县| 芮城县| 白朗县| 长乐市| 新建县| 平谷区| 云龙县| 连江县| 江油市| 晋江市| 紫金县| 安丘市| 合川市| 鹤岗市| 古丈县| 石嘴山市| 宁晋县| 嘉祥县| 青海省| 高淳县| 抚宁县| 岳普湖县| 威远县| 莲花县| 五家渠市| 罗山县|