一次出产 CPU 100% 排查优化实践
副问题[/!--empirenews.page--]
媒介 到了年底公然都不平静,最近又收到了运维报警:暗示有些处事器负载很是高,让我们定位题目。 还真是想什么来什么,前些天还存心把某些处事器的负载进步(没错,老板让我写个 BUG!),不外还好是差异的情形相互没有影响。 定位题目 拿到题目后起首行止事器上看了看,发明运行的只有我们的 Java 应用。于是先用 ps 呼吁拿到了应用的 PID。 接着行使 ps-Hppid 将这个历程的线程表现出来。输入大写的 P 可以将线程凭证 CPU 行使比例排序,于是获得以下功效。 公然某些线程的 CPU 行使率很是高。 为了利便定位题目我立马行使 jstack pid>pid.log 将线程栈 dump 到日记文件中。 我在上面 100% 的线程中随机选了一个 pid=194283 转换为 16 进制(2f6eb)后在线程快照中查询: 由于线程快照中线程 ID 都是16进制存放。 发明这是 Disruptor 的一个仓库,前段时刻正好办理过一个因为 Disruptor 行列引起的一次 OOM:强如 Disruptor 也产生内存溢出? 没想到又来一出。 为了越发直观的查察线程的状态信息,我将快照信息上传到专门说明的平台上。 http://fastthread.io/ 个中有一项菜单展示了全部耗损 CPU 的线程,我细心看了下发明险些都是和上面的仓库一样。 也就是说都是 Disruptor 行列的仓库,同时都在执行 java.lang.Thread.yield 函数。 众所周知 yield 函数会让当前列程让出 CPU 资源,再让其他线程来竞争。 按照适才的线程快照发明处于 RUNNABLE 状态而且都在执行 yield 函数的线程或许有 30几个。 因此起源判定为大量线程执行 yield 函数之后相互竞争导致 CPU 行使率增高,而通过对仓库发明是和行使 Disruptor 有关。 办理题目 尔后我查察了代码,发明是按照每一个营业场景在内部城市行使 2 个 Disruptor 行列来解耦。 假设此刻有 7 个营业范例,那就便是是建设 2*7=14 个 Disruptor 行列,同时每个行列有一个斲丧者,也就是总共有 14 个斲丧者(出产情形更多)。 同时发明设置的斲丧守候计策为 YieldingWaitStrategy 这种守候计策确实会执行 yield 来让出 CPU。 代码如下: 起源看来和这个守候计策有很大的相关。 当地模仿 为了验证,我在当地建设了 15 个 Disruptor 行列同时团结监控调查 CPU 的行使环境。 建设了 15 个 Disruptor 行列,同时每个行列都用线程池交往 Disruptor行列 内里发送 100W 条数据。 斲丧措施仅仅只是打印一下。 跑了一段时刻发明 CPU 行使率确实很高。 同时 dump 线程发明和出产的征象也是同等的:斲丧线程都处于 RUNNABLE 状态,同时都在执行 yield。 通过查询 Disruptor 官方文档发明: YieldingWaitStrategy 是一种充实压榨 CPU 的计策,行使 自旋+yield的方法来进步机能。 当斲丧线程(Event Handler threads)的数目小于 CPU 焦点数时保举行使该计策。 同时查阅到其他的守候计策 BlockingWaitStrategy (也是默认的计策),它行使的是锁的机制,对 CPU 的行使率不高。 于是在和之前同样的前提下将守候计策换为 BlockingWaitStrategy。 和适才的 CPU 比拟会发明到后头行使率的会有明明的低落;同时 dump 线程后会发明大部门线程都处于 waiting 状态。 优化办理 看样子将守候计策换为 BlockingWaitStrategy 可以减缓 CPU 的行使, 但寄望到官方对 YieldingWaitStrategy 的描写里谈道: 当斲丧线程(Event Handler threads)的数目小于 CPU 焦点数时保举行使该计策。 (编辑:湖南网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |