Linux

執行相同工作的伺服器的不同 linux 頁面記憶體行為

  • October 27, 2017

我有兩組具有 128G 記憶體的伺服器,它們的區別在於它們的配置時間,它們在執行完全相同的守護程序(elasticsearch)時表現非常不同。我使用 elasticsearch 進行全文搜尋,而不是日誌儲存,所以這基本上是一個讀取繁重的操作,寫入最少(小於 1MB/s)。這個守護程序 mmap 將大約 350GB 的完整數據集放入其虛擬記憶體中,然後訪問其中的某些部分以服務請求。這些伺服器沒有配置交換空間。

問題是一組伺服器表現良好,每秒發出約 50 個主要故障,並且平均需要 10MB/s 的磁碟 io 才能滿足該需求。性能不佳的伺服器每秒會看到 500 個主要故障,並且平均需要約 200MB/s 的磁碟 io 來滿足這一要求。磁碟 io 的增加導致 p95 響應延遲較差,並且偶爾會出現過載,因為它達到了 ~550MB/s 的磁碟限制。

它們都位於同一個負載均衡器後面,並且屬於同一個集群。我可以看到一台伺服器是否表現不佳,這可能是負載差異,但要與 16 台伺服器表現不佳和 20 台伺服器表現良好有如此明顯的區別,它們是在不同時間購買+配置的,核心/配置級別一定是導致問題的原因。

為了解決這個問題,我怎樣才能讓這些表現不佳的伺服器表現得像那些表現良好的伺服器?調試工作應該集中在哪裡?

下面是我收集的一些數據,用於查看系統在三種狀態中的每一種狀態下的sar和工具正在做什麼。page-types

軟體:-debian jessie-linux 4.9.25-elasticsearch 5.3.2-openjdk 1.8.0_141

首先來自表現良好的伺服器的一些頁面錯誤數據(來自sar -B):

07:55:01 PM  pgpgin/s pgpgout/s   fault/s  majflt/s  pgfree/s pgscank/s pgscand/s pgsteal/s    %vmeff
08:05:01 PM   3105.89    811.60   2084.40     48.16   3385.30      0.00      0.00    810.35      0.00
08:15:01 PM   4317.65    665.28    910.29     57.03   3160.14      0.00      0.00   1047.14      0.00
08:25:01 PM   3132.84    648.48    868.41     50.00   2899.14      0.00      0.00    801.27      0.00
08:35:01 PM   2940.02   1026.47   2031.69     45.26   3418.65      0.00      0.00    764.05      0.00
08:45:01 PM   2985.72   1011.27    744.34     45.78   2796.54      0.00      0.00    817.23      0.00
08:55:01 PM   2970.14    588.34    858.08     47.65   2852.33      0.00      0.00    749.17      0.00
09:05:01 PM   3489.23   2364.78   2121.48     47.13   3945.93      0.00      0.00   1145.02      0.00
09:15:01 PM   2695.48    594.57    858.56     44.57   2616.84      0.00      0.00    624.13      0.00

這是性能不佳的伺服器之一:

07:55:01 PM  pgpgin/s pgpgout/s   fault/s  majflt/s  pgfree/s pgscank/s pgscand/s pgsteal/s    %vmeff
08:05:01 PM 268547.64   1223.73   5266.73    503.12  71836.18      0.00      0.00  67170.50      0.00
08:15:01 PM 279865.31    944.04   3995.52    520.17  74231.90      0.00      0.00  70000.23      0.00
08:25:01 PM 265806.75    966.55   3747.43    499.45  70443.49      0.00      0.00  66407.62      0.00
08:35:01 PM 251820.93   1831.04   4689.62    475.43  67445.29      0.00      0.00  63056.35      0.00
08:45:01 PM 236055.04   1022.32   3498.37    449.37  62955.37      0.00      0.00  59042.16      0.00
08:55:01 PM 239478.40    971.98   3523.61    451.76  63856.04      0.00      0.00  59953.38      0.00
09:05:01 PM 232213.81   1058.04   4436.75    437.09  62194.61      0.00      0.00  58100.47      0.00
09:15:01 PM 216433.72    911.94   3192.28    413.23  57737.62      0.00      0.00  54126.78      0.00

