3.31-3 性能问题

性能测试问题

案例1:某次压力测试,同样并发TPS,但前期性能良好,后期数据库CPU飙升

压测会产生大量级的数据,数据增长会带来性能的损耗

压测数据不合理,导致统一设备 关联多个用户,服务端不做限制的in查询

不合理分页,未做页数limit,导致将数据库新增数据全部查询

案例2:响应时间过长,什么原因怎么分析?

  一般响应时间过长有下面几个原因:

(1)服务器硬件资源cpu,内存,磁盘达到瓶颈,可以使用监控命令排查

(2)网络问题导致,比如丢包,带宽不够等等

(3)线程出现死锁,阻塞等问题可以用jstack查看

(4)中间件比如mq消息队列拥堵排队等

(5)数据库层面sql不够优化,没有索引,联合索引失效等,数据库连接数不够。

案例3:压力测试中TPS一直上不去

这个原因比较多,压测整个链路上任何一个环节有瓶颈或者问题都有可能导致

 首先是压力机压力不够,比如用我们笔记本基本压不到那么高TPS,   所以我们公司有自己的压测平台,分布式集群压测。

(1)网络带宽,单位时间内网络传输数据量过大,超过带宽处理能力

(2)数据库连接数太少,最大连接数不够

(3)Cpu,内存,磁盘硬件资源达到瓶颈

(4)中间件redis也有可能存在瓶颈比如缓存穿透,缓存过期等等

(5)存在大量线程阻塞,线程死锁等

(6)中间件消息队列拥堵  

案例4:数据库CPU高

问题现象:后台指令发送满负荷工作时,数据库CPU高。

问题原因:后台指令发送线程每次对全量查询结果排序,结果集很大,然后取一条记录;索引区分度不高,满负荷执行时;查询频率很高;压测显示,并行发送指令的后台线程越多,数据库CPU越高,效率越低。

解决方法:

去掉ORDER BY,增加索引后,效果不明显。因为结果集大和查询频繁两个问题没有解决,因此考虑使用设计新的方案。

新方案:设计指令发送线程池,生产者线程每台任务服务器只有一个线程,负责查询待发送指令,每次查询50条指令。每条指令包装成一个Runnable对象,放进ThreadPoolExecutor线程池,线程池大小参数设置为100或200。每当线程池满时,生产者停止生产指令,休息15秒后继续。消费者线程即线程池里的线程,参数设置为4,8或12(和不同指令类型的指令数据量成正比)。

改进后的方案,数据库CPU降到10%一下,发送效率单机提升6倍,且可线性扩展任务服务器。

案例5:内存溢出(堆溢出、栈溢出、持久代溢出)

解决思路:1、调整堆内存参数,一般是增加堆内存

    2、减少批处理数据量

案例5:

线程死锁:容量(压力)测试压测一段时间后,报连接超时

解决思路:

1、造成这种现象的原因很多,比如带宽不够,中间件线程池不够用,数据库连接池不够,连接数占满等都会造成连接不上而报超时 错误

2、找到死锁的线程,分析对应的代码

案例6:压测TPS曲线剧烈下降或抖动

问题现象:50并发压测,TPS曲线正常应该是平缓的,波动不大,如果突然出现剧烈下降,并且短时间内无法恢复,则可能存在问题。

问题原因:一般是由于前置或bp的jvm进行垃圾回收,或者日志记录磁盘满导致的。

解决方法:如果不是特别剧烈的波动或者TPS曲线下降后长时间不反弹,则可以忽略该问题。否则,需要分析曲线下降的时刻,系统当时正在发生的事情。可以通过top命令监控当时CPU占用比价高的线程,也可以kill -3 pid杀javacore来查看线程堆栈。

案例7:

CPU高

问题现象:50并发压测,监控工具显示bp、前置CPU占用90%以上。

问题原因:业务处理中存在大量CPU计算操作。

解决方法:采用更高效的算法、数据结构替换原来消耗CPU的代码,或者采用新的设计绕过瓶颈代码,比如查找数据的逻辑,可以把List改为Map,以空间换时间;比如用Json报文替换XML报文,提高传输、解析和打印日志的效率。

导致Cpu计算资源高消耗的代码:报文格式转换、加解密、正则表达式、低效的循环、低效的正则表达式。

排查方法:

压测进行时,使用jvisualvm工具远程连接应用,点抽样器àCPU,点快照生成线程快照。采样一段时间后,抽样器会显示各个方法占用cpu时间,可以针对CPU时间占用高的方法进行优化。

使用tprofiler,jprofiler,OracleDeveloperStudio12.6-linux-x86工具分别分析消耗CPU时间长的方法,以上工具分析结果可能有些差别。针对CPU计算耗时最长的方法进行优化。

案例8:内存泄漏

问题现象:JVM内存耗尽,后台日志抛出OutOfMemeryError异常 ;

问题原因:内存溢出问题可能的原因比较多,可能是全局的List、Map等对象不断被扩大,也可能是程序不慎将大量数据读到内存里;可能是循环操作导致,也可能后台线程定时触发加载数据导致。

解决方法:对于ibmjdk纯java应用,在jvm启动时设置-XX:+HeapDumpOnOutOfMemory Error参数,会在内存溢出时生成heapdump文件。使用ha456.jar工具打开heapdump文件,分析大对象是如何产生的。

当然,在heapdump中对象类型可能只是List这种结构,看不出具体哪个业务代码创建的对象。此时要分析所有的全局对象,列出可疑的List或Map对象,排查其溢出原因。

全局对象、引用的初始化、修改要慎重。建议应用梳理所有可能存放全局对象的代码,统一管控

案例9:打开了太多文件

