zoukankan      html  css  js  c++  java
  • 性能测试之磁盘读引起IO高案例(四)

    案例:当Postgres磁盘读引起IO

         在性能分析的人眼里,性能瓶颈就是性能瓶颈。无论这个性能瓶颈出现在代码层、操作系统层、数据库层还是其他层,最终的目的只有一个结果:解决掉!

         有人可能会觉得这种说法过于霸道。

         事实上,我要强调的性能分析能力,是一套分析逻辑。在这一套分析逻辑中,不管是操作系统、代码还是数据库等,所涉及到的都只是基础知识。如果是对一个性能团队的要求,我觉得一点也不高。

         在性能测试和性能分析的项目中,没有压力发起,就不会有性能瓶颈,也谈不上性能分析了,所以每个问题的前提,都是要有压力。

         但不是所有的压力场景都合理,再加上即使压力场景不合理,也能压出性能瓶颈,这就会产生一种错觉:似乎一个错误的压力场景也是有效的。

         我是在介入一个项目时,首先会看到场景是否有效。如果无效,我就不会下手去调了,因为即使优化好了,可能也给不出生产环境应该如何配置的结论,那工作就白做了。

         所以要先调场景。我经常会把一个性能测试项目里面的工作分成两个阶段:

    整理阶段

    在这个阶段中,要把之前项目中做错的内容纠正过来,不止有技术里的纠正,还有从上到下沟通上的纠正。

    调优阶段

    这才真是干活阶段。在这个案例中,同样,我还是要表达一个分析的思路。

    案例问题描述

    这是一个性能从业人员问的问题:为什么这个应用的update用了这么长时间呢?他还给了我一个截图:

     

      从张图中可以看到时间在100ms左右。根据我的经验,一个SQL执行100ms,对实时业务来说,确实有点长了。

      但是这个时间是长是短,还不能下结论。要是也无需要必须写成这种耗时的SQL呢?

      接着他又发给我了TPS图。如下所示:

     

      这个TPS图确实……有点乱!还记得前面我对TPS的描述吧,在一个场景中,TPS是要有阶梯的。

      如果你在递增的TPS场景中发现了问题,然后为了找这个问题,用同样的TPS级别快速加起来压力,这种方式也是可以的。只是这个结果不作为测试报告,而是应该记录到调优报告当中。

      而现在我们看到的TPS趋势,那真是哪哪都挨不上呀。如此混乱的TPS,那必然是性能有问题。

         她还告诉了我两个信息。

    1. 100万条参数化数据;
    2. GC正常,dump文件也没有死锁的问题。

    这两个信息应该说只是信息,并不能起到什么作用。另外,我也不知道他说的GC正常是怎么个正常法,只能相信他说的。

    分析过程

      照旧,先画个架构图出来看看。有了这个,才能明确知道要面对的系统范围有多大;才能在一个地方出问题的时候,去考虑是不是由其他地方引起的;才能跟着问题找到一条条的分析路径……

      下面是一张简单的架构图,从下面这张图可以看到,这不是个复杂的应用,是个非常典型的微服务结构,只是数据库用了PostgreSQL而已。

     

      由于这个反馈的是从服务集群日志中看到的update慢,所以后面的分析肯定是直接对着数据库去了。

         这里需要提醒一句,我们看到什么现象,就跟着现象去分析。这是非常正规的思路吧。但就有一些人,明明看着数据库有问题,非要瞪着眼睛跟应用服务较劲。

      前不久就有一个人问了起一个问题,说是压力过程中,发现数据库CPU用完了,应用服务器的CPU还有余量,于是加了两个数据库CPU。但是加完之后,发现数据库CPU使用率没有上去,反而应用服务器的CPU用完了。我一听,觉得挺合理的呀,为什么他在纠结应用服务器CPU用完了呢?于是我就告诉他,别纠结这个,先看时间耗在哪了。结果发现应用的时间都耗在读取数据库上了,只是数据库硬件好了一些而已。

          因为这是个数据库上的问题,所以我直接查了数据库的资源。

     

      查看vmstat,从这个结果来看,系统资源确实没有用上。不过请注意,这个bi挺高的都30万以上了。那这个值说明了什么呢?我们来算一算。

         bi是指每秒读磁盘的块数。所以要先看一下,一个块有多大。

     

      那计算下来大约就是:303624/1024300M,显然这个值是不低的。

      接下来查看I/O。再执行下iostat看看。

     

      从这个结果来看,%util已经达到了95%左右,同时看rkB/s那一列,确实在300M左右。

      接着在master上面执行iotop

     

      我发现Walsender Postgres进程达到了56.07%的使用率,也就是说它的读在300M左右。但是写的并不多,从图上看只有5.77M/s

         结合上面的几张图,我们后面优化方向就是:降低读取,提高写入。

    到这里,我们就得说道说道。这个Walsender Postgres是干什么的,根据自己的理解,画了一个Walsender 的逻辑图:

     

      从这个图中可以看得出来,WalsenderWalreceiver实现了PostgreSQLmasterSlaves之间的流式复制。Walsender取归档目录中的内容(敲黑板了呀!),通过网络网络发送给WalreceiverWalreceiver接收之后在slave上还原和master数据库一样的数据。

    而现在读取这么高,那我们就把读取将下来。

         先查看一下几个关键参数。

     

     

      这两个数对PostgreSQL非常重要。Checkpoint_completion_target这个值标识这次checkpoint完成时间占到下一次checkpoint之间的时间百分比。

         这样说似乎不太好理解。画图说明一下:

       在这个图中300s就是checkpoint_timeout,即两次checkpoint之间的时间长度。这时若将Checkpoint_completion_target设置为0.1,那就是说checkpoint1完成时间的目标就是在30s以内。在这样的配置下,你就会知道Checkpoint_completion_target设置的越短,集中写的内容就越多,I/O峰值就会高;Checkpoint_completion_target设置的越长,写入就不会那么集中。也就是说Checkpoint_completion_target设置的长,会让写I/O有缓解。

           在我们这个案例中,写并没有多少。所以这个不是什么问题。

      但是读取I/O那么大,又是流式传输的,那就是会不断地读文件,为了保证有足够的数据可以流式输出,这里我把shared_buffers增加,以便减轻本地I/O的压力。

         来看一下优化动作:

     

      其中的max_wal_sizemin_wal_size官方给的含义如下所示:

     

       请注意,上面的shared_buffers是有点过大的,不过我们先验证结果再说。

    优化结果

    再看iostat

     

      看起来持续的读写降低了不少。效果是有的,方向没错。再来看看tps

     

          TPS确实稳定了很多,效果也比较明显。

      这也就达到了我们优化的目标了。就像在前面文章中所说的,在优化的过程中,当你碰到TPS非常不规则时,请记住,一定要先把TPS调稳定,不要指望在一个混乱的TPS曲线下做优化,那将使你无的放矢。

         问题又来了?

         在解决了上一个问题之后,没过多久,另一个问题又抛出来了,这是另一个接口,因为是在同一个项目上,所以对问问题的人来说,疑惑还是数据库有问题。

      来看一下TPS

     

       这个问题很明显,那就是后面的成功事务数怎么能达到8000以上?如果让你蒙的话,你觉得回事什么原因呢?

       在这里,告诉你我对TPS趋势的判断逻辑,那就是TPS不能出现以外的趋势。

       什么叫做意外趋势?就是当在运行一个场景之前就已经考虑到了这个TPS趋势应该是个什么样子(做尝试的场景除外),当拿到运行的结果之后,TPS趋势要和预期的一致。

       如果没有预期,就不具有分析TPS的能力了,最多也就是压出曲线,但不会懂曲线的含义。

       像上面的这处TPS图,显然就出现意外了,并且是如此大的意外。前面只有1300左右的TPS,后面怎么可能跑到8000以上,还全是对的呢?

             所以我看到这个图之后,就问了一下:是不是没加断言?

            然后他查了一下,果然没加断言。于是重跑场景,得到结果如下:

     

       从这个图上可以看到,加了断言之后,错误的事务都正常暴露出来了。像这种后台处理了异常并返回返回信息的时候,前端会收到正常的HTTP Code,所以才会出现这样的问题。

             这也是为什么通常我们都要加断言来判断业务是否正常。

    总结

        在性能分析的道路上,我们会遇到各种乱七八糟的问题。很多时候,我们期待着性能测试中的分析像破案一样,并且最好可以破一个惊天地泣鬼神的的大案,以扬名四海。

        然而分析到了根本原因之后,你会发现优化的部分是如此简单。

      其实对于PostgreSQL数据库来说,像bufferlogreplication等内容,都是非常重要的分析点,再做项目之前,我建议先把这样的参数给收拾一遍,不要让参数配置成为性能问题,否则得不偿失。

    思考题

     为什么加大buffer可以减少磁盘I/O的压力?为什么说TPS趋势要在预期的之内?

    性能测试报告见附件:某某银行性能测试规范v1.1

  • 相关阅读:
    2006: [NOI2010]超级钢琴
    3640: JC的小苹果
    2005: [Noi2010]能量采集
    金蝶云星空修改密码策略的SQL脚本
    关于 springboot 过滤器中使用@Autowired 为空 以及 使用 @Value 无法读取yml配置的问题解决
    CAS .NET Client 循环重定向的解决办法
    K/3 Cloud SSO配置
    K/3 Cloud SSO配置答疑
    K/3 Cloud 元数据表
    AngularJS select中ngOptions用法详解【转】
  • 原文地址:https://www.cnblogs.com/mys6/p/14941914.html
Copyright © 2011-2022 走看看