记一次服务器响应慢问题的排查

这次问题查了一个星期,期间有点紧张,慌得一比,确定问题原因之前都是懵的。

1.发现日志里面有mysql连接超时(Communications link failure,The last packet sent successfully to the server was 0 milliseconds ago. Caused by: java.net.ConnectException: Connection timed out)的情况;


2.发现有的请求花了6s,有的花了12s,有的15s超时报异常;
3.baidu搜了一番没什么结果,到“MySQL技术大牛群”QQ群里咨询,大牛们各种说法都有

 

 

 

考虑是连接池不够大,达到连接池上限,于是调大resin数据源连接池上限配置,从20调到50;查数据库慢日志,发现没有业务查询的记录


4.问题仍然存在,想分析日志,没有找到能用的工具,于是自己写java程序分析日志,统计连接请求时间分布,发现91%在1s内响应,有部分1-2s,有部分3s,有部分6s,有部分12s,很有规律,1.5->3->6->12,成倍增长,其它响应时间的很少

接口主要的开始和结束日志是这种格式:

2022-01-19 08:09:32,469 INFO   -[http://*:8080-4] - [AgentController] requestId=xxxx,进入AgentController的loginAndCall()方法,参数:{"agentId":"","ani":"2","dn":"xxxx","number":"xxxx","requestId":"xxxx","um":"xxxx"}

2022-01-19 08:09:32,499 INFO   -[pool-1-thread-1] - [AgentController] requestId=xxxx,强制登录----start

分析代码如下,用了正则表达式提取关键信息

public static void main(String[] args) throws ParseException {
        List<String> list = readFile("E:\\Document\\CRM\\CDesk\\2022年1月\\日志0124\\AgentController59-0124.log");
        Pattern pattern = Pattern.compile("(.*) INFO.*http.*AgentController.*requestId=(.*?),.*|(.*) INFO.*AgentController.*requestId=(.*?),.*强制登录.*start.*");
        Map<String, List<String>> requestIdMap = new LinkedHashMap<String, List<String>>();
        for (String s : list) {
            Matcher matcher = pattern.matcher(s);
            if (matcher.find()) {
                String time = matcher.group(1);
                String requestId = matcher.group(2);
                if (time == null) {
                    time = matcher.group(3);
                    requestId = matcher.group(4);
                }
                List<String> timeList = requestIdMap.get(requestId);
                if (timeList == null) {
                    timeList = new ArrayList<String>();
                    timeList.add(time);
                    timeList.add(time);
                    requestIdMap.put(requestId, timeList);
                }
                if (timeList.get(1).compareTo(time) < 0) {
                    timeList.set(1, time);
                }
                //System.out.println(matcher.group(1) + "\t" + matcher.group(2));
            }
        }
        List<Long> statistic = new ArrayList<Long>();
        for (int i = 0; i < 50; i++) {
            statistic.add(0L);
        }
        for (String requestId : requestIdMap.keySet()) {
            List<String> timeList = requestIdMap.get(requestId);
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss,SSS");
            Date begin = sdf.parse(timeList.get(0));
            Date end = sdf.parse(timeList.get(1));
            long diff = (end.getTime() - begin.getTime()) / 1000;
            int interval = (int) diff;
            if (interval > 6) {
                System.out.println(requestId + " " + diff);
            }
            statistic.set(interval, 1 + statistic.get(interval));
        }
        //System.out.println(statistic);
        long sum = 0;
        for (int i = 0; i < 50; i++) {
            System.out.println(i + "s 请求数" + statistic.get(i));
            sum += statistic.get(i);
        }
        System.out.println(sum);
    }


5.考虑数据库连接池50还是不够,获取连接池可能有间隔时间递增的算法,于是把连接池从50调到500;
6.问题仍然存在,没有办法,考虑网络问题。对程序所在机器进行数据库端口3306的抓包;
7.抓包文件中出现大量TCP Retransmission,有的重传6次才成功得到响应,正好花了6s;每次重传间隔时间倍增;


8.网络组最后排查网络问题,查到是keepalive的id重了,于是解决了网络问题,再分析日志,已经正常了,一天内两个实例的10979个http请求中只有1个超过了1s,其他都在1s内响应了

总结:愚以为网络问题是找不到问题真正原因时用来搪塞的借口,所以一直没有想到去抓包查网络问题,浪费了几天时间,没想到真是网络问题。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值