欢迎访问昆山宝鼎软件有限公司网站! 设为首页 | 网站地图 | XML | RSS订阅 | 宝鼎邮箱 | 后台管理


新闻资讯

MENU

软件开发知识

为了证明我 劳务派遣管理系统 们的猜测

点击: 次  来源:宝鼎软件 时间:2017-09-30

原文出处: @蛋疼的axb

1.摘要

前一阵子发明处事会有偶发的处事不行用的环境,记录一下这个问题的排查进程。

现象是这样的:天天到了某个时间点,就会呈现处事不不变的环境,偶发接口调不通。

线上业务利用了lvs-nginx-tomcat三层布局,首先查察tomcat监控,没有什么出格异常的环境,响应时间和错误码没发明有什么异常,软件开发,CPU、IO等等指标也都正常。

再查察nginx上的监控,发此刻某个时刻这个处事的5xx报错突增,软件开发,或许7、8秒之后又规复了。

继承在nginx处事器上找线索,发明Nginx在谁人时间点会呈现报错:

2015/12/24 10:30:38 [error] 13433#0: check time out with peer: 10.79.40.1xx:80

线上nginx会每秒探测后端所有处事器的某个uri,假如返回的http状态码是200则认为正常,持续3次探测失败则摘除探测失败的处事器,直到探测乐成再规复。

从日志中可以发明nginx在出问题的时间点对付后端所有tomcat的探测请求都呈现了问题,导致摘除了所有后端处事器,在这段时间里请求会报502异常。

从nginx上的日志可以看到探测请求没有返回,那么请求实际发到tomcat了没有?线上业务中的探测频率是1s/次,于是到tomcat的会见日志里查找线索,过滤一个nginx对tomcat的所有探测请求:

为了证明我 劳务调派打点系统 们的揣摩

可用看出从7:00:10-7:00:40阁下的探测请求是有丢失的。

前端机的负载并不高,于是我们第一时间认为这大概是nginx到tomcat处事器的网络有问题。统计了一下线上日志,出问题的呆板会合在某个网段,劳务派遣管理系统,而且会合在一天之内的某几个时间点,这好像也进一步印证了我们的揣摩。

但到此为止仅仅是猜疑,为了证明我们的揣摩,我们实验去复现问题。我们在nginx上陈设了一个简朴的剧本,用curl呼吁对同样的tomcat提倡每秒一次的请求,但功效较量诡异:

监测方法 监测地点 http版本 频率 地址处事器 目标处事器 问题

nginx / 1.0 1s nginx tomcat 有
curl / 1.0 1s nginx tomcat 无

这跟我们之前的揣摩纷歧致,没步伐,实验在两头抓包查察网络状况,

tomcat抓包:

为了证明我 劳务调派打点系统 们的揣摩

nginx抓包:

为了证明我 劳务调派打点系统 们的揣摩

tomcat处事器在7:00:10已经吸收了请求而且回覆了ACK,7:00:13 nginx超时主动断开毗连,7:00:15时tomcat才返回数据,网络的问题被解除了。

那么接下来的重点就是tomcat自己,在吸收问题请求的时候,tomcat处事毕竟做了什么?

照旧通过简朴的剧本,在容易出问题的时间段持续利用jstack打印线程栈,查找出问题时处于RUNNABLE状态的catalina线程,发明这里有一句很可疑:

为了证明我 劳务调派打点系统 们的揣摩

这个处事用的照旧较量陈腐的tomcat6.0.32,查察源码,可以发此刻tomcat对请求header做完理会之后会挪用这个函数:

        MessageBytes valueMB = headers.getValue("host");

        // Check host header
        if (http11 && (valueMB == null)) {
            error = true;
            // 400 - Bad request
            if (log.isDebugEnabled()) {
                log.debug(sm.getString("http11processor.request.prepare")+
                          " host header missing");
            }
            response.setStatus(400);
            adapter.log(request, response, 0);
        }

        parseHost(valueMB);
        
        
        ....
     /**
     * Parse host.
     */
    public void parseHost(MessageBytes valueMB) {

        if (valueMB == null || valueMB.isNull()) {
            // HTTP/1.0
            // Default is what the socket tells us. Overriden if a host is
            // found/parsed
            request.setServerPort(socket.getLocalPort());
            InetAddress localAddress = socket.getLocalAddress();
            // Setting the socket-related fields. The adapter doesn't know
            // about socket.
            request.serverName().setString(localAddress.getHostName());
            return;
        }

也就是说,假如request请求的header里没有配置host,那么tomcat会利用本身处事器的hostname作为request工具的host属性。

再比拟线上nginx探测的请求和curl发出的请求,可以看出nginx的探测请求确实没有带任何header,而curl请求默认是带了3个header的:

curl:

GET / HTTP/1.0
Host: localhost:8080
User-Agent: curl/7.43.0
Accept: */*

nginx:

GET / HTTP/1.0

到这里可以确认,假如请求的header里没有带Host的话就有大概呈现问题。找到了hang住的位置,那么接下来的问题就是,为什么这里会hang住?