美文网首页
记一次线上故常处理

记一次线上故常处理

作者: ajajaj | 来源:发表于2020-08-19 08:32 被阅读0次

前言

作为一个开发,肯定会遇到线上问题,遇到线上故障快速的定位解决,是开发者一项必备的能力。工作中可能会遇到各种故障,这边主要记录下之前遇到的一个线上问题

问题描述

早上到办公室打开钉钉,发现线上应用的一个实例重启了…..

卧槽感觉情况不妙!!!

image

迅速打开sls看下线上日志情况,一看果然有问题

oom了….

image

自己登录系统大致浏览了下,系统比较正常,应该是重启之后,使用过程中没发生异常情况,感觉应该是偶发情况,准备看下代码慢慢定位下问题,再解决。

就在这时,系统的用户找过来了

image

于此同时发现,公司内部运维系统消息推送群,出现一大波线上实例重启的日志

感觉这个问题很严重呀…...

image

问题分析

再次到sls看下,竟然没有发现异常日志,这是怎么回事呢?

找运维问下吧

运维给出的回复是OOM了,但是我这边最近几次oom的日志,我这边不确定和上面的是不是同一个问题(上一次有明确的日志,这几次实例重启没有日志呀)

image

随后运维给出了线上服务的cpu、内存使用情况

OOMKilled 是因为实例内存超过了K8S给它分配的最高允许内存,所以K8S就把它oomkill掉

image

但是我还是怀疑和上面是同一个问题,我结合上面日志描述的异常看了下代码,然后我找到上面报错日志指向的接口,一看真的是要骂娘(当然自己代码写的也很烂),这代码写的呀…...

image

这种代码频繁访问接口,线程创建的多了,肯定会有很大的内存占用,K8s检测到了那就把实例杀掉了呀

用过CompletableFuture的同学就知道,默认情况下 CompletableFuture 会使用公共的 ForkJoinPool 线程池,这个线程池默认创建的线程数是 CPU 的核数(也可以通过 JVM option:-Djava.util.concurrent.ForkJoinPool.common.parallelism 来设置 ForkJoinPool 线程池的线程数)。如果所有 CompletableFuture 共享一个线程池,那么一旦有任务执行一些很慢的 I/O 操作,就会导致线程池中所有线程都阻塞在 I/O 操作上。这样等有大请求量过来,处理逻辑又很复杂,很多线程都在等待执行,慢慢拖垮了服务器。

这个异常问题本质原因是我们创建了太多的线程,而能创建的线程数是有限制的,导致了异常的发生。能创建的线程数的具体计算公式如下

(MaxProcessMemory - JVMMemory - ReservedOsMemory) / (ThreadStackSize) = Number of threads

  • MaxProcessMemory 指的是一个进程的最大内存
  • JVMMemory JVM内存
  • ReservedOsMemory 保留的操作系统内存
  • ThreadStackSize 线程栈的大小

在java语言里, 当你创建一个线程的时候,虚拟机会在JVM内存创建一个Thread对象同时创建一个操作系统线程,而这个系统线程的内存用的不是JVMMemory,而是系统中剩下的内存(MaxProcessMemory - JVMMemory - ReservedOsMemory)。由公式得出结论:你给JVM内存越多,那么你能创建的线程越少,越容易发生 java.lang.OutOfMemoryError: unable to create new native thread

问题复现

那么问题基本可以确定了,根据接口找到对应的页面,然后在预发环境频繁浏览那个页面,然后我让运维到宿主机和容器看下具体的情况(看看这线程数量涨的…..),果然又发现预发的实例也重启了!

image

问题解决

问题定位了清楚就好解决了呀

刚才的代码对应的地方改成自定义线程池就好了

//可以指定线程池  
static CompletableFuture<Void> 
  runAsync(Runnable runnable, Executor executor)

改完上线,线上立马稳了…...

问题总结

  • 线程属于宝贵资源,使用的时候尽量使用线程池管理,在使用线程池的时候,要注意尽量使用自定义线程池,明确线程池中的各个参数
  • codereview很重要呀!!!

码字不易,觉得还不错可以点个赞

原文地址

http://cbaj.gitee.io/blog/2020/06/19/%E8%AE%B0%E4%B8%80%E6%AC%A1%E7%BA%BF%E4%B8%8A%E6%95%85%E5%B8%B8%E5%A4%84%E7%90%86/#more

相关文章

  • 记一次线上故常处理

    前言 作为一个开发,肯定会遇到线上问题,遇到线上故障快速的定位解决,是开发者一项必备的能力。工作中可能会遇到各种故...

  • 记一次线上故障处理

    1.背景 负载均衡两台机器一台cpu飙高,一台正常 2.问题排查 1.排除了代码问题2.排除了上下游调用3.排除了...

  • 记一次线上'事故'处理

    记一次线上'事故'处理 今早十点左右(2019年12月23日 10:00), 项目运营反馈新版 App 有闪退问题...

  • 线上故障处理书目录

    线上故障处理之故障信息获取源 线上故障处理之处理流程 线上故障处理之故障后处理

  • 此间倾城之故常记于心

    高二文理分班后,少了部分文科的优势,总成绩排名开始掉的厉害,根据学习互补的方针张老头安排他当我同桌。他脾气很好,我...

  • 故常怀

    从乡村到县城、市区,再到一千六百公里的沿海城,足迹不算多。虽然我始终觉得在哪儿不重要,和万事万物的互动都值得认真对...

  • 记一次线上重大故障处理与思考

    背景 像往常一样,和部门的同事准备参加晨会。去会议室的途中,被其他部门的同事叫住,告知收到线上告警,我们部门核心平...

  • 记一次线上update数据报错ERROR 1062 (23000

    记一次线上update数据报错ERROR 1062 (23000): Duplicate entry '1764-...

  • gitlab 500 no space left on devi

    gitlab故障处理一: gitlab nginx页面500 记一次gitlab故障处理之no space lef...

  • Kafka线上单partition积压问题定位

    现象 近期,参与了一次处理线上Kafka单partition积压问题的定位处理。总结一下 处理过程 我上线的情况是...

网友评论

      本文标题:记一次线上故常处理

      本文链接:https://www.haomeiwen.com/subject/qsxrjktx.html