性能调优案例(代码片段)

mingyuewu mingyuewu     2022-12-06     426

关键词:

性能调优案例

时间2021-09-02
环境centos7.6,jmeter,redis,mysql,java应用

文章目录

一、jmeter的命令行使用

举例:

# 以命令行方式运行,执行test.jmx测试脚本,将测试结果保存到result.jtl中
jmeter   -n   -t   test.jmx   -l  result.jtl  
# 指定IP分布式运行
jmeter -n -t test1.jmx -R 192.168.10.25:1036 -l report\\01-result.csv -j report\\01-log.log

jmeter命令输出格式

summary + 6440 in 00:00:21 313.9/s 代表 在21秒内执行了6440个测试用例,平均每秒执行313.9个,即TPS=313.9

6440/21=306.7 ,TPS是怎么计算的?

Avg 平均响应时间,Min 最短响应时间,Max最大响应时间

active:当前在执行的线程数,start:开始执行的线程数,finish:结束的线程数
第一条,in 00:00:21 active 80 代表有80个线程已启动,到第二行 in 00:00:30时active 为100 代表100个线程都已启动

线程数:模拟虚拟用户

请求数:这些虚拟用户发起的请求数量,请求数>线程数

二、JVM调优js、 jmap 、 jstat

(1)官网文档 https://docs.oracle.com/javase/1.5.0/docs/tooldocs/share/jmap.html

(2) Jmap命令

​ Java Virtual Machine Memory Map生成虚拟机的内存转储快照(heapdump)文件。jmap命令可以获得运行中的jvm的堆的快照,从而可以离线分析堆,以检查内存泄漏,检查一些严重影响性能的大对象的创建,检查系统中什么对象最多,各种对象所占内存的大小等等。可以使用jmap生成Heap Dump。

参考文档:https://blog.csdn.net/jiang_zf/article/details/79540234

-heap 显示Java堆详细信息,如使用哪种回收器、参数配置、分代状况等

-histo 显示堆中对象统计信息,包括类、实例数量和合计容量

查看java堆的使用情况

###开启卡关服务:先启动reids,rocketmq,mysql等中间件数据库,再开启卡管应用,查看应用的日志看启动是否正常
[root@iZbp1ecjj2jqnihvrx19piZ ehcServer]# jps     # 查看使用JVM的进程
8027 Jps
7967 WrapperSimpleApp
[root@iZbp1ecjj2jqnihvrx19piZ ehcServer]# jmap -heap   7967
Attaching to process ID 7967, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.231-b11

using thread-local object allocation.
Parallel GC with 2 thread(s)       # gc(垃圾回收)线程默认cpu核心数

Heap Configuration:  #堆内存初始化配置
   MinHeapFreeRatio         = 0    #-XX:MinHeapFreeRatio设置JVM堆最小空闲比率 
   MaxHeapFreeRatio         = 100  #-XX:MaxHeapFreeRatio设置JVM堆最大空闲比率  
   MaxHeapSize              = 1073741824 (1024.0MB)  #-XX:MaxHeapSize=设置JVM堆的最大大小,默认1/4内存大小
   NewSize                  = 357564416 (341.0MB)	 #-XX:NewSize=设置JVM堆的‘新生代’的默认大小
   MaxNewSize               = 357564416 (341.0MB)    #-XX:MaxNewSize=设置JVM堆的‘新生代’的最大大小
   OldSize                  = 716177408 (683.0MB)    #-XX:OldSize=设置JVM堆的‘老生代’的大小
   NewRatio                 = 2		#-XX:NewRatio=:‘新生代’和‘老生代’的大小比率
   SurvivorRatio            = 8      #-XX:SurvivorRatio=设置年轻代中Eden区与Survivor区的大小比值
   MetaspaceSize            = 21807104 (20.796875MB)  
   CompressedClassSpaceSize = 1073741824 (1024.0MB)
   MaxMetaspaceSize         = 17592186044415 MB
   G1HeapRegionSize         = 0 (0.0MB)

Heap Usage:
PS Young Generation
#新生代区内存分布,包含伊甸园区+1个Survivor区
Eden Space:  #Eden区内存分布
   capacity = 284164096 (271.0MB)
   used     = 149041648 (142.13719177246094MB)
   free     = 135122448 (128.86280822753906MB)
   52.44914825552064% used
