【编者按】新婚现场给服务器扩容 , 下班路上修Bug……对于程序员来说 , 这样的日常并不陌生 。 在新年第一天 , 国外一名叫Ali Josie 的软件工程师、信息安全爱好者就经历了找Bug、复现、修复这样的事情 , 并且还发表了一篇《This Is Why Our 3000 Apache Servers Went Down On The First Day of 2022》 , 具体是怎么一回事呢?作者 |Ali Josie 译者| 弯月
出品 | CSDN(ID:CSDNnews)
新年第一天 , 又恰逢周六 , 早上醒来却看到一堆整个基础设施挂掉的警报!我的一位同事就遭遇了这样的真实 , 他当时的心情可想而知 。
大清早
首先 , 最重要的是恢复服务 , 把服务宕机的影响降到最低 , 我们重启了所有Apache服务器 , 还好没有任何问题 。 接下来就要找出宕机的原因了 。 为什么所有服务器都在新年第一天宕机?这肯定不是偶然吧?
我们看到每台服务器上都记录了如下日志:
思考
回到错误本身 。我们每天早上都会做一次日志轮转 , 这样每天都用新的日志 。 因此要重启服务器 。 似乎Apache已经成功重启 , 但由于libgomp错误又宕机了 。
在网上搜索到的大量结果中寻找答案无异于大海捞针 , 于是我们开始阅读libgomp的源代码 , 看看究竟发生了什么 。 首先 , libgomp是什么?根据其主页的描述:
- “GOMP项目是C、C++和Fortran编译器OpenMP的一个实现……GOMP能简化所有GNU系统上的并行编程 。 ”
搜索了一下源代码 ,我们发现错误消息的唯一出处是这里:
所以显然 , 它在试图创建一个线程键 , 但出错了 。 检查pthread_key_create的手册:
- “pthread_key_create会创建用于线程专有的数据键 , 可在进程的所有线程中使用 。 pthread_key_create提供的键值是不透明的对象 , 用于定位线程专有的数据 。 虽然不同线程可以使用相同的键名称 , 通过pthread_setspecific绑定到键的值是按照线程维护的 , 在线程的整个生命周期都有效 。 ”
“pthread_key_create函数会在下述情况失败:
- 系统资源不足 , 无法创建另一个线程特定数据键 , 或每个进程的键总数达到了 PTHREAD_KEYS_MAX 上限 。
- 内存不足 , 无法创建键 。 ”
文章图片
所以说 , key只是一个0~1024之间(不含1024)的数字 , 赋给pthread_key_create的调用者 。 这些键由一个简单的CAS负责赋值 , 因此肯定有某个地方释放这些键 。 似乎我们找到了问题 。 我们只需要增大PTHREAD_KEYS_MAX 。 但是 , 这个值是常量 。 我们甚至找到了一个帖子 , 要求增加PTHREAD_KEYS_MAX:
- “pthread_key_create会拒绝超过 PTHREAD_KEYS_MAX pthread_key_t的创建请求 。 我遇到的问题是在NetBSD上Apache无法与多种模块一起工作 , 因为这个值太低了 。 时间长了 , 服务器就会陷入无法提供服务的状态 。 ”
特别声明:本站内容均来自网友提供或互联网,仅供参考,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
