当前位置: 首页 > 科技观察

致命故障!投资人炸了!

时间:2023-03-18 01:07:54 科技观察

本文转载自微信公众号“小姐姐的味道”,作者小姐姐养的狗。转载本文请联系味觉小姐公众号。我听说了不起的人注重整体而不是细节,因为他们认为没有必要;我还听说管理哲学是协调资源,让人像牛一样低头,不达目的不罢休。置身于这种环境多年,生活中隐约有一种错觉:管理可以解决一切问题。如果管理解决不了,那一定是流程问题。但是看到拼多多这样的公司的管理方式后,我的信念又变了,觉得这是不对的。PDD的管理模式打了各大高校的《管理学》课程,抹黑了所有从事管理工作的人。只要钱够用,什么管理都不需要!只有没钱的穷B公司才搞管理。要说高能正统的管理,那非传销莫属了。话说的有点远,进入到跑题的路子了,需要用glitch拉回来。1、出现故障无事可做。如果你在IT行业,你每天都要面对故障。每个人都是传奇的消防员,到处救火。不过这次故障范围有点大,无法打开宿主机。好在监控系统留下了一些证据。有证据发现,随着业务的增长,机器的CPU、内存、文件句柄不断上升……上升……直到监控收不到信息。可怕的是,这些主机上部署了很多Java进程。没有别的原因,就是为了节省成本,应用混杂。当主机出现整体异常时,很难找到罪魁祸首。因为远程登录也Over了,暴力运维只能重启机器,重启机器后再重启应用。经过漫长的等待,所有的进程都还活着,但是仅仅片刻之后,宿主机就立即死亡了。生意一直处于死气沉沉的状态,着实让人恼火。这也令人担忧。几经尝试,运维崩溃,启动应急预案:回滚!最近上线记录很多,也有开发者擅自上线部署。脑子一亮,想起有个find命令,然后把最近更新的jar包都找出来,给它回滚。find/apps/deploy-mtime+3|grepjar$如果不知道find命令,那真是一场灾难。还好有人知道。回滚了十几个jar包,还好数据库的schema没有变,系统终于正常运行了。2.没有其他办法查找原因,查看日志,进行codereview。codereview应该追溯到最近一两周内的代码变动,因为有些功能代码需要沉淀一段时间才能上线。看着满是“OK”的提交记录,技术经理的脸都绿了。“xjjdog说,《80%的程序员,不会写commit记录》,我看你100%不会写。”所有人都安静下来,忍着痛苦查看着历史的变迁。经过大家的不懈努力,终于在一堆狗屎中找到了一些有问题的代码。CxO亲自建群,大家把可能出问题的代码丢到群里。“系统服务中断近一个小时,影响非常恶劣,”CxO表示,“必须彻底解决问题,投资者非常关心这个问题”!okokok,在钉钉的帮助下,大家的手势都统一了。3.线程池的参数代码很多,问题代码大家讨论了很久。包括一些使用并行流的代码,以及包裹在lamba表达式中的trick代码,也重点检查了一些使用线程池的代码。最后大家还是决定把线程池的代码再过一遍。其中一个是这样读的。RejectedExecutionHandlerhandler=newThreadPoolExecutor.DiscardOldestPolicy();ThreadPoolExecutorexecutor=newThreadPoolExecutor(100,200,60000,TimeUnit.MILLISECONDS,newLinkedBlockingDeque<>(10),handler);更不用说,参数有一个很好的模型,甚至考虑拒绝政策。Java的线程池让编程变得非常简单。它有很多参数,如上图所示,让我们一一介绍,否则代码无法查看。corePoolSize:核心线程数,核心线程创建后会存活maxPoolSize:最大线程数keepAliveTime:线程空闲时间workQueue:阻塞队列threadFactory:线程创建工厂处理程序:拒绝策略下面介绍一下它们的关系。当线程数小于核心线程数时,会产生新的任务,产生新的线程来服务。当当前线程数大于核心线程数且阻塞队列未满时,任务会被放入阻塞队列。当线程数大于核心线程数且阻塞队列已满时,会创建新的线程进行服务,直到线程数达到maximumPoolSize大小。此时,如果有新的任务,就会触发拒绝策略。再来说说拒绝策略。jdk默认实现了4个policy,默认实现是AbortPolicy,也就是直接抛出异常。下面描述了其他几个。DiscardPolicy比abort更激进,连异常信息都没有,直接丢弃任务。CallerRunsPolicy由调用线程处理。比如在一个web应用中,线程池资源满了之后,新的任务会在tomcat线程中运行。这种方式可以延缓部分任务的执行压力,但更多情况下会直接阻塞主线程的运行。DiscardOldestPolicy丢弃队列前端的任务,然后再次尝试执行该任务。这个线程池的代码是新加的。参数设置很正常,没有大问题。唯一可能的风险是使用DiscardOldestPolicy的拒绝策略。当任务很多时,这种拒绝策略会导致任务排队,请求超时。当然,这个风险不能放过。说实话,是目前能找到的最有可能的风险代码。“把DiscardOldestPolicy改成默认的AbortPolicy,重新打包上线试试。”技术专家在群里说。4、问题出在哪里?结果灰度服务上线后没多久宿主机就挂了。原因是没有运行,但是为什么呢?线程池的大小,最小为100,最大为200,说多了也不过分。阻塞队列的容量只有10,说什么都不会有问题。你要说是这个线程池引起的,我打死你也不信。但是业务部反映,加了这个代码就死了,不加就没事了。技术人员摸不着头脑,摸不着头脑,不知道他们的妹妹是什么东西。最后终于有人忍不住了,下载了业务代码调试。打开Idea,他先是一愣,然后又是一瞬间的领悟。他终于明白这段代码为什么会出问题了。线程池其实是在方法中创建的!当每个请求到来时,它会创建一个线程池,直到系统无法再分配资源。真是霸道啊。大家都在关注线程池的参数是怎么设置的,但是从来没有人怀疑过这段代码在哪里。5、结尾题层次低,普遍。现在我严重怀疑拒绝策略也是从网上抄来的代码。那么多码农熬夜,选择业务低峰期上线,但还是逃不过性命,也逃不过猪队友的伤害。当然,这也说明了另一个问题:如果技术能力跟不上,再好的管理也是束手无策。最后,几乎没有人愿意为连投资人都施压的失败去实际检查业务的代码。这屎山有多大,让人避而远之,生怕弄脏了自己的羽毛!作者简介:薇薇小姐姐(xjjdog),一个不允许程序员走弯路的公众号。专注于基础架构和Linux。十年架构,每天百亿流量,与你探讨高并发世界,给你不一样的滋味。我的个人微信xjjdog0,欢迎加好友进一步交流。