From Space:
   capacity = 36700160 (35.0MB)
   used     = 36678544 (34.97938537597656MB)
   free     = 21616 (0.0206146240234375MB)
   99.94110107421875% used
To Space:
   capacity = 36700160 (35.0MB)
   used     = 0 (0.0MB)
   free     = 36700160 (35.0MB)
   0.0% used
PS Old Generation
   capacity = 716177408 (683.0MB)
   used     = 152398744 (145.3387680053711MB)
   free     = 563778664 (537.6612319946289MB)
   21.279468229190496% used

26423 interned Strings occupying 2749688 bytes.

(3)调优参数

启动jar应用时,如果不指定堆内存大小,则默认xmx(最大堆内存)是机器内存1/4,gc线程默认cpu核心数,gc算法parallel

初始堆内存 -Xms2500m
最大堆内存 -Xmx3000m
如果服务器上只跑该java应用,可将最大堆内存设为机器内存75%,至少留20%的内存给操作系统
垃圾回收方式USEG1GC jdk8建议使用G1垃圾回收算法

-Xmx3550m   #JVM最大可用内存
-Xms3550m   #设置JVM初始内存为3550m。此值可以设置与-Xmx相同,以避免每次垃圾回收完成后JVM重新分配内存。
USEG1GC    UseParallelGC      #GC的方式。一般用并行GC    https://www.cnblogs.com/yuanzipeng/p/13374690.html
wrapper.java.additional.2=-XX:+UseParallelGC
wrapper.java.addtional.11=-Xms1g
wrapper.java.addtional.12=-Xmx1g

(4)检查调优情况jstat

动态查看:使用jstat统计一下jvm在内存回收中发生的频率耗时以及是否有full gc,使用这个数据来评估一内存配置参数、gc参数是否合理。YGC YGCT FGC FGCT

[root@iZbp1ecjj2jqnihvrx19piZ conf]# jps
16723 Jps
22046 WrapperSimpleApp
[root@iZbp1ecjj2jqnihvrx19piZ conf]# jstat -gc  22046
 S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT   
3584.0 3584.0 2304.0  0.0   342016.0 173818.6  699392.0   257431.9  81944.0 77727.9 9776.0 9054.6    530   17.479   3      1.521   19.001

#S0C:第一个幸存区的大小
#S1C:第二个幸存区的大小
#S0U:第一个幸存区的使用大小
#S1U:第二个幸存区的使用大小
#EC:伊甸园区的大小
#EU:伊甸园区的使用大小
#OC:老年代大小
#OU:老年代使用大小
#MC:方法区大小
#MU:方法区使用大小
#CCSC:压缩类空间大小
#CCSU:压缩类空间使用大小
#YGC:年轻代垃圾回收次数
#YGCT:年轻代垃圾回收消耗时间
#FGC:老年代垃圾回收次数
#FGCT:老年代垃圾回收消耗时间
#GCT:垃圾回收消耗总时间   (多少时间算正常呢?越少越好)
#参考文章:https://www.cnblogs.com/sxdcgaq8080/p/11089841.html

三、Redis调优

1 设置redis能够使用的的最大内存

maxmemory     2g

2 到达最大内存后的替换策略

#如果到达了最大内存,需要设置替换策略,(类比操作系统管理内存空间,LRU、FIFO等算法替换内存)
maxmemory-policy   volatile-lru
#最近最少使用算法,链表实现

当 Redis 内存使用达到 maxmemory时,需要选择设置好的 maxmemory-policy进行对老数据的置换。

(1) noeviction: 不进行置换,表示即使内存达到上限也不进行置换,所有能引起内存增加的命令都会返回error

(2)allkeys-lru: 优先删除掉最近最不经常使用的key,用以保存新数据

(3)volatile-lru: 只从设置失效(expire set)的key中选择最近最不经常使用的key进行删除,用以保存新数据

(4)allkeys-random: 随机从all-keys中选择一些key进行删除,用以保存新数据

(5)volatile-random: 只从设置失效(expire set)的key中,选择一些key进行删除,用以保存新数据

(6)volatile-ttl: 只从设置失效(expire set)的key中,选出存活时间(TTL)最短的key进行删除,用以保存新数据

