容器隔离 java_容器隔离性带来的问题--容器化Java应用比虚机启动速度慢

本文探讨了Java应用在容器环境中启动速度较虚拟机慢的问题,主要聚焦于CPU隔离和线程数量差异。通过检查CPU频率、工作模式,发现并非决定因素。最终发现容器内的Java进程创建了更多线程,导致性能下降。解决方案是使用包含`cpu-online`的LXCFS,有效减少线程数,提升启动速度。
摘要由CSDN通过智能技术生成

# 引发的问题

同等配置下,虚机中的java 服务的启动速度,要比容器快很多(将近两倍)

#### 实测数据

在同是1c1g的虚机和容器中,虚机启动时间大概在1min20s,容器启动时间大概在2min40s。

# 排查思路

## 怀疑网络

最开始怀疑是网络问题,因为业务依赖外部数据库,在容器和虚机中ping、telnet外部数据库,能通而且延迟差不多。

咨询熟悉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不是决定的影响因素。

后来详细查了一下,cpu MHz是个不断浮动的素质,cpu性能要看CPU max MHz和工作模式。两台宿主机的cpu型号是一致的,改动cpu工作模式影响有限

## 容器对java的隔离缺陷

在之前容器化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后,线程数下降明显,启动速度有明显的改善,达到和虚机同等水平。

## [LXCFS 3.1.2](Linux Containers - LXCFS - News) has been released

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能解决这个问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值