我懷疑這是由於頁面回收的 LRU 部分性能不佳。如果我執行while true; do echo 1 > /proc/sys/vm/drop_caches; sleep 30; done,它會丟棄所有非映射頁面,磁碟 io 的初始峰值會出現,但大約 30 分鐘後它會穩定下來。我在所有伺服器上執行了大約 48 小時,以驗證它在每日峰值負載和低點下都會顯示相同的 IO 減少。它做了。Sar 現在報告以下內容:

12:55:01 PM  pgpgin/s pgpgout/s   fault/s  majflt/s  pgfree/s pgscank/s pgscand/s pgsteal/s    %vmeff
01:05:01 PM 121327.14   1482.09   2277.40    140.25  32781.26      0.00      0.00   1764.61      0.00
01:15:01 PM 109911.39   1334.51   1057.51    130.53  31095.68      0.00      0.00   1121.39      0.00
01:25:01 PM 126500.69   1652.51   1216.76    143.07  35830.38      0.00      0.00   2801.84      0.00
01:35:01 PM 132669.45   1857.62   2309.86    148.47  36735.79      0.00      0.00   3181.19      0.00
01:45:01 PM 126872.04   1451.94   1062.94    145.68  34678.26      0.00      0.00    992.60      0.00
01:55:01 PM 121002.21   1818.32   1142.16    139.40  34168.53      0.00      0.00   1640.18      0.00
02:05:01 PM 121824.18   1260.22   2319.56    142.80  33254.67      0.00      0.00   1738.25      0.00
02:15:02 PM 120768.12   1100.87   1143.36    140.20  34195.15      0.00      0.00   1702.83      0.00

主要頁面錯誤已減少到先前值的 1/3。從磁碟導入的頁面已減半。這將磁碟 IO 從 ~200MB/s 減少到 ~100MB/s,但表現良好的伺服器仍然顯著優於它們,只有 50 個主要故障/s,並且只需要執行 ~10MB/s 的磁碟 io。

為了了解 LRU 算法的工作原理,我使用了核心中的頁麵類型工具。這是一個表現良好的伺服器(來自page-types | awk '$3 > 1000 { print $0 }' | sort -nk3):

            flags      page-count       MB  symbolic-flags                     long-symbolic-flags
0x0000000000000828          257715     1006  ___U_l_____M______________________________ uptodate,lru,mmap
0x0000000000000080          259789     1014  _______S__________________________________ slab
0x000000000000006c          279344     1091  __RU_lA___________________________________ referenced,uptodate,lru,active
0x0000000000000268          305744     1194  ___U_lA__I________________________________ uptodate,lru,active,reclaim
0x0000000000100000          524288     2048  ____________________n_____________________ nopage
0x000000000000082c          632704     2471  __RU_l_____M______________________________ referenced,uptodate,lru,mmap
0x0000000000000000          763312     2981  __________________________________________
0x0000000000000068         2108618     8236  ___U_lA___________________________________ uptodate,lru,active
0x000000000000086c         6987343    27294  __RU_lA____M______________________________ referenced,uptodate,lru,active,mmap
0x0000000000005868         8589411    33552  ___U_lA____Ma_b___________________________ uptodate,lru,active,mmap,anonymous,swapbacked
0x0000000000000868        12513737    48881  ___U_lA____M______________________________ uptodate,lru,active,mmap
            total        34078720   133120

這是一個性能不佳的伺服器:

            flags      page-count       MB  symbolic-flags                     long-symbolic-flags
0x0000000000100000          262144     1024  ____________________n_____________________ nopage
0x0000000000000828          340276     1329  ___U_l_____M______________________________ uptodate,lru,mmap
0x000000000000086c          515691     2014  __RU_lA____M______________________________ referenced,uptodate,lru,active,mmap
0x0000000000000028          687263     2684  ___U_l____________________________________ uptodate,lru
0x0000000000000000          785662     3068  __________________________________________
0x0000000000000868         7946840    31042  ___U_lA____M______________________________ uptodate,lru,active,mmap
0x0000000000005868         8588629    33549  ___U_lA____Ma_b___________________________ uptodate,lru,active,mmap,anonymous,swapbacked
0x0000000000000068        14133541    55209  ___U_lA___________________________________ uptodate,lru,active
            total        33816576   132096

