上个月生产环境忽然出现部分交易处理缓慢甚至超时,查看对应应用日志发现一直在刷报错日志,报错信息如下
java.lang.OutOfMemoryError: unable to create new native thread
从报错上来看是说不能创建本地线程了,应用都是容器部署的,开始我怀疑是容器内存不够了导致内存泄露,但经过查看容器的内存使用情况,发现内存是够用的;
然后继续查看不同应用的日志,发现所有报错的应用都部署在同一台宿主机,因此我怀疑是公共资源导致的报错,于是翻了翻近几天的系统messages日志,发现系统pi服务器托管网d在一天前已经占满了,查看系统内核设置的pid最大是32768,这个感觉也够用啊,随即查看了这台机器上的容器,发现一共部署了大约三十个,然后docker stats查看了容器资源的使用情况,发现在每个容器占用的pid都不少,大多在1000-1100内,且观察了一段时间也没有释放的趋势,这样算来,30个容器确实会导致pid占满;
然后我开始分析为什么容器会占用1000-1100的线程数且不释放,我查看了生产环境的配置,单个应用配置的用来处理请求的最大线程数是1000,然后我在测试环境使用相同的配置启动应用,然后不断的发请求,并且监控docker stats,发现pid随着不断处理请求而增加,当增加到1000多的时候,pid不再增长,经过和我们的架构分析,我们为了满足性能要求,pid占用是不会释放的;
所以最后问题的原因就确定了,首先是单个宿主机部署的容器太多了且每个服务器托管网容器占用的pid不会释放,其次是pid设置的值偏小;
解决方案就是合理的分配机器资源,不在一台机器上部署过多的应用,或是在部署应用时评估最大pid设置为多少来调整系统参数。
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net
机房租用,北京机房租用,IDC机房托管, http://www.fwqtg.net
今天分享的内容比较基础,准确地说是 Go 的语言特性——命名、匿名返回值。 先看下面的例子,猜测会输出什么? package main func main() { println(A()) println(B()) } func A() int { var i…