成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

一次接口超時排查,花費了我兩個星期。。

系統 Linux
最近在查一個問題,花費了近兩個星期,我一定要總結一下,今天繼續。

 [[423985]]

最近在查一個問題,花費了近兩個星期,我一定要總結一下,今天繼續。

Jdk 的 native 方法當然不是終點,雖然發現 Jdk、docker、操作系統 Bug 的可能性極小,但再往底層查卻很可能發現一些常見的配置錯誤。

為了便于復現,我用 JMH 寫了一個簡單的 demo,控制速度不斷地通過 log4j2 寫入日志。將項目打包成 jar 包,就可以很方便地在各處運行了。 

  1. @BenchmarkMode(Mode.AverageTime)  
  2. @OutputTimeUnit(TimeUnit.MICROSECONDS)  
  3. @State(Scope.Benchmark)  
  4. @Threads(5)  
  5. public class LoggerRunner {  
  6.     public static void main(String[] args) throws RunnerException {  
  7.         Options options = new OptionsBuilder()  
  8.                 .include(LoggerRunner.class.getName())  
  9.                 .warmupIterations(2)  
  10.                 .forks(1)  
  11.                 .measurementIterations(1000)  
  12.                 .build();  
  13.         new Runner(options).run();  
  14.     }  

我比較懷疑是 docker 的原因。

但是在 docker 內外運行了 jar 包卻發現都能很簡單地復現日志停頓問題。而 jdk 版本眾多,我準備首先排查操作系統配置問題。

系統調用

strace 命令很早就使用過,不久前還用它分析過 shell 腳本執行慢的問題( 解決問題,別擴展問題),但我還是不太習慣把 Java 和它聯系起來,幸好有部門的老司機指點,于是就使用 strace 分析了一波 Java 應用。

命令跟分析普通腳本一樣, strace -T -ttt -f -o strace.log java -jar log.jar, -T 選項可以將每一個系統調用的耗時打印到系統調用的結尾。當然排查時使用 -p pid 附加到 tomcat 上也是可以的,雖然會有很多容易混淆的系統調用。

對比 jmh 壓測用例輸出的 log4j2.info() 方法耗時,發現了下圖中的狀況。

一次 write 系統調用竟然消耗了 147ms,很明顯地,問題出在 write 系統調用上。最新 Java 核心技術教程,都在這了,推薦看下。

文件系統

結構

這時候就要好好回想一下操作系統的知識了。

在 linux 系統中,萬物皆文件,而為了給不同的介質提供一種抽象的接口,在應用層和系統層之間,抽象了一個虛擬文件系統層(virtual file system, VFS)。上層的應用程序通過 系統調用 system call 操作虛擬文件系統,進而反饋到下層的硬件層。

由于硬盤等介質操作速度與內存不在同一個數量級上,為了平衡兩者之間的速度,linux 便把文件映射到內存中,將硬盤單位塊(block)對應到內存中的一個 頁(page)上。這樣,當需要操作文件時,直接操作內存就可以了。當緩沖區操作達到一定量或到達一定的時間后,再將變更統一刷到磁盤上。這樣便有效地減少了磁盤操作,應用也不必等待硬盤操作結束,響應速度得到了提升。

而 write 系統調用會將數據寫到內存中的 page cache,將 page 標記為 臟頁(dirty) 后返回。

linux 的 writeback 機制

對于將內存緩沖區的內容刷到磁盤上,則有兩種方式:

首先,應用程序在調用 write 系統調用寫入數據時,如果發現 page cache 的使用量大于了設定的大小,便會主動將內存中的臟頁刷到硬盤上。在此期間,所有的 write 系統調用都會被阻塞。

系統當然不會容忍不定時的 write 阻塞,linux 還會定時啟動 pdflush 線程,判斷內存頁達到一定的比例或臟頁存活時間達到設定的時間,將這些臟頁刷回到磁盤上,以避免被動刷緩沖區,這種機制就是 linux 的 writeback 機制。

另外,Linux 系列面試題和答案全部整理好了,微信搜索Java技術棧,在后臺發送:面試,可以在線閱讀。

猜測

了解了以上基礎知識,那么對于 write 系統調用為什么會被阻塞,提出了兩種可能:

  •  page cache 可用空間不足,導致觸發了主動的 flush,此時會阻塞所有對此 device 的 write。
  •  寫入過程被其他事務阻塞。

首先對于第一種可能:查看系統配置 dirty_ratio 的大小:20。此值是 page cache 占用系統可用內存(real mem + swap)的最大百分比, 我們的內存為 32G,沒有啟用 swap,則實際可用的 page cache 大小約為 6G。

另外,與 pdflush 相關的系統配置:系統會每 vm.dirty_writeback_centisecs (5s) 喚醒一次 pdflush 線程, 發現臟頁比例超過 vm.dirty_background_ratio (10%) 或 臟頁存活時間超過 vm.dirty_expire_centisecs(30s) 時,會將臟頁刷回硬盤。

查看 /proc/meminfo 內 Dirty/Writeback 項的變化,并對比服務的文件寫入速度,結論是數據會被 pdflush 刷回到硬盤,不會觸發被動 flush 以阻塞 write 系統調用。

ext4 的 journal 特性

write 被阻塞的原因

繼續搜索資料,在一篇文章(Why buffered writes are sometimes stalled )中看到 write 系統調用被阻塞有以下可能:

  •  要寫入的數據依賴讀取的結果時。但記錄日志不依賴讀文件;
  •  wirte page 時有別的線程在調用 fsync() 等主動 flush 臟頁的方法。但由于鎖的存在,log 在寫入時不會有其他的線程操作;
  •  格式為 ext3/4 的文件系統在記錄 journal log 時會阻塞 write。而我們的系統文件格式為 ext4。維基百科上的一個條目( https://en.wikipedia.org/wiki/Journaling_block_device ) 也描述了這種可能。

journal

journal 是 文件系統保證數據一致性的一種手段,在寫入數據前,將即將進行的各個操作步驟記錄下來,一旦系統掉電,恢復時讀取這些日志繼續操作就可以了。但批量的 journal commit 是一個事務,flush 時會阻塞 write 的提交。

我們可以使用 dumpe2fs /dev/disk | grep features 查看磁盤支持的特性,其中有 has_journal 代表文件系統支持 journal 特性。

ext4 格式的文件系統在掛載時可以選擇 (jouranling、ordered、writeback) 三種之一的 journal 記錄模式。

三種模式分別有以下特性:

  •  journal:在將數據寫入文件系統前,必須等待 metadata 和 journal 已經落盤了。
  •  ordered:不記錄數據的 journal,只記錄 metadata 的 journal 日志,且需要保證所有數據在其 metadata journal 被 commit 之前落盤。ext4 在不添加掛載參數時使用此模式。
  •  writeback: 數據可能在 metadata journal 被提交之后落盤,可能導致舊數據在系統掉電后恢復到磁盤中。

當然,我們也可以選擇直接禁用 journal,使用 tune2fs -O ^has_journal /dev/disk,只能操作未被掛載的磁盤。

猜測因為 journal 觸發了臟頁落盤,而臟頁落盤導致 write 被阻塞,所以解決 journal 問題就可以解決接口超時問題。

解決方案與壓測結果

以下是我總結的幾個接口超時問題的解決方案:

  1.  log4j2 日志模式改異步。但有可能會在系統重啟時丟失日志,另外在異步隊列 ringbuffer 被填滿未消費后,新日志會自動使用同步模式。
  2.  調整系統刷臟頁的配置,將檢查臟頁和臟頁過期時間設置得更短(1s 以內)。但理論上會略微提升系統負載(未明顯觀察到)。
  3.  掛載硬盤時使用 data=writeback 選項修改 journal 模式。但可能導致系統重啟后文件包含已刪除的內容。
  4.  禁用 ext4 的 journal 特性。但可能會導致系統文件的不一致。
  5.  把 ext4 的 journal 日志遷移到更快的磁盤上,如 ssd、閃存等。操作復雜,不易維護。
  6.  使用 xfs、fat 等 文件系統格式。特性不了解,影響不可知。

當然,對于這幾種方案,我也做了壓測,以下是壓測的結果。

文件系統特性 接口超時比例
ext4(同線上) 0.202%
xfs文件系統 0.06%
page過期時間和pdflush啟動時間都設置為 0.8s 0.017%
ext4 掛載時 journal 模式為 writeback 0%
禁用 ext4 的 journal 特性 0%
log4j2 使用異步日志 0%

小結

接口超時問題總算是告一段落,查了很久,不過解決它之后也非常有成就感。遺憾的是沒有在 linux 內核代碼中找到證據,160M 的代碼,分層也不熟悉,實在是無從查起,希望以后有機會能慢慢接觸吧。

程序員還是要懂些操作系統知識的,不僅幫我們在應對這種詭異的問題時不至于束手無策,也可以在做一些業務 。

 

責任編輯:龐桂玉 來源: Java技術棧
相關推薦

2022-09-14 15:40:03

接口解決

2019-06-25 10:46:04

Flutter開發APP

2024-03-11 08:35:25

Python工程幻燈片

2025-03-17 10:01:07

2023-04-06 07:53:56

Redis連接問題K8s

2025-06-30 07:15:00

Linuxfork()系統調用

2017-12-19 14:00:16

數據庫MySQL死鎖排查

2019-03-15 16:20:45

MySQL死鎖排查命令

2021-05-13 08:51:20

GC問題排查

2025-02-24 12:00:00

開發SpringBootJava

2021-03-29 12:35:04

Kubernetes環境TCP

2022-11-03 16:10:29

groovyfullGC

2023-01-04 18:32:31

線上服務代碼

2019-01-21 11:17:13

CPU優化定位

2020-08-24 07:34:39

網絡超時請求

2018-07-20 08:44:21

Redis內存排查

2021-11-23 21:21:07

線上排查服務

2020-11-02 09:48:35

C++泄漏代碼

2018-01-19 11:12:11

HTTP問題排查

2022-10-10 09:10:07

命令磁盤排查
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 日韩一区欧美一区 | 三极网站| 国产精品91视频 | 日韩一区二区三区在线观看视频 | 亚洲韩国精品 | 成人一区二区电影 | av一区二区三区四区 | 亚洲精品日韩综合观看成人91 | 欧美在线日韩 | 福利片在线观看 | 久久九九网站 | 国产一区二区在线91 | 激情毛片 | 欧美电影免费网站 | 亚洲一区二区三区在线播放 | 亚洲成人www | 黄色在线免费观看视频网站 | 亚洲一区二区视频在线播放 | 日韩1区 | 在线看av的网址 | 爱爱小视频 | 在线不卡视频 | 成人一区二区三区在线 | 久久久精品久 | 久久久久久91香蕉国产 | 成人一区二区三区在线观看 | 亚洲国产伊人 | 成人夜晚看av | 午夜天堂精品久久久久 | 国产免费一区二区 | 亚洲国产情侣 | 久久久久国产精品人 | 黄色一级大片在线免费看产 | 性一交一乱一伦视频免费观看 | 久久国产精品色av免费观看 | 国产精品一区二区久久 | 狠狠的干狠狠的操 | 精品久久久久久久久久久久 | 欧美视频三区 | 天天干 夜夜操 | 亚洲欧美一区二区三区国产精品 |