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

一次接口超時(shí)排查,花費(fèi)了我兩個(gè)星期。。

系統(tǒng) Linux
最近在查一個(gè)問(wèn)題,花費(fèi)了近兩個(gè)星期,我一定要總結(jié)一下,今天繼續(xù)。

 [[423985]]

最近在查一個(gè)問(wèn)題,花費(fèi)了近兩個(gè)星期,我一定要總結(jié)一下,今天繼續(xù)。

Jdk 的 native 方法當(dāng)然不是終點(diǎn),雖然發(fā)現(xiàn) Jdk、docker、操作系統(tǒng) Bug 的可能性極小,但再往底層查卻很可能發(fā)現(xiàn)一些常見的配置錯(cuò)誤。

為了便于復(fù)現(xiàn),我用 JMH 寫了一個(gè)簡(jiǎn)單的 demo,控制速度不斷地通過(guò) log4j2 寫入日志。將項(xiàng)目打包成 jar 包,就可以很方便地在各處運(yùn)行了。 

  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 內(nèi)外運(yùn)行了 jar 包卻發(fā)現(xiàn)都能很簡(jiǎn)單地復(fù)現(xiàn)日志停頓問(wèn)題。而 jdk 版本眾多,我準(zhǔn)備首先排查操作系統(tǒng)配置問(wèn)題。

系統(tǒng)調(diào)用

strace 命令很早就使用過(guò),不久前還用它分析過(guò) shell 腳本執(zhí)行慢的問(wèn)題( 解決問(wèn)題,別擴(kuò)展問(wèn)題),但我還是不太習(xí)慣把 Java 和它聯(lián)系起來(lái),幸好有部門的老司機(jī)指點(diǎn),于是就使用 strace 分析了一波 Java 應(yīng)用。

命令跟分析普通腳本一樣, strace -T -ttt -f -o strace.log java -jar log.jar, -T 選項(xiàng)可以將每一個(gè)系統(tǒng)調(diào)用的耗時(shí)打印到系統(tǒng)調(diào)用的結(jié)尾。當(dāng)然排查時(shí)使用 -p pid 附加到 tomcat 上也是可以的,雖然會(huì)有很多容易混淆的系統(tǒng)調(diào)用。

對(duì)比 jmh 壓測(cè)用例輸出的 log4j2.info() 方法耗時(shí),發(fā)現(xiàn)了下圖中的狀況。

一次 write 系統(tǒng)調(diào)用竟然消耗了 147ms,很明顯地,問(wèn)題出在 write 系統(tǒng)調(diào)用上。最新 Java 核心技術(shù)教程,都在這了,推薦看下。

文件系統(tǒng)

結(jié)構(gòu)

這時(shí)候就要好好回想一下操作系統(tǒng)的知識(shí)了。

在 linux 系統(tǒng)中,萬(wàn)物皆文件,而為了給不同的介質(zhì)提供一種抽象的接口,在應(yīng)用層和系統(tǒng)層之間,抽象了一個(gè)虛擬文件系統(tǒng)層(virtual file system, VFS)。上層的應(yīng)用程序通過(guò) 系統(tǒng)調(diào)用 system call 操作虛擬文件系統(tǒng),進(jìn)而反饋到下層的硬件層。

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

而 write 系統(tǒng)調(diào)用會(huì)將數(shù)據(jù)寫到內(nèi)存中的 page cache,將 page 標(biāo)記為 臟頁(yè)(dirty) 后返回。

linux 的 writeback 機(jī)制

對(duì)于將內(nèi)存緩沖區(qū)的內(nèi)容刷到磁盤上,則有兩種方式:

首先,應(yīng)用程序在調(diào)用 write 系統(tǒng)調(diào)用寫入數(shù)據(jù)時(shí),如果發(fā)現(xiàn) page cache 的使用量大于了設(shè)定的大小,便會(huì)主動(dòng)將內(nèi)存中的臟頁(yè)刷到硬盤上。在此期間,所有的 write 系統(tǒng)調(diào)用都會(huì)被阻塞。

系統(tǒng)當(dāng)然不會(huì)容忍不定時(shí)的 write 阻塞,linux 還會(huì)定時(shí)啟動(dòng) pdflush 線程,判斷內(nèi)存頁(yè)達(dá)到一定的比例或臟頁(yè)存活時(shí)間達(dá)到設(shè)定的時(shí)間,將這些臟頁(yè)刷回到磁盤上,以避免被動(dòng)刷緩沖區(qū),這種機(jī)制就是 linux 的 writeback 機(jī)制。

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

猜測(cè)

了解了以上基礎(chǔ)知識(shí),那么對(duì)于 write 系統(tǒng)調(diào)用為什么會(huì)被阻塞,提出了兩種可能:

  •  page cache 可用空間不足,導(dǎo)致觸發(fā)了主動(dòng)的 flush,此時(shí)會(huì)阻塞所有對(duì)此 device 的 write。
  •  寫入過(guò)程被其他事務(wù)阻塞。

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

