一次排查记录

2019-05-12  本文已影响0人  只是肿态度

现象

在SDMK的管理后台的订单管理模块中,发现获取订单列表数据的延迟非常高。经过测试,发现该接口在生产环境中的延迟竟然达到2.5S左右。

因此,我开始排查测试环境的接口,发现测试环境的接口稳定在500ms左右。说明这两个环境可能存在某种差异。这两个环境代码一致,环境配置一致,说明可能是哪个环节出现了问题。

慢慢开始排查这个接口的调用链信息,因为我们用的是微服务架构,每个接口可能会涉及多个模块。所以要在每个调用处添加日志打印以及记录调用接口调用时间。
比如:

 long start = System.currentTimeMillis();
 //接口调用
 long end = System.currentTimeMillis();
 invokeLogger.info("该接口耗时:{} ms", (end - start));

类似这样的代码添加在了多处调用点。

在测试环境,数据库请求在10ms以内,网络接口请求在20ms左右,并没有发现任何异常信息。
因此,想着在生产环境的一个节点部署下该版本,查验下究竟是哪里出现了问题。
果不其然,发现在请求官网账户中心的接口时,发现该接口不稳定,一直维持在90ms~200ms之间。

既然发现了问题所在,就要着手去解决。要解决这个问题有两种方案:

目前来看第二种比较现实一点,因为第一种,需要跟他们沟通、提需求,这些都是时间成本,因此还不如自己动手来的快。

最后经过优化、改善,接口的调用稳定在200ms。

回顾

回顾这次问题。我们不难发现,在微服务架构中,多个服务相互调用的情况很常见。因此,服务间的调用日志、监控必不可少。难道我们需要像前面那样,每处网络调用都要加这几行代码么?先不说繁琐,万一漏掉了某处,恰好这处出现了问题,到时候排查问题的时候可能会更麻烦。

因此,可以从网络请求处着手,我们一般都是用的第三方客户端比如apache的httpClient。我们可以借此封装自己的客户端,在网络的请求以及响应处添加自己的业务逻辑。这样就可以监控到每一处的网络请求。

我们的项目中有些是用SpringBoot框架,其中基本上都是用的spring提供的RestTemplate。因此,我对它做了点小小的添加,来达到我监控网络请求的目的。

RestTemplate自己提供了添加拦截器的方法。

    /**
     * Sets the request interceptors that this accessor should use.
     */
    public void setInterceptors(List<ClientHttpRequestInterceptor> interceptors) {
        this.interceptors = interceptors;
    }

因此,我们实现相应的拦截器就好了。

public class LoggingRequestInterceptor implements ClientHttpRequestInterceptor{
    final private Logger invokeLogger = LoggerFactory.getLogger("invokeLog");

    @Override
    public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
        return writeLog(request, body, execution);
    }

    private ClientHttpResponse writeLog(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
        long start = System.currentTimeMillis();
        ClientHttpResponse response = execution.execute(request, body);
        long end = System.currentTimeMillis();
        InvokeLog invokeLog = new InvokeLog(request.getURI().toString(), (end-start), response.getRawStatusCode());
        invokeLogger.info(invokeLog.toString());
        return response;
    }
}

然后在配置RestTemplate的时候添加上该拦截器:

   RestTemplate restTemplate = new RestTemplate();
   List<ClientHttpRequestInterceptor> interceptors = new ArrayList<>();
   interceptors.add( new LoggingRequestInterceptor());
   restTemplate.setInterceptors(interceptors);

这就简单的实现了在SpringBoot框架下实现了网络请求的统一监控。

但是这仅仅是只是监控某个服务的网络调用。并无法来监控整个调用链的。如果想尝试针对整个调用链的监控,可以试试zipkin。

上一篇 下一篇

猜你喜欢

热点阅读