美文网首页
图片验证码事故总结

图片验证码事故总结

作者: 40ab6525bf35 | 来源:发表于2016-10-24 17:32 被阅读140次

    事故描述

    2016.10.22.09.30左右验证码无法显示,一直超时。初步调查发现2016.10.21日晚上10点已经出现此问题。加上往前几天内也发现了图片验证码服务变慢,偶尔超时的现象。但是服务器一直运行,未出现宕机。

    事故原因

    最终调查发现,是因为图形验证码服务器中缓存的10000张图片导致了内存过多占用(>90%),服务器实际的请求处理能力变弱。之前2个多月的运行没有暴露是因为图片验证码用量小。最近用量稍微增大后,就会出现此问题。

    事故分析

    一开始考虑是并发量超过处理能力导致服务器变慢,于是在本地进行了压测,发现增大线程确实可以增大QPS,然而忽略了JVM运行参数,因此结论并不准确。
    后来统计Nginx访问量后发现,接口调用在正常值范围内,并不多。

    • 查看线上日志后,发现了heap space的OOM错误,但是并不确定是请求拥塞还是其他原因。
    • 在本地使用和线上相同的JVM参数后再进行压测,由于生成图片验证码池需要一定时间,所以长时间压测后发现出现相同错误。参数中配置了dump OOM。
    • 使用MAT工具对dump文件进行分析。以下是MAT推荐分析结果。
    Overview
    • 继续查看Histogram:
    Histogram
    • 发现BufferImage占用了近470M内存(默认启动参数里设置的是500M)。Int数组为像素数组。验证码池刚好占用了91%,并没有完全占满。所以具备一定服务能力,也是为什么之前运行2个月都没有暴露的原因。不过请求数量变多,按道理会触发消耗图片验证码,反而是释放内存才对,确实,所以上述验证码对象并没有到达1万,dump前肯定有一定的消耗,但是由于剩余内存已经完全不够当时请求处理需要的内存,所以请求处理线程无法创建,请求一直积压导致timeout。 请求线程需要内存,同样也会释放内存,每0.5秒触发消耗验证码,但若是0.5秒内进来的请求所需的内存大于省下的内存,就会造成OOM。由于验证码对象个数并没有超过10000,所以初步断定不是内存泄漏导致。但是还需要进一步排除。

    • 在本地分别对单独循环生产验证码逻辑和生成到验证码池做测试,发现后者在内存一定的情况下,确实会引起OOM,前者并不会,排除内存泄漏。

    • 把JVM的 Xmx参数改为800M后,长时间压测没有影响系统稳定性,佐证了结论。

    事故处理

    调整JVM内存大小或者减小图片验证码池大小。目前一方面稍微增大了JVM内存,并且合理的设置了图片验证码大小。

    事故总结

    之前只是通过最终网页展示的图片大小(<5KB)毛估了1万张图片的占用量(约50M),所以认为对内存需求并不大,事实是,每张图片对应的内存对象平均50KB左右(包括无法GC的直接或者间接强引用对象)。当时得出10000张的结论也没有经过科学计算,也是毛估。现在对其进行分析,得到了如下公式:
    S = T3/T2 - T3/T1
    其中:
    S 为验证码池大小
    T1 为生成到验证码池的周期
    T2 为从验证码池消费验证码的周期
    T3 为最大连续高峰服务时间(S值能保证这段时间内不用临时生成新的图片验证码而浪费CPU)
    (时间单位均为s)
    巧的是验证码池刚好接近500M占用,但是并不完全占用,所以小量运行没有运行就出错,而且后台生成到池子的速度也很慢,所以短期高并发压测也并不会出现异常。总之因为很多巧合,图片验证码系统侥幸运行至今。在设计系统的时候,还是要多一点科学的精打细算。

    相关文章

      网友评论

          本文标题:图片验证码事故总结

          本文链接:https://www.haomeiwen.com/subject/qeyluttx.html