【Kubernetes】记录一次K8S容器内程序OOM排查过程:unable to create new native thread

项目背景

基于k8s的容器化kafka PaaS管理平台,业务团队申请kafka,通过一系列操作,封装crd,调用operator创建集群,当然还包括其他功能、topic管理、group管理、监控告警、集群扩容、分区管理等等。

后台会对每个集群启动定时任务,扫描kafka的元数据变化,主要是使用zk客户端Curator。

问题初现

在集群增长到一定数量后,有一天,突然再访问PaaS平台就报错了,报错信息竟然是OOM:unable to create new native thread

原因可能是:

  • 线程数过多,无法再申请新的线程

  • 线程数超过机器每个对进程的线程数的限制

问题排查

首先查看程序占用的线程数

由于种种原因,用了比较笨的方法:

jstack 1 | grep 'java.lang.Thread.State' | wc -l

得到的数量是2300+,而容器对每个pod的线程数限制为2000,这就是问题所在

通过观察之后,大部分线程都是以“Curator-”为前缀的,进一步过滤:

jstack 1 |grep  "Curator" |wc -l

得到的数量是1800+

所以可以定位到:这些线程,都是和zk客户端有关系。

问题定位

首先看是哪个地方创建的线程,根据一顿搜索,找到了创建线程池的代码,其中线程池核心数的取值是这样的:

Math.max(Runtime.getRuntime().availableProcessors(), 16)

平平无奇,毫无波澜,但是这就是罪魁祸首

我们项目的Dockerfile如下:

FROM java:8
WORKDIR /
ADD target/xadd-kafka-console.jar app.jar
RUN bash -c 'cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && touch /app.jar'
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-server","-Xms4096m","-Xmx4096m","-XX:NewSize=1500m","-XX:+UseConcMarkSweepGC","-XX:CMSInitiatingOccupancyFraction=70","-jar","/app.jar"]

没有指定具体的java版本,这么写,到容器内会拉取哪个版本呢?

root@xadd-consumer-bbb464c4-qp7q8:/# java -version
openjdk version "1.8.0_111"
OpenJDK Runtime Environment (build 1.8.0_111-8u111-b14-2~bpo8+1-b14)
OpenJDK 64-Bit Server VM (build 25.111-b14, mixed mode)
root@xadd-consumer-bbb464c4-qp7q8:/# 
root@xadd-consumer-bbb464c4-qp7q8:/# 

答案是较低版本的:1.8.0_111

低版本的jdk对容器环境支持并不友好,使用代码Runtime.getRuntime().availableProcessors()获取到的CPU数量是宿主机的真实核数,而不是pod所分配的核数,我们K8S node节点的CPU核数为100左右,所以导致线程池的核心线程数是100(这是一个很大的坑,并不容易发现)

这个问题解决了,还有一个问题:为什么线程数会一直不断上涨呢?

查看项目代码:
在这里插入图片描述在这里插入图片描述
通过查看项目代码发现,每个Curator客户端都需要一个线程池作为参数,也就是每次有新的集群创建,都会创建一个新的线程池,这个无法避免,但是可以将核心线程数改小,保证线程数的增长在可控范围内

问题解决

  • 替换基础为openjdk:8u332-jdk

  • 修改核心线程数为4(CPU limit为2)

一个集群会创建4个线程 以集群接入速度来看 目前是可以接受的。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
出现"java.lang.OutOfMemoryError: unable to create new native thread"错误通常是由于应用程序请求第三方系统资源时内存不足所导致的。这个错误可能发生在应用程序尝试创建新的本机线程,但无法分配足够的内存来支持新线程的情况下。这通常是由于操作系统的限制或者应用程序本身的资源管理问题所引起的。 在处理这个问题时,有几个可能的解决方案可以尝试: 1. 调整操作系统的线程限制:如果操作系统对线程数有限制,并且应用程序达到了这个限制,可以尝试增加操作系统的线程限制。这可以通过修改操作系统的配置文件来实现。 2. 优化应用程序的资源管理:检查应用程序的代码和配置,确保合理地使用和释放资源。特别注意确保关闭和释放不再使用的线程和连接,以避免资源泄漏。 3. 调整应用程序的线程池配置:如果应用程序使用了线程池来管理线程,可以尝试调整线程池的配置,如增加线程池的最大线程数或者使用不同的线程池实现。例如,如果应用程序使用的是newCachedThreadPool,可能会导致线程数无限制增长,从而导致内存不足。可以考虑使用固定大小的线程池来限制线程数。 4. 分析应用程序的线程使用情况:使用工具分析应用程序的线程使用情况,找出是否有线程泄漏或者线程过多的情况。可以使用工具如jstack、jvisualvm等来生成线程转储并进行分析。 综上所述,当出现"java.lang.OutOfMemoryError: unable to create new native thread"错误时,可以尝试调整操作系统的线程限制、优化应用程序的资源管理、调整应用程序的线程池配置或者分析应用程序的线程使用情况来解决该问题。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [问题分析:java.lang.OutOfMemoryError unable to create new native thre](https://download.csdn.net/download/weixin_35823099/86281250)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [【内存溢出系列】OutOfMemoryError:Java heap space(1/8)](https://blog.csdn.net/weixin_31966453/article/details/114324660)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [由于不知道Java线程池的bug,某程序员叕被祭天](https://blog.csdn.net/qq_33589510/article/details/109549716)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值