疑问 key 的过期时间是在代码里设置的吗,过期时间设置为多少合适?如果不设置过期时间的话,感觉allkeys-lru算法比较合适。

选择maxmemory-policy的建议:

(1)在所有的 key 都是最近最经常使用,那么就需要选择 allkeys-lru 进行置换最近最不经常使用的 key,如果你不确定使用哪种策略,那么推荐使用 allkeys-lru

(2)如果所有的 key 的访问概率都是差不多的,那么可以选用 allkeys-random 策略去置换数据

(3)如果对数据有足够的了解,能够为 key 指定 hint(通过expire/ttl指定),那么可以选择 volatile-ttl 进行置换

3 如果业务不需要redis持久化,则关闭

RDB 默认开启,注释掉三行sava即可关闭

AOF 默认关闭 appendonly no

redis关闭持久化后,每个redis请求不用刷盘,可提升性能

四、Mysql优化

调优标准:尽量少读磁盘和跨网络,从计算机系统硬件来看,CPU、内存都不慢,慢的是磁盘和网络。
java应用需要访问数据,数据存放位置
JVM堆内存—>本机redis---->分布式redis集群----->mysql集群缓存区------>mysql磁盘

1 sql语句优化

2 索引优化

3 配置优化

#共有缓存
innodb_buffer_pool_size=3G    # 在oracle中交SGA
innodb_flush_log_at_trx_commit=2
sync_binlog=10
# 线程独有内存    在oracle中叫PGA
join_buffer_size   
sort_buffer_size
read_rnd_buffer_size

(1)innodb_buffer_size

innodb_buffer_size缓存的内容

数据缓存 – 这绝对是它的最重要的目的
索引缓存 – 这使用是的同一个缓冲池
缓冲 – 更改的数据(通常称为脏数据)在被刷新到硬盘之前先存放到缓冲
存储内部结构 – 一些结构如自适应哈希索引或者行锁也都存储在InnoDB缓冲池

innodb_buffer_size设置的大小

在一个独立的只使用InnoDB引擎的MySQL服务器中,根据经验,推荐设置innodb-buffer-pool-size为服务器总可用内存的50%~80%

更改innodb_buffer_size的命令

root身份

mysql> SET GLOBAL innodb_buffer_pool_size=size_in_bytes;

参考链接:https://blog.csdn.net/weixin_41782053/article/details/87269158
或者直接在/etc/my.cnf里设置

(2) innodb_flush_log_at_trx_commit (log_buffer何时写入磁盘内存映射cache)

mysql缓存(log_buffer)------------>磁盘内存映射(cache)----------------->磁盘

日志写入磁盘要经过两个缓存,一个是mysql自己的log_buffer,另一个是操作系统的磁盘内存映射缓存(磁盘和内存之间的cache)

mysql可以 调用 flush 主动将log buffer 刷新到磁盘内存映射,也可以调用 fsync 强制操作系同步磁盘映射文件到磁盘。还可以同时调用 flush + fsync, 将缓存直接落盘。

innodb_flush_log_at_trx_commit = 0 就是每秒调用 flush + fsync ,定时器Mysql自己维护。Mysql崩溃会丢失1s数据

innodb_flush_log_at_trx_commit = 1 就是实时调用 flush + fsync ,没法批处理,性能很低。

innodb_flush_log_at_trx_commit = 2 就是实时flush ,定时 fsync,定时器OS维护。操作系统崩溃会丢失1s数据

参考链接:https://blog.csdn.net/u010833547/article/details/109293213

(3) sync_binlog=0|n(磁盘内存映射何时写入磁盘)

sync_binlog=0 由操作系统决定什么时候写入,性能最好,风险最大。

​ 当事务提交之后,MySQL不做fsync之类的磁盘同步指令刷新binlog_cache中的信息到磁盘,而让Filesystem自行决定什么时候来做同步,或者cache满了之后才同步到磁盘。

sync_binlog=n 每当提交n次事务后,mysql调用fsync将磁盘内存映射写入磁盘。

当每进行n次事务提交之后,MySQL将进行一次fsync之类的磁盘同步指令来将binlog_cache中的数据强制写入磁盘。