下面是循環 drop_caches 命令時的樣子:

            flags      page-count       MB  symbolic-flags                     long-symbolic-flags
0x0000000000100000          262144     1024  ____________________n_____________________ nopage
0x0000000000000400          394790     1542  __________B_______________________________ buddy
0x0000000000000000          761557     2974  __________________________________________
0x0000000000000868         1451890     5671  ___U_lA____M______________________________ uptodate,lru,active,mmap
0x000000000000082c         3123142    12199  __RU_l_____M______________________________ referenced,uptodate,lru,mmap
0x0000000000000828         5278755    20620  ___U_l_____M______________________________ uptodate,lru,mmap
0x0000000000005868         8622864    33683  ___U_lA____Ma_b___________________________ uptodate,lru,active,mmap,anonymous,swapbacked
0x000000000000086c        13630124    53242  __RU_lA____M______________________________ referenced,uptodate,lru,active,mmap
            total        33816576   132096

嘗試的事情:

  • 將 /proc/sys/vm/vfs_cache_pressure 增加到 150 到 10000 之間的各種值。這對 IO 或報告的數據沒有影響 page-types,這是有道理的,因為這可以平衡核心結構與使用者頁面,而我的問題是不同的使用者頁面
  • 增加 /proc/sys/vm/swappiness。沒想到這會做任何事情,它沒有,但檢查並沒有什麼壞處。
  • 禁用 mmap(而不是使用基於 epoll 的 java 的 nio)。這立即使伺服器的 IO 使用看起來就像在 IO 使用方面表現良好的一樣。這裡的缺點是系統 cpu % 與發生了多少 IO 相關,10MB/s 佔用約 1.5%,偶爾負載高達約 100MB/s 的磁碟 io 看到系統 cpu % 為 5% 到 10%。在 1.5 到 3 個 CPU 的 32 核伺服器上,完全用於處理 epoll。nio 的延遲也更差(與表現良好的 mmap’d 伺服器相比)。這是一個合理的解決方案,但它是一種逃避,不了解實際出了什麼問題。
  • perf該工具在堆棧跟踪、火焰圖和尋找核心行為的差異方面花費了無數小時。幾乎沒有獲得任何洞察力。
  • 檢查的磁碟預讀設置在伺服器之間是相同的。raid0 在性能不佳的伺服器上預設為 2048 塊,性能良好的伺服器 raid0 預設為 256 塊。將性能不佳的伺服器更新到 256blockdev --setra對 IO 行為沒有影響。
  • 啟動 jvmnumactl --interleave=all以確保問題與兩個 numa 節點之間的平衡無關。沒區別。
  • 用 驗證vmtouch,它基本上用於mincore(2)詢問核心是否記憶體了文件,99% 以上的緩衝記憶體正用於文件系統 elasticsearch 儲存它的數據。在上述所有 3 種情況下都是如此。
  • 經驗證fuser -m,elasticsearch 是唯一使用文件系統上的文件的程序,elasticsearch 將其數據儲存在其中。

盡快測試:

  • 下週我將重新配置其中一台行為不端的伺服器,但我並不樂觀這會產生多大影響。在此配置期間,我還將更新 RAID 陣列以將 LVM 放在其前面。不要期望與 LVM 有任何不同,但刪除變數似乎是值得的。

這最終成為一個過於激進的磁碟預讀。性能良好的伺服器具有 128 kB 的預讀。性能不佳的伺服器具有 2 mB 的預讀。無法查明預讀究竟為何不同,但最可能的原因是新機器在軟體 raid 前面有 LVM,而舊機器直接與軟體raid 對話。

雖然我的問題表明我最初確實檢查了預讀,注意到差異,並在其中一台伺服器上更新它,但 mmap 和預讀之間的互動並不是那麼直接。特別是當一個文件被 mmap’d 時,linux 核心會將預讀設置從磁碟複製到有關該 mmap’d 文件的結構中。更新預讀設置不會更新該結構。因此,更新的預讀在保持文件打開的守護程序重新啟動後才會生效。

減少預讀並在性能不佳的伺服器上重新啟動守護程序會立即使磁碟讀取與性能良好的伺服器保持一致,並立即減少我們的 IO 等待和尾部延遲。

引用自:https://serverfault.com/questions/868355