问题现象:采用合理的并发数压测,交易失败,或后台日志报错:To many open files。

问题原因:

读取配置文件或者业务数据文件后,未关闭文件流;

/etc/security/limits.conf中***打开文件数配置过小。

解决方法:

使用lsof –p pid 命令查看进程打开的文件,如果大部分文件都是同一类型的文件,说明可能未关闭文件流。找到打开文件的代码,关闭文件流即可。

如果不存在未关闭文件流的问题,且业务本身就需要处理大量文件,则修改/etc/security/limits.conf文件如下内容:

* hard nproc 10240

* soft nproc 10240

案例10:

线程阻塞在日志记录上

问题现象:系统响应时间长、通过javacore查看很多线程阻塞在打印日志上。

问题原因:log4j1.x版本较低,性能较差;大报文日志多次输出。

解决方法:

减少无效日志、删除无用日志,减少大日志输出。

升级log4j组件到log4j2,参考log4j2官方文档,配置合理的日志缓冲区,采用高效的Appenders,比如RollingRandomAccessFile。但log4j2仍然采用同步日志,不采用异步日志。因为网银系统日志量较大,异步日志队列很快就满了,如果单条日志存在大报文,还有可能导致内存溢出,因此不适合采用异步日志。如果日志量少(压测产生日志的速度,低于日志写入文件的速度),则可以使用异步日志,大幅提高性能。如果日志量较大,则不建议使用异步日志。

排查方法:

JVM启动参数中增加-XX:+HeapDumpOnCtrlBreak,压测进行时,kill -3 pid 杀几个javacore,使用jca457.jar工具打开并分析。推荐使用该工具,因为该工具可以对所有线程状态进行统计,并生成饼状图,方便查看。

压测进行时,使用jvisualvm获取jvm快照,分析线程堆栈。

案例11、多线程并发问题

问题现象:采用合理的并发数压测,系统出现逻辑错误、交易失败或异常报错。经查是由于对象中变量被异常修改导致。

问题原因:系统中全局对象中的类变量或全局对象,被多个线程修改。

解决方法:排查系统中所有持有全局对象或类变量的代码,检查其全局变量是否可能被多个线程并行修改。

修改方法:

将全局变量转成方法内的局部变量;

对全局变量进行同步控制比如syncronized代码块,或者java.util.concurrent锁

排查方法:并发问题很可能是由全局变量或者对象导致,准确识别全局变量,通过阅读代码找问题。建议应用梳理所有可能存放全局对象的代码,统一管控,或者把所有全局对象放到一个类中,方便管理

案例12:

JMeter Address 占用的问题(jmeter地址占用问题)

搜索之后发现需要在regedit中添加注册表项MaxUserPort,TcpTimedWaitDelay重启一下就可以解决了。

解决方法:

打开注册表:ctrl+r 输入regedit

进入注册表,路径为:\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters

新建DWORD值,(十进制)设置为30秒。名称:TcpTimedWaitDe,值:30

新建DWORD值,(十进制)最大连接数65534。名称:MaxUserPort,值:65534

修改完成后重启生效

《餐馆点餐管理系统——基于Java和MySQL的课程设计解析》 在信息技术日益发达的今天,餐饮行业的数字化管理已经成为一种趋势。本次课程设计的主题是“餐馆点餐管理系统”,它结合了编程语言Java和数据库管理系统MySQL,旨在帮助初学者理解如何构建一个实际的、具有基本功能的餐饮管理软件。下面,我们将深入探讨这个系统的实现细节及其所涉及的关键知识点。 我们要关注的是数据库设计。在“res_db.sql”文件中,我们可以看到数据库的结构,可能包括菜品表、订单表、顾客信息表等。在MySQL中,我们需要创建这些表格并定义相应的字段,如菜品ID、名称、价格、库存等。此外,还要设置主键、外键来保证数据的一致性和完整性。例如,菜品ID作为主键,确保每个菜品的唯一性;订单表中的顾客ID和菜品ID则作为外键,与顾客信息表和菜品表关联,形成数据间的联系。 接下来,我们来看Java部分。在这个系统中,Java主要负责前端界面的展示和后端逻辑的处理。使用Java Swing或JavaFX库可以创建用户友好的图形用户界面(GUI),让顾客能够方便地浏览菜单、下单。同时,Java还负责与MySQL数据库进行交互,通过JDBC(Java Database Connectivity)API实现数据的增删查改操作。在程序中,我们需要编写SQL语句,比如INSERT用于添加新的菜品信息,SELECT用于查询所有菜品,UPDATE用于更新菜品的价格,DELETE用于删除不再提供的菜品。 在系统设计中,我们还需要考虑一些关键功能的实现。例如,“新增菜品和价格”的功能,需要用户输入菜品信息,然后通过Java程序将这些信息存储到数据库中。在显示所有菜品的功能上,程序需要从数据库获取所有菜品数据,然后在界面上动态生成列表或者表格展示。同时,为了提高用户体验,可能还需要实现搜索和排序功能,允许用户根据菜品名称或价格进行筛选。 另外,安全性也是系统设计的重要一环。在连接数据库时,要避免SQL注入攻击,可以通过预编译的PreparedStatement对象来执行SQL命令。对于用户输入的数据,需要进行验证和过滤,防止非法字符和异常值。 这个“餐馆点餐管理系统”项目涵盖了Java编程、数据库设计与管理、用户界面设计等多个方面,是一个很好的学习实践平台。通过这个项目,初学者不仅可以提升编程技能,还能对数据库管理和软件工程有更深入的理解。在实际开发过程中,还会遇到调试、测试、优化等挑战,这些都是成长为专业开发者不可或缺的经验积累
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值