https://www.cnblogs.com/jpfss/p/10772952.html

五、报错及总结:

1 jmeter执行测试用例时,测试用例错误率高

可能是服务器资源不足。

2 压测的时候,nginx的日志access.log没有变化

​ df -h 磁盘满了, 或者nginx配置中没有开启日志,或者用户请求没有经过nginx 。

3 了解用户请求的路径

例如:

用户发出request请求------->Nginx-------->java应用------->redis缓存---------->mysql数据库

用户发出request请求-------->java应用---------->redis缓存----------->mysql数据库

4 压测执行流程

启动服务:启动中间件、数据库,再启动服务
检查服务:查看应用的日志验证启动成功
执行压测
查看请求的响应时间:比如在ngixn日志中加人$request_time
查看中间件、数据库的状态:比如jvm的GC次数时间,mysql的慢日志
查看系统硬件指标:CPU利用率,内存利用率,查找到较消耗资源的进程。

六、总结

1 数据库调优原则

(1)SQL语句调优最为重要,索引,join连接,子查询
(2)数据库参数设置
(3)硬件配置

2 响应时间

研发人员写完业务逻辑代码后,测试该业务的响应时间,一般需在50ms以内,复杂业务在100ms以内。在生产环境中,加上网络传输时间,请求的排队时间等,整个响应时间就会变长。

3 cache与buffer

buffer
用于网络缓存区,减小短期突发I/O事件,起到流量整形的作用,把突发的大数量小规模的I/O整理成平稳的小数量较大规模的I/O。
写1k 写1000次
写1M,写1次
当网络收发较多时,使用的buffer数量较多,在top 和 free命令中可以看到
cache
CPU和内存之间的设备 ,弥补高速设备和低速设备之间速度不匹配时的一种折中策略 (内存和磁盘之间也有缓存)
当读写磁盘较多时(如数据库,写日志),cache使用量较大。

假定以后存储器访问变得跟CPU做计算一样快,cache就可以消失,但是buffer依然存在。比如从网络上下载东西,瞬时速率可能会有较大变化,但从长期来看却是稳定的,这样就能通过引入一个buffer使得OS接收数据的速率更稳定,进一步减少对磁盘的伤害。

4 http长连接与短连接


HTTP协议的长连接和短连接,实质上是TCP协议的长连接和短连接

jvm性能调优实战篇(代码片段)

????????关注后回复 “进群” ,拉你进程序员交流群????????作者丨黎杜来源丨黎杜编程这一篇是JVM的调优实战篇,内容如下,包括常用的调优工具本地的和线上的,并且有案例结合使用来讲解,然后就是一些常... 查看详情

day814.电商系统表设计优化案例分析-java性能调优实战(代码片段)

电商系统表设计优化案例分析Hi,我是阿昌,今天学习记录的是关于电商系统表设计优化案例分析。如果在业务架构设计初期,表结构没有设计好,那么后期随着业务以及数据量的增多,系统就很容易出现瓶颈... 查看详情

四:jvm调优与常见异常处理方案(代码片段)

