同等配置下,虛機中的java 服務的啓動速度,要比容器快不少(將近兩倍)java
在同是1c1g的虛機和容器中,虛機啓動時間大概在1min20s,容器啓動時間大概在2min40s。node
最開始懷疑是網絡問題,由於業務依賴外部數據庫,在容器和虛機中ping、telnet外部數據庫,能通並且延遲差很少。linux
諮詢熟悉java的小夥伴,說 spingboot可能有潛在的外部網絡請求延遲(如請求Spring官網等),請求可能屢次失敗超時,不影響服務啓動,但會影響啓動時間。經過在虛機和容器中抓包,抓到了一個外部域名,可是虛機容器中均可以正常聯通。包括修改域名服務器,都沒有效果數據庫
排查問題陷入僵局後,諮詢小夥伴的建議,濤哥提出是否是由於硬件差別致使的?這是個新的思路,以前只關注了軟件層面的。服務器
google了下,確實有人遇到了由於cpu頻率的差別,致使虛機和容器中業務性能的差別。查看了容器和虛機所在主機的cpu頻率後,進一步證明了濤哥的猜測,cpu頻率確實有將近一倍的差別。根據文章中提供的解決辦法,經過修改cpu的工做模式,從
powersave到performance,來提升cpu的工做頻率。命令以下:網絡
# 查看cpu頻率 # lscpu Architecture: x86_64 CPU op-mode(s): 32-bit, 64-bit Byte Order: Little Endian CPU(s): 48 On-line CPU(s) list: 0-47 Thread(s) per core: 2 Core(s) per socket: 12 Socket(s): 2 NUMA node(s): 2 Vendor ID: GenuineIntel CPU family: 6 Model: 79 Model name: Intel(R) Xeon(R) CPU E5-2650 v4 @ 2.20GHz Stepping: 1 CPU MHz: 2494.133 CPU max MHz: 2900.0000 CPU min MHz: 1200.0000 BogoMIPS: 4389.67 Virtualization: VT-x L1d cache: 32K L1i cache: 32K L2 cache: 256K ··· # 查看cpu工做模式 # cat /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor powersave powersave ... # 修改cpu工做模式 # cpupower -c all frequency-set -g performance # 查看每一個cpu的頻率 # grep -i mhz /proc/cpuinfo cpu MHz : 1870.495 cpu MHz : 2348.156 cpu MHz : 2160.900 cpu MHz : 1918.896 ···
在修改完cpu工做模式後,cpu MHz確實有很大的提升,可是實測容器中業務啓動時間並無預期的和虛機中的速度同樣,只有一點優化。看來cpu MHz不是決定的影響因素。 jvm
後來詳細查了一下,cpu MHz是個不斷浮動的素質,cpu性能要看CPU max MHz和工做模式。兩臺宿主機的cpu型號是一致的,改動cpu工做模式影響有限socket
在以前容器化java業務的時候就遇到了OOMKilled,以及Runtime.getRuntime().availableProcessors()獲取的cpu核數問題。當時經過引入了lxcfs,以及替換jvm libnumcpus.so文件,經過環境變量注入cpu核數來解決這個問題。性能
在懷疑是隔離引發的問題後,對比了虛機和容器中java進程的線程數,發現確實有比較大的差別。命令以下:優化
# 虛機中 ··· [root@data-message-b69c847c7-sjlrx /]# cat /proc/136/status |grep Threads Threads: 42 [root@data-message-b69c847c7-sjlrx /]# cat /proc/136/status |grep Threads Threads: 42 [root@data-message-b69c847c7-sjlrx /]# cat /proc/136/status |grep Threads Threads: 42 [root@data-message-b69c847c7-sjlrx /]# cat /proc/136/status |grep Threads Threads: 42 [root@data-message-b69c847c7-sjlrx /]# cat /proc/136/status |grep Threads Threads: 42 [root@data-message-b69c847c7-sjlrx /]# cat /proc/136/status |grep Threads Threads: 42 ··· # 容器中 ··· [root@data-message-79bb65797d-ffsfb /]# cat /proc/42/status |grep Threads Threads: 74 [root@data-message-79bb65797d-ffsfb /]# cat /proc/42/status |grep Threads Threads: 74 [root@data-message-79bb65797d-ffsfb /]# cat /proc/42/status |grep Threads Threads: 76 [root@data-message-79bb65797d-ffsfb /]# cat /proc/42/status |grep Threads Threads: 76 [root@data-message-79bb65797d-ffsfb /]# cat /proc/42/status |grep Threads Threads: 76 ···
使用包含了cpu-online /sys/devices/system/cpu/online
的lxcfs(咱們以前引入的lxcfs還未支持cpu-online)
在引入新版lxcfs cpu-online後,線程數降低明顯,啓動速度有明顯的改善,達到和虛機同等水平。
Virtualize /sys/devices/system/cpu/online
LXCFS now also partially virtualizes sysfs. The first file to virtualize is /sys/devices/system/cpu/online per container.
容器java進程啓動慢的最終緣由,仍是容器的隔離性不夠,致使jvm啓動過多的線程,線程頻繁切換帶來的性能降低。目前使用包含cpu-online的lxcfs能解決這個問題。