性能文章>记一次线上服务不可用问题分析>

记一次线上服务不可用问题分析原创

1年前
532819

问题描述

线上接口服务隔一天就不能访问,重启大法好,只要重启就可以调用,间隔半天又会出现这种情况,由于该服务是mocker代理服务,所以开了443、80、11181等端口,但是只有80端口才会被阻塞,其他端口访问服务没有问题

问题排查分析

最初没有意识到和端口有关,所以下意识的去想是不是服务器宕机了,所以直接去环境敲命令,查看当前java PID

jps 

获取当前web服务运行的pid之后,通过查看内存gc来判断服务器是否挂掉

jstat -gcutil ${pid} 2000 20 

image.png

具体展示内容可以查看jvm相关命令学习,在这里简单说下这个gc是没有问题的,gc次数和时间没有明显异常,其实下面进行了一次ygc,截图没有截到,证明服务是没有问题的。

思考会不会是端口被安全组或防火墙给关了? 通过telnet 查看端口也是通的啊。

image.png

纳闷了,端口是通的,服务也没挂,到底是啥问题,要疯了,只能让运维保留客户现场,然后重启服务了。说到保留现场的话,建议设置jvm一个参数当OOM时,输出dump文件。

由于当前服务没挂,所以只能手动通过jmap命令来打包,具体去网上查一下,然后我又让运维把线程的日志文件给我down了一份,正是由于我多此一举的查看线程文件,才发现了问题的根源!!!!

不说了,先上图

image.png

jstack ${pid} > stack.log

image.png

想必各位大神应该差不多明白了,大量的线程处理80端口请求的服务,但是这些接口应该处理完了啊,逻辑也不是很复杂,为什么线程一直在运行呢~~。为了验证其他端口没有阻塞这个猜想,我用其他端口测一下接口服务,果然接口可以调通返回数据。

至于怎么去分析线程日志的话,说实话,还是要凭感觉的,因为线上大部分问题其实是由于锁操作或者其他某些问题导致线程死锁TIME_WAIT或WAITING等,但是线程一直是RUNNABLE的出问题真的要靠猜了,我也是看到大量80线程一直运行才想到这方面。

既然项目里面没有运行完,说明进入80端口的服务没有处理完就被客户端关闭了,导致大量请求CLOSE_WAIT,具体TCP/IP原理四次挥手原理建议小伙伴们去温习一下,这里就不多做描述了。

image.png

可以看到上图,大量请求没有完成就被动关闭了,至此,整个问题就分析完成。知道原因的话就好解决了。

解决问题

其实从分析打印出来的栈日志就能看到,是请求某个链接,没有返回导致接口长时间没有返回,但是后台请求其他服务的HttpClient服务一般都是会设置SOCKET_TIMEOUTConnect_TimeOut值,所以不应该会有这种问题出现的,为了验证这一问题,去看代码是最好的。

image.png

上图可以看到,左边是没有修改之前,并没有设置请求参数设置,右边是加了请求超时的配置,具体配置如下:

image.png

连接超时和读取超时时间都设置为5s,这样防止请求接口时,接口没有请求处理完发起关闭连接,导致问题重复发生。

至此,该问题就已经彻底解决了。

其实出现问题不可怕,可怕的是不知道哪里出现了问题。解决问题要按部就班,把所有可能出现的问题一一排查,走到最后总是能找到问题的根源所在,找到问题并解决问题,最后,希望你也可以顺利解决自己的问题。

本文作者:钟元

请先登录,查看1条精彩评论吧
快去登录吧,你将获得
  • 浏览更多精彩评论
  • 和开发者讨论交流,共同进步

为你推荐

字符串字面量长度是有限制的
前言 偶然在一次单元测试中写了一个非常长的字符串字面量。 正文 在一次单元测试中,我写了一个很长的字符串字面量,大概10万个字符左右,编译时,编译器给出了异常告警 `java: constant
多次字符串相加一定要用StringBuilder而不用-吗?
今天在写一个读取Java class File并进行分析的Demo时,偶然发现了下面这个场景(基于oracle jdk 1.8.0_144): ``` package test; public c
如何通过反射获得方法的真实参数名(以及扩展研究)
前段时间,在做一个小的工程时,遇到了需要通过反射获得方法真实参数名的场景,在这里我遇到了一些小小的问题,后来在部门老大的指导下,我解决了这个问题。通过解决这个问题,附带着我了解到了很多新的知识,我觉得
高吞吐、低延迟 Java 应用的 GC 优化实践
本篇原文作者是 LinkedIn 的 Swapnil Ghike,这篇文章讲述了 LinkedIn 的 Feed 产品的 GC 优化过程,虽然文章写作于 April 8, 2014,但其中的很多内容和
「每日五分钟,玩转 JVM」:久识你名,初居我心
聊聊 JVMJVM,一个熟悉又陌生的名词,从认识Java的第一天起,我们就会听到这个名字,在参加工作的前一两年,面试的时候还会经常被问到JDK,JRE,JVM这三者的区别。JVM可以说和我们是老朋友了
据说99.99%的人都会答错的类加载的问题
概述首先还是把问题抛给大家,这个问题也是我厂同学在做一个性能分析产品的时候碰到的一个问题。 同一个类加载器对象是否可以加载同一个类文件多次并且得到多个Class对象而都可以被java层使用吗请仔细注意
Java多线程——并发测试
编写并发程序时候,可以采取和串行程序相同的编程方式。唯一的难点在于,并发程序存在不确定性,这种不确定性会令程序出错的地方远比串行程序多,出现的方式也没有固定规则。那么如何在测试中,尽可能的暴露出这些问
Java多线程知识小抄集(一)
本文主要整理笔者遇到的Java多线程的相关知识点,适合速记,故命名为“小抄集”。本文没有特别重点,每一项针对一个多线程知识做一个概要性总结,也有一些会带一点例子,习题方便理解和记忆。 1.interr