另外,與 pdflush 相關(guān)的系統(tǒng)配置:系統(tǒng)會(huì)每 vm.dirty_writeback_centisecs (5s) 喚醒一次 pdflush 線程, 發(fā)現(xiàn)臟頁(yè)比例超過(guò) vm.dirty_background_ratio (10%) 或 臟頁(yè)存活時(shí)間超過(guò) vm.dirty_expire_centisecs(30s) 時(shí),會(huì)將臟頁(yè)刷回硬盤。

查看 /proc/meminfo 內(nèi) Dirty/Writeback 項(xiàng)的變化,并對(duì)比服務(wù)的文件寫入速度,結(jié)論是數(shù)據(jù)會(huì)被 pdflush 刷回到硬盤,不會(huì)觸發(fā)被動(dòng) flush 以阻塞 write 系統(tǒng)調(diào)用。

ext4 的 journal 特性

write 被阻塞的原因

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

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

journal

journal 是 文件系統(tǒng)保證數(shù)據(jù)一致性的一種手段,在寫入數(shù)據(jù)前,將即將進(jìn)行的各個(gè)操作步驟記錄下來(lái),一旦系統(tǒng)掉電,恢復(fù)時(shí)讀取這些日志繼續(xù)操作就可以了。但批量的 journal commit 是一個(gè)事務(wù),flush 時(shí)會(huì)阻塞 write 的提交。

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

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

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

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

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

猜測(cè)因?yàn)?journal 觸發(fā)了臟頁(yè)落盤,而臟頁(yè)落盤導(dǎo)致 write 被阻塞,所以解決 journal 問(wèn)題就可以解決接口超時(shí)問(wèn)題。

解決方案與壓測(cè)結(jié)果

以下是我總結(jié)的幾個(gè)接口超時(shí)問(wèn)題的解決方案:

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

當(dāng)然,對(duì)于這幾種方案,我也做了壓測(cè),以下是壓測(cè)的結(jié)果。

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

小結(jié)

接口超時(shí)問(wèn)題總算是告一段落,查了很久,不過(guò)解決它之后也非常有成就感。遺憾的是沒(méi)有在 linux 內(nèi)核代碼中找到證據(jù),160M 的代碼,分層也不熟悉,實(shí)在是無(wú)從查起,希望以后有機(jī)會(huì)能慢慢接觸吧。

程序員還是要懂些操作系統(tǒng)知識(shí)的,不僅幫我們?cè)趹?yīng)對(duì)這種詭異的問(wèn)題時(shí)不至于束手無(wú)策,也可以在做一些業(yè)務(wù) 。

 

責(zé)任編輯:龐桂玉 來(lái)源: Java技術(shù)棧
相關(guān)推薦

2022-09-14 15:40:03

接口解決

2019-06-25 10:46:04

Flutter開發(fā)APP

2024-03-11 08:35:25

Python工程幻燈片

2025-03-17 10:01:07

2023-04-06 07:53:56

Redis連接問(wèn)題K8s

2017-12-19 14:00:16

數(shù)據(jù)庫(kù)MySQL死鎖排查

2019-03-15 16:20:45

MySQL死鎖排查命令

2021-05-13 08:51:20

GC問(wèn)題排查

2025-02-24 12:00:00

開發(fā)SpringBootJava

2021-03-29 12:35:04

Kubernetes環(huán)境TCP

2022-11-03 16:10:29

groovyfullGC

2023-01-04 18:32:31

線上服務(wù)代碼

2019-01-21 11:17:13

CPU優(yōu)化定位

2020-08-24 07:34:39

網(wǎng)絡(luò)超時(shí)請(qǐng)求

2018-07-20 08:44:21

Redis內(nèi)存排查

2021-11-23 21:21:07

線上排查服務(wù)

2018-01-19 11:12:11

HTTP問(wèn)題排查

2020-11-02 09:48:35

C++泄漏代碼

2022-10-10 09:10:07

命令磁盤排查

2021-04-13 08:54:28

dubbo線程池事故排查
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 国产精品久久视频 | 91久久久久久久久久久久久 | 91麻豆精品国产91久久久久久 | 欧美一级免费黄色片 | 欧美在线视频网站 | 日韩一区二区三区在线视频 | 91高清免费| 在线区| 国产在线永久免费 | 色眯眯视频在线观看 | 人人艹人人爽 | 激情免费视频 | 天天操天天拍 | 亚洲精品一区二区三区 | 午夜精品一区二区三区在线观看 | 亚洲成av人影片在线观看 | 久久成人综合 | 欧美四虎| 国产精品久久久久久久久久久久午夜片 | 人人干97 | 亚洲成人高清 | 97精品久久 | 婷婷综合久久 | 激情一区二区三区 | 日韩成人在线观看 | 天天爽网站 | 国产在线中文字幕 | 色精品视频 | 伊人网伊人 | 国产精产国品一二三产区视频 | 国产精品久久久久久 | 欧美亚洲视频 | 国产精品国产 | 国产成人福利在线观看 | 免费精品一区 | 91网站视频在线观看 | 国产在线观看网站 | 欧美中文字幕在线观看 | 日韩喷潮 | 欧美日韩一区在线 | 久久久久久久久毛片 |