V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
seraphv3
V2EX  ›  Java

网站性能着急,怎么定位性能瓶颈进行优化

  •  2
     
  •   seraphv3 · 2018-10-10 15:18:15 +08:00 · 6076 次点击
    这是一个创建于 2262 天前的主题,其中的信息可能已经有所发展或是发生改变。

    公司的网站大约有 180 用户使用,从监控工具听云来看,目前性能吃紧,需要优化。但是没有找到是什么导致了现在的性能吃紧,性能瓶颈在什么地方,向各位大神求助。

    目前在 3 台阿里云机器上部署了 3 个 tomcat 实例,用的 nginx 做负载均衡。机器都是 8G 内存,分配了 4G 给 tomcat 的 JVM。网站用到了 mongodb,mysql,redis,3 个 tomcat 用的是同一个数据库。以前出现过 mongodb 性能瓶颈,加了索引之后解决了;还出现过 redis 性能瓶颈导致网站崩溃,切换了阿里云的专用 redis 服务器也解决了;还出现过代码问题导致的 OutOfMemoryError,也优化了。但是现在听云显示的是主要响应时间是在应用层时间上,应用层时间我理解是 CPU 占用的时间,但 CPU 占用率不到 50%,不应该花这么长时间。而且 3 台实例的响应时间统计基本是同步地时间变长变短。看慢请求列表,也是一些普通的不占什么资源的请求。

    问下各位大神有什么优化思路。

    下图是听云截图

    截图

    第 1 条附言  ·  2018-10-11 15:33:05 +08:00
    我还是先看几本书学习下,再进行优化吧。不知道这几本书有帮助没。《 Java 性能优化权威指南》《 Java 性能权威指南》《深入理解 Java 虚拟机》
    第 2 条附言  ·  2018-10-26 17:24:01 +08:00
    今天又出现了一次 tomcat 死掉的问题,死了一台,没有造成太大影响。用 jstack 查看,发现是一个全量刷新 redis 缓存的线程卡住了,卡在把数据转 json 的过程中,估计有五万条多条数据转一个 json 串。而我对 redis 的操作加了 ReentrantReadWriteLock。一个线程锁住了写锁,其它读的线程也阻塞在获取读锁那里,导致越来越多线程挂起,最后操作系统线程调度开销过大,CPU 100%。

    现在优化了,把全量刷新 redis 缓存改为增量式刷新,再看看情况
    37 条回复    2018-10-14 20:38:46 +08:00
    misaka19000
        1
    misaka19000  
       2018-10-10 15:23:13 +08:00   ❤️ 2
    看起来像是数据库的原因,数据库高峰的时候响应时间都 200ms 了,有点慢
    hihipp
        2
    hihipp  
       2018-10-10 15:26:05 +08:00
    看慢事务追踪列表,详情。一般都可以定位到哪个方法慢。
    hiro0729
        3
    hiro0729  
       2018-10-10 15:26:55 +08:00
    不是说阿里云的 io 很捉急么,mysql 直接装在实例上性能不怎么好,也是逼你用云数据库
    seraphv3
        4
    seraphv3  
    OP
       2018-10-10 15:28:15 +08:00
    @misaka19000 左上方的统计图是全部的响应时间,主要的时间是应用层时间

    ![截图]( http://www.classic-text.com/tingyun/tingyun2.png)
    misaka19000
        5
    misaka19000  
       2018-10-10 15:30:02 +08:00
    > 目前性能吃紧,需要优化

    你是怎么判断出来这个现象的?
    seraphv3
        6
    seraphv3  
    OP
       2018-10-10 15:32:43 +08:00
    @misaka19000 主要是看听云的 Apdex 指标,以前平均能达到 0.99 以上,基本是一条直线,现在只有 0.975 ,差的时候 0.95
    liuxu
        7
    liuxu  
       2018-10-10 15:33:23 +08:00
    mongodb 和 redis 尖峰延迟?用的是内网 IP 么,400ms,独出的数据量大了带宽不够?
    gaius
        8
    gaius  
       2018-10-10 15:38:16 +08:00
    180 用户,平均 60 人占一台?
    artist
        9
    artist  
       2018-10-10 15:39:29 +08:00
    什么业务?多大数据量?遇到 redis 性能瓶颈这个判断可能存在误解,初步猜测问题在代码这块。
    seraphv3
        10
    seraphv3  
    OP
       2018-10-10 15:41:57 +08:00
    @liuxu mongodb、redis 都是内网 IP,我还没想到带宽可能有问题,让我检查下
    qcloud
        11
    qcloud  
       2018-10-10 15:48:11 +08:00
    这...........180 用户都这么复杂了咩
    seraphv3
        12
    seraphv3  
    OP
       2018-10-10 15:48:44 +08:00
    @artist 是一个集成了呼叫中心的 CRM 系统,主要是处理名单列表查询、活动统计(活动就是一组名单)、名单呼叫历史查询、工单列表查询等操作,做成多租户的,多的企业有 50000+名单。代码的话我再检查下
    CoderGeek
        13
    CoderGeek  
       2018-10-10 15:50:32 +08:00
    看 slow sql 啥的 是否有不合适的 SQL
    captainjack
        14
    captainjack  
       2018-10-10 16:39:07 +08:00
    用 jstack 看看栈情况,估计很多线程都在 blocking 的状态
    tao1991123
        15
    tao1991123  
       2018-10-10 16:48:51 +08:00
    既然是公司用 就别省钱 把 mongodb,mysql,redis 全部迁出去 用云服务
    artist
        16
    artist  
       2018-10-10 17:11:28 +08:00
    @seraphv3 这个数据量不大,可能 redis 使用方式有问题,或者单 key 数据太大,带宽小。现在还会出现 OOM 么?代码可以看看是否存在大的事务,事务中数据库查询是否存在没索引全表扫描或者一次查询查出了所有数据。
    egfegdfr
        17
    egfegdfr  
       2018-10-10 17:16:58 +08:00
    听你这么说,感觉 sql 这块的问题更大,关注下慢 sql
    seraphv3
        18
    seraphv3  
    OP
       2018-10-10 17:17:25 +08:00
    @captainjack 感谢,学到一个新工具
    seraphv3
        19
    seraphv3  
    OP
       2018-10-10 17:24:25 +08:00
    @artist 现在没有 OOM 了,只是性能不佳,之前 OOM 就是因为统计的时候一次查出了所有数据在内存中统计导致的。感谢
    qq46733
        20
    qq46733  
       2018-10-10 17:25:22 +08:00
    阿里云数据库有个慢日志查看的,看看数据库慢 sql,这个量十有八九是 sql 出了问题
    likuku
        21
    likuku  
       2018-10-10 18:38:30 +08:00   ❤️ 1
    @seraphv3 [是一个集成了呼叫中心的 CRM 系统,主要是处理名单列表查询、活动统计(活动就是一组名单)、名单呼叫历史查询、工单列表查询等操作,做成多租户的,多的企业有 50000+名单。代码的话我再检查下]

    我懂了,很类似我工作的某前司的业务。

    看似客户少,但可能有的客户数据量巨大,且是这种企业工具型应用,在白天工作日很容易出现高峰,尤其早晚上下班高峰,工作日还常遇到处理大量数据的 SQL 长查询。

    实际经验,建议多关注数据库,MySQL 开 slow log 记录慢查询,有针对性优化。

    每客户都是单独库么? MySQL 都是 InnoDB 这种行级锁的现代表么(别觉的我问得傻,因为我遇到过)?
    数据库假若不是云数据库,那么你数据库机器上,数据库文件落地的磁盘 IO 够不够快?是否都是 SSD 的?

    有条件,建议按不同客户优先级(重要性 /付钱多少 /难搞程度) 分到优先级 /性能 不同的 独立数据库机器上。
    likuku
        22
    likuku  
       2018-10-10 18:43:37 +08:00
    #21 补充,之前遇到某新分支业务开发到上线很久都是 MyISAM,虽然都 21 世纪好多年了,还有人默认用它。
    sampeng
        23
    sampeng  
       2018-10-10 18:48:15 +08:00
    看慢 sql。

    应用慢那就要看一下是不是线程堵塞。。这个就很复杂的故事了。。。因为在云上。你的 mysql 装在实例上。。本身阿里云的 io 也是跟屎一样。。。所以说不清是 mysql 问题还是你代码问题。但你还有 redis 缓存。像种种企业应用。应该大部分数据都缓存命中才是。。。
    zealzz
        24
    zealzz  
       2018-10-10 18:49:01 +08:00
    建议你还是做一个性能压测试,基本上能暴露短板,这样可以针对性的优化。以前用的 MySQL 数据都跑到亿的级别了,照样跑很流畅。之前遇到过的问题,大部分都是数据库首先成为瓶颈。这时读写分离、分区、分表实在不行就分库。
    sampeng
        25
    sampeng  
       2018-10-10 18:53:39 +08:00
    redis 使用也要注意。。别存大 hash。或者一次性取一堆。。redis 是单线程的。不然你取的时候其他 client 都得等着。。这也会出现尖峰。

    信息太少。。不好分析。。。
    MeteorCat
        26
    MeteorCat  
       2018-10-10 18:59:39 +08:00 via Android
    htop 看下内存占用情况,是 mysql 负载大还是 java 负载大,3 个 tomcat 访问一个数据库是做 dao 吗?
    seraphv3
        27
    seraphv3  
    OP
       2018-10-10 20:02:58 +08:00
    @sampeng 我们确实存了大的 hash,但是取的时候已经改成了只取 hash 里面的一条数据,这应该是可以的吧?
    yzkos
        28
    yzkos  
       2018-10-10 21:22:03 +08:00
    上面不是有慢事务追踪列表?
    上面的每个都执行高达十几秒,看看是不是慢事务里的请求拉低了 Apdex 指标;
    排查一下慢事务追踪列表里的执行时间是不是正常的;
    dnsaq
        29
    dnsaq  
       2018-10-10 22:54:12 +08:00 via iPhone
    目测是使用不当导致的 不说所有服务单个服务真正会用到极致的人都不多
    dnsaq
        30
    dnsaq  
       2018-10-10 22:55:23 +08:00 via iPhone   ❤️ 1
    主要是开发使用上,感觉和机器配置无关
    metrxqin
        31
    metrxqin  
       2018-10-10 23:11:35 +08:00
    愿意付费优化可以私信我。
    watch
        32
    watch  
       2018-10-10 23:23:13 +08:00 via iPhone
    页面太大了吧 cdn 用上了么
    qfdk
        33
    qfdk  
       2018-10-11 00:27:27 +08:00 via iPhone
    数据库查询咋写的 分页那边不会是 offset 之类的吧……
    akira
        34
    akira  
       2018-10-11 00:40:03 +08:00
    看第一张图 redis 这里有点 问题 啊...
    既然你是用了阿里云的,那就看看 redis 的性能监控,目测带宽数据有惊喜
    lbp0200
        35
    lbp0200  
       2018-10-11 10:39:06 +08:00
    可能一次请求要从 redis 读几个 G 的数据
    sampeng
        36
    sampeng  
       2018-10-11 10:44:05 +08:00
    @seraphv3 这样应该没问题。不要一次性从 redis 取一坨东西。。带宽数据有惊喜。。尤其是事务处理上。。。
    如果事务处理是写事务。加个队列。异步写好了。。。
    cabing
        37
    cabing  
       2018-10-14 20:38:46 +08:00
    180 日活,量很小啊。
    数据库确实有点慢啊。不至于啊。我觉得几十 ms 就了不起了啊。
    如果有 redis,redis 读写应该很快啊。几毫秒。。。
    也可能是 dns,io 或者带宽有问题吧
    可以看看服务器整体有啥问题。cpu,内存,磁盘 io,带宽,做个整体监控。。sar 命令就行。或者装个监控软件
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5217 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 37ms · UTC 01:28 · PVG 09:28 · LAX 17:28 · JFK 20:28
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.