服务雪崩问题

问题原因:最近项目上线,上线过程中引发了服务的不可用问题,立即回滚得到解决,那么问题原因是什么呢,主要是我改了我们服务之间的调用关系链路,调用关系很简单,本来是我们对外提供了一个HTTP接口,给公司其他团队使用,这个接口的流量非常大,平均QPS在8000左右,这个接口的逻辑不是很复杂,其中一个前置的逻辑就是查询CouchBase,那么问题就产生在这里,因为我们在做中间件的迁移,所以需要将次couchbase从A服务中迁移到B服务中,我的做法就是将couchBase迁移到B服务中,然后通过HTTP请求A服务来调用B服务,以上就是整个代码的改动,代码改动之后上线,上线过程中,服务的表现就是刚开始没问题,过了一会我们A服务对外的HTTP接口响应延时升高,B服务出现大量499超时,A服务也出现大量超时,最后A服务被健康局检查杀死,B服务也出现问题,以上就是整个代码的改动以及出现的问题。

第一阶段,出现了这个问题当时还是很慌的,因为对大流量问题的处理不是很多,所以开始的时候也不知道问题出在哪里,因为我们将A服务调用CouchBase改为了HTTP,所以问题肯定是出现在这里,最开始的想法是不是HTTP客户端的连接池配置的不合理导致的,所以重新改了一些HTTP客户端的配置,配置如下

我们的配置是客户端在80ms之内超时。长连接,连接数在200

        // 长连接保持1天
        PoolingHttpClientConnectionManager pollingConnectionManager = new PoolingHttpClientConnectionManager(1,
            TimeUnit.DAYS);
        // 总连接数
        pollingConnectionManager.setMaxTotal(200);
        // 同路由的并发数
        pollingConnectionManager.setDefaultMaxPerRoute(200);
        HttpClientBuilder httpClientBuilder = HttpClients.custom();
        httpClientBuilder.setConnectionManager(pollingConnectionManager);
        // 重试次数
        httpClientBuilder.setRetryHandler(new DefaultHttpRequestRetryHandler(1, true));
        // 保持长连接配置,需要在头添加Keep-Alive
        httpClientBuilder.setKeepAliveStrategy(new DefaultConnectionKeepAliveStrategy());
        HttpClient httpClient = httpClientBuilder.build();
        HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory(
            httpClient);
        clientHttpRequestFactory.setConnectTimeout(1000);
        clientHttpRequestFactory.setReadTimeout(80);
        return new RestTemplate(clientHttpRequestFactory);

配置之后重新上线还是发现问题依旧,上线过了一会服务很快就不行了,大量499超时, A服务被健康检查杀死,这个时候因为经验不够,不知道如何处理了,所以在同事的帮助下,用了一个工具就是Arthes

这个工具还是很好用的,我们灰度了几台机器然后将流量小步放开通过Arthes来观察情况,这里面流量小步方法,是在配置中心配置了一个数据,然后来请求的时候每次都产生一个随机数,如果大于这个随机数,那么A服务就请求B服务的HTTP接口,否则还是请求本地的CouchBase,因为是在公司内部需要使用Arthes,设计到网络问题,所以我们可以先将Arthes下载到本地,然后在上传到公司的堡垒机上,获取下载链接,在去我们的容器上进行下载,然后启动。

我们是将Arthes下载在B服务中的,然后通过对A服务放流量来观察B服务的CPU,内存的一些情况,

发现最明显的就是BusinessLogicThread-0001-0001这个线程只要一出行大量的waitting,A服务的对外接口响应时间就会上升,不知道是不是巧合,然后我们开始追踪BusinessLogicThread-0001-0001这个线程的来源,通过thread 线程ID来打印这个线程的堆栈,只能看出来这个线程是从线程池产生的,不知道其他的原因,这个时候心情还是比较差的,感觉唯一的线索没有了。

第二阶段,跟我们组长说了一下这个接口的情况,A服务调用B服务改成了HTTP,以及之前查询CouchBase的时间和现在B服务通过HTTP接口返回的时间,之前CouchBase我打印了日志,查询一个CouchBase耗时大约得2ms左右,响应非常快,改成了HTTP接口提供服务之后,响应时间变成了30ms左右,可以说是响应时间提升了15倍左右,我们组长说那问题就出现在这里,得去排查一下为什么加了一层HTTP代理之后响应时间加了这么多,理论上也就是加个2ms左右,HTTP内部网络传输也是很快的,你可以算一下 之前响应时间是2ms 那么1秒可以处理500个请求 线下响应时间变成了30ms,一秒可以处理30个请求,那如果一次请求很多,后边的接口请求就会阻塞,导致服务相应时间升高,相关联的服务也会有问题,因为整个排查的重心变成了,为什么改为了HTTP接口以后,响应时间变这么高,

最开始我看了下网关日志,看一下是不是网关的问题

可以看出request_time和upstream_response_time是差不多的,upstream_response_time是后端服务的响应时间

同时也通过CURL命令直接访问后端服务的接口看了下耗时,发现的确需要30ms左右,那问题就是还是出现在B服务上,B服务的耗时就是这么多,为什么呢,因为B服务也就是查询了一下CouchBase然后返回,怎么时间这么多,这个时候Arthes的作用就真的显现出来了

通过trace命令跟踪某个接口

trace creation.ops.controller.api.backdoor.couchbase.QipuIdToMaterialIdInnerController getMaterialFromCb

通过图片大家可以看出来有大量的耗时都在intercept上,都是被spring的拦截器耗时引起的,那这个又是什么东东,哪来的这么多拦截器,难道是代码中AOP引起的?OK打开IDEA看了一下我们的代码

发现代码中的确是有大量的AOP但是并不是所有的AOP都拦截了这个方法,因此我去掉了几个拦截这个方法的AOP,重新部署了一下代码然后通过trace进行跟踪,发现拦截的时间的确没有了!!!!而且

时间跟CouchBase的查询时间也的确是查了2ms左右,基本上是差不多,这个时候感觉是看到了希望,发布到线上,然后进行流量的灰度观察,发现服务的确没问题了,不会像之前一样流量一大服务的响应时间时间大量升高这种情况,为了避免流量过大,在网关层加入了限流,会发现B服务会报出429错误的情况,跟网关同事沟通,是因为流量过大,触发了限流,所以才会有429的这个错误码,不过不是主要问题,不影响服务,同事会有不到%0.1的499错误码,这个也不影响服务和接口.到这里整个的问题排查与解决就全部结束了,一下是几个目前我的疑问点。

  1. 我明明设置了连接池的响应时间是80ms,就算是B服务来不及处理那A服务也应该会报响应超时的情况,然后返回,而不至于A服务接口的对外响应时间这么高,导致拖垮了A服务,这点不是很明白,不过从当时的日志情况来看我发现A服务请求B服务的HTTP链接哪里,好像是没出现超时,而是请求阻塞在那里了,这个需要试验一下,在确定下问题。

  1. 主要是经验不足,没有找到问题的明确点,其实根本原因还是在B服务的HTTP接口性能不足,导致的一系列问题,而性能不足的原因要依次排查,但是却不知道从哪里下手,还是在同事的帮助下,使用了arthes才知道可以通过trace命令去查看接口的响应时间和调用链,arthes这个工具还是很好用的

  1. 对CURL一些命令使用的也不是很熟练,同事对一些状态码不是很敏感,不知道它真正表达的是什么意思,比如说499

  1. 对HTTP连接池的调优经验不是很足,不知道如何去调优,每个字段参数的含义不是很清楚。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值