【性能调优】堆外内存溢出

在工作中类似死循环的案例普通测试时测不出来的,一旦项目上线,会爆出很多雷,推荐使用Jmeter压测工具,它可以测出两种类型错误:内存泄露,并发与同步。
mac笔记本安装Jmeter:

brew install jmeter //事先安装homebrew才可使用此命令
open /usr/local/bin/jmeter  //打开JMeter

压测关注几个指标:
HPS:点击率
TPS:一个完整的业务流程,不同于数据库事务
QPS:Query Per Second 每秒查询率,每秒响应请求数
吞吐量:单位时间内处理请求的数量
响应时间

以下是测试www.baidu.com的接口情况,设置200个线程:处理请求最少6ms,最长371ms,吞吐量达到1520.9/s,性能确实不错。
【性能调优】堆外内存溢出_第1张图片
压测项目接口列表如下:
【性能调优】堆外内存溢出_第2张图片
由此推出:
单独网关服务,nginx,简单服务,吞吐量都很高,可是通过nginx代理到网关,然后网关路由到服务,吞吐量明显下降,可见调用链路越长,中间件越多,对性能影响越大。
性能优化从业务一般考虑如下几个方面:
1、DB(考虑sql加索引,sql优化)
2、模板渲染速度(thymeleaf线上要打开缓存,开发关闭)
3、静态资源(nginx动静分离)
4、visualvm查看GC情况,如果GC次数过多证明分配内存偏小
5、业务优化(优化掉频繁查库的操作)
6、加入redis缓存

在做到第6步的时候,发生堆外内存溢出
【性能调优】堆外内存溢出_第3张图片
查看原因,发现springboot在2.0后默认使用lettuce操作redis客户端,它使用netty通信,lettuce的bug导致堆外内存溢出,底层实现是只要有操作,会统计内存使用量,操作完会decrement减内存,可能是lettuce客户端在减内存的过程出错。
【性能调优】堆外内存溢出_第4张图片
对这个问题调节-Xmx大小不起作用,而且如果netty没指定堆外内存,默认使用-Xmx,所以一旦出现问题,就算调大-Xmx也总会到堆外内存溢出的地步。所以我们不能用io.netty.maxDirectMemory只修改堆外内存大小。
解决方案:
1、升级lettuce客户端
2、排除lettuce依赖,使用jedis

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
    <exclusions>
        <exclusion>
            <groupId>io.lettuce</groupId>
            <artifactId>lettuce-core</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
</dependency>

总结:
不破不立,任何新事物的引入必然导致新问题的发生,这是规律,引入redis还会存在其他的问题,究竟如何,我们下篇博客再见!

你可能感兴趣的:(性能调优)