上个月生产环境忽然出现部分交易处理缓慢甚至超时,查看对应应用日志发现一直在刷报错日志,报错信息如下
java.lang.OutOfMemoryError: unable to create new native thread
从报错上来看是说不能创建本地线程了,应用都是容器部署的,开始我怀疑是容器内存不够了导致内存泄露,但经过查看容器的内存使用情况,发现内存是够用的;
然后继续查看不同应用的日志,发现所有报错的应用都部署在同一台宿主机,因此我怀疑是公共资源导致的报错,于是翻了翻近几天的系统messages日志,发现系统pid在一天前已经占满了,查看系统内核设置的pid最大是32768,这个感觉也够用啊,随即查看了这台机器上的容器,发现一共部署了大约三十个,然后docker stats查看了容器资源的使用情况,发现在每个容器占用的pid都不少,大多在1000-1100内,且观察了一段时间也没有释放的趋势,这样算来,30个容器确实会导致pid占满;
然后我开始分析为什么容器会占用1000-1100的线程数且不释放,我查看了生产环境的配置,单个应用配置的用来处理请求的最大线程数是1000,然后我在测试环境使用相同的配置启动应用,然后不断的发请求,并且监控docker stats,发现pid随着不断处理请求而增加,当增加到1000多的时候,pid不再增长,经过和我们的架构分析,我们为了满足性能要求,pid占用是不会释放的;
所以最后问题的原因就确定了,首先是单个宿主机部署的容器太多了且每个容器占用的pid不会释放,其次是pid设置的值偏小;
解决方案就是合理的分配机器资源,不在一台机器上部署过多的应用,或是在部署应用时评估最大pid设置为多少来调整系统参数。