...面的文章里面有介绍!接下来我们通过一个案例来调整jvm性能。一:调优案例:  1.1编写demoimportjava.text.DecimalFormat;/**-XX:+PrintGC   GC回收的时候打印相关日志-XX:+UseSerialGC串行回收-XX:+PrintGCDetails 查看详情

linux性能调优总结(代码片段)

系统性能一直是个热门话题。做运维这几年也一直在搞性能调优,写这个文章也算是对工作的总结。讲调优第一步是,要讲为什么要调优?也就是系统分析,分析还需要有指标,做好性能监控的情况下,看到确实需要调优才能进... 查看详情

独一无二的「mysql调优金字塔」相信也许你拥有了它,就再也不用为数据库性能发愁(代码片段)

文章目录开发俏皮话笔者瞩望技术金字塔技术梗概研发成本角度技术可行性和效果角度调优白皮书业务需求和业务架构SQL技术调优调优的思路发现问题(慢SQL的优化和分析)发现慢SQL以及查询日志使用方式-修改MySQL服务... 查看详情

hbase性能调优案例

hbase性能调优案例1、人员-角色 人员有多个角色 角色优先级 角色有多个人员 人员删除添加角色 角色可以添加删除人员 人员角色删除添加 设计思路person表rowkeycf1-人员基本信息 cf2-角色列表pidcf1:pname... 查看详情

性能测试常见调优(代码片段)

在性能测试过程中,最重要的一部分就是性能瓶颈定位与调优。而引发性能瓶颈的原因是多种多样的,在之前的博客:常见的性能测试缺陷有进行介绍。这篇博客,来聊聊性能测试过程中的一些注意事项,以及常见的一些性能缺... 查看详情

spark常规性能调优(代码片段)

 1.常规性能调优一:最优资源配置Spark性能调优的第一步,就是为任务分配更多的资源,在一定范围内,增加资源的分配与性能的提升是成正比的,实现了最优的资源配置后,在此基础上再考虑进行后面论述的性能调优策略... 查看详情

day776.如何制定性能调优策略-java性能调优实战(代码片段)

如何制定性能调优策略Hi,我是阿昌,今天学习记录的是关于如何制定性能调优策略。面对日渐复杂的系统,制定合理的性能测试,可以提前发现性能瓶颈,然后有针对性地制定调优策略。总结一下就是“测试... 查看详情

day775.如何制定性能调优标准-java性能调优实战(代码片段)

如何制定性能调优标准Hi,我是阿昌,今天开启一个新的篇章,学习关于Java性能调优实战,那今天学习的是关于如何制定性能调优标准的内容。一个朋友,有一次说,公司的系统从来没有经过性能调优࿰... 查看详情

hbase性能调优_表设计案例

2017年2月9日,星期四hbase性能调优案例1、人员-角色 人员有多个角色 角色优先级 角色有多个人员 人员删除添加角色 角色可以添加删除人员 人员角色删除添加 设计思路 person表rowkeycf1-人员基本信息&nb... 查看详情

性能调优调优的常见思路和方法(代码片段)

...和调优?在这里提供一些可实践、可借鉴、可参考的性能调优套路,即:如何在众多异常性能指标中,找出最核心的那一个,进而定位性能瓶颈点,最后进行性能调优以下会按照代码、CPU、内存、网络、磁... 查看详情

性能调优一次监控数据错误的性能调优经历(代码片段)

...,qps一直卡在1w,但是从各种监控和分析并未找到性能瓶颈,最后发现竟然因为数据库cpu监控不准备误导,特此记录整个调优的过程一、源码分析回调接口源码性能分析:1次redis查询2次db操作,其中1次查询... 查看详情

一文教会你数据库性能调优(附某大型医院真实案例)

原文:一文教会你数据库性能调优(附某大型医院真实案例)前言 微软工程师的一个工程师曾经对性能调优有一个非常形象的比喻:剥洋葱。我也非常认可,让我们来一层一层拨开外面它神秘的面纱。  六大因素下面... 查看详情

fastdfs性能调优knowhow(代码片段)

FastDFS性能调优本篇文章转载于FastDFS作者余庆大佬的FastDFS分享与交流公众号。众所周知,软件性能调优不是一撮而就的事情,它是一个反复磨合的过程。下面介绍FastDFS几个性能调优相关的重要参数,供大家参考。1.最... 查看详情

day778.正则表达式问题-java性能调优实战(代码片段)

正则表达式问题Hi,我是阿昌,今天学习记录的是关于正则表达式问题。String对象优化,提到了Split()方法,该方法使用的正则表达式可能引起回溯问题,这次就深入了解下开始之前,先来看一个案例。在一... 查看详情

性能测试常见瓶颈分析及调优方法(代码片段)

在性能测试过程中,最重要的一部分就是性能瓶颈定位与调优。而引发性能瓶颈的原因是多种多样的,在之前的博客:常见的性能测试缺陷有进行介绍。这篇博客,来聊聊性能测试过程中的一些注意事项,以及常见的一些性能缺... 查看详情

day820.抢购活动性能瓶颈调优-java性能调优实战(代码片段)

抢购活动性能瓶颈调优Hi,我是阿昌,今天学习记录的是关于抢购活动性能瓶颈调优。每年的双十一都是很多研发部门最头痛的节日,由于这个节日比较特殊,公司一般都会准备大量的抢购活动,相应的瞬时高... 查看详情