码迷,mamicode.com
首页 > 其他好文 > 详细

性能问题汇总

时间:2018-12-07 21:22:53      阅读:548      评论:0      收藏:0      [点我收藏+]

标签:红包   不能   flight   算法   高峰   实时   api   响应   accept   

1. 压测端硬件、网络或软件

问题1:域名压测导致大量请求流向外网,并出现流量清洗

现象:测试结果显示tps非常低,请求量压测端统计与服务端统计相差很大

解决思路:

确认压测域名是否走内网IP,ping + 压测域名获取到的ip地址与运维确认是否为内网ip,若不支持ping(腾讯云机器不支持ping)可尝试tracert。

确定未走内网可能需要运维协助,在入口机器(nginx)配置host将域名指定到某台或多台服务器上。

问题2:jmeter测试报告显示出现各种异常报错信息,如500、502、Non Http responsecode

现象:控制台错误请求量增加、测试报告显示相应错误提示、错误

解决思路:确定错误类型,根据错误类型寻找错误真实原因。

Non HTTP response code: java.net.ConnectException,java.net.ConnectException,一般是连接超时(查日志)。从几个方面排查,脚本问题、网络、服务器承受能力到了极限(监控系统资源),并发量超过系统处理能力会出现这种情况(可参考http://confluence.sui.work/pages/viewpage.action?pageId=13182064)

问题3:jmeter Jvm分配内存不足导致内存溢出

现象:控制台出现报错,出现OutOfMemoryError

解决思路:

Windows中对应的文件路径:Jmeter_Home/bin/jmeter.bat

set HEAP=-Xms512m -Xmx512m

set NEW=-XX:NewSize=128m -XX:MaxNewSize=128m

Linux下对应文件路径:Jmeter_Home/bin/jmeter

HEAP=-Xms512m -Xmx512m

NEW=-XX:NewSize=128m -XX:MaxNewSize=128m

通常就meter默认的HEAP -Xms512:初始化内存大小,-Xmx512m:最大堆内存。需要增加内存的时候需要注意

- 一般会将-Xms和-Xmx两个值配置为相同值,目的是为了能在java的GC完成后堆内存不需要重新分隔计算堆区大小而浪费资源

- -Xms和-Xmx两个值修改的值一般需要为512的整数倍

- -Xmx不要超过物理内存的50%,超出可能会导致jmeter变慢

- 当脚本执行过程中出现内存溢出outfmenmory错误,先尝试增加增加HEAP的-Xms和-Xmx

- JDK32位的电脑Xmx不能超过1500m,最大1378m.否则在启动Jmeter时会报错

- -XX:NewSize:新生代初始内存大小,该值一定要小于—Xms

- -XX:MaxNewSize:新生代可被分配的内存的最大上限,这个值应该小于-Xmx的值,因为新生代占内存来自整个堆内存通常设置为-Xmx的三分之一

- jvm在执行GC时,会停止工作。MaxnewSize的增大,可以降低GC频率

问题4: 端口被占用

现象:并发6000次/s,错误率高达66.89%

错误日志:Non HTTP response code:java.net.BindException,Non HTTP response message: Address already in use

原因:Jmeter windows压测环境:Windows Server 缺失MaxUserPort和TcpTimedWaitDelay;限制了tcpip最大连接数和响应时间

解决办法:注册表HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/ Services/TCPIP/Parameters;添加MaxUserPort和TcpTimedWaitDelay,分别设置值为65534、30,以增大可分配的tcp连接端口数、减小处于TIME_WAIT状态的连接的生存时间

 

2. 服务器硬件、网络

问题1:压测方式使用的是域名压测,走的外部网络,所以压测压力未能如预期一样对目标服务器施压,导致TPS非常低,服务器各种资源消耗也很小。

现象:使用单台压测机器分别进行了100、500、1000进程压测,500个线程的时候tps只有180-200,再增加压力Tps上不去。

解决思路:一开始以为服务器连接数有问题,修改Tomcat最大连接数无效果。最后统计压测端请求量与被测服务器接收请求量相差比较大

解决方式:网络入口配置host/dns的形式将指定域名的请求全部指向测试服务器(对应IP)

问题2:原有集群到达最大极限,TPS达到280左右就出现CPU适应过高的情况

现象:2台web和4台service在调整配置、代码优化出现瓶颈,使用单台压测机器分别进行了100、500、1000进程压测,500个线程的时候tps达到280位最高并发,90%响应时间最小而且CPU等资源正常,增加并发数到1000后tps降低、响应时间增加CPU使用率>70%

解决方法:增加集群机器

3. 中间件

问题1:Nginx入策略配置不平均,后端4台服务器负载不均衡,导致压测时其中一台cpu使用率远远高于其他3台

解决:优化Nginx轮训策略,默认使用的轮训算法修改成安权重分配

问题2:Nginx入口未开启长连接,导致TPS上不去

现象:增加并发数,tps、响应时间无太大增长,服务器资源消耗都在正常范围内,TPC连接数中出现大量time-wait,tomcat已开启长连接配置,可以确定是入口长连接配置没生效

- keepalive_timeout 20s;  #一个keepalive 连接被闲置以后还能保持多久打开状态

- keepalive_requests 1000;  #一个客户端可以通过一个keepalive连接的请求次数。

 

问题3:Tomcat连接处瓶颈,导致高并发时出现接口超时

现象:500线程组并发的时候,服务端日志出现大量超时提示,排查Tomcat线程数配置的时候发现maxThreads(线程池中最大活跃线程数)为100。

解决:修改maxThreads、accept-count为500后错误解决

- maxThreads:最大请求进程数,默认设置为200,该值设置应该考虑实际情况,当

请求进程数达到最大值时,一般会出现错误提示:SEVERE: All threads (150) are currently busy, waiting. Increase maxThreads (150) or check the servlet status

- accept:可接队列长度,与maxThreads对应,当达到maxThreads后进入等待队列。而等待队列数达到最大值后,再有新请求后就会出现refuse connection(拒绝请求)

 

 

问题4:. 502 Bad Gateway和504 Gateway Time-out

问题定位:tomcat的参数配置问题

解决办法:调整tomcat配置文件server.xml的配置:主要是最大线程数、最大建立连接数和最长连接时间。

问题扩展:Nginx或腾讯云LB代理模式下后端tomcat服务器出现问题引起的。首先,检查Nginx/腾讯LB或者tomcat的配置参数;其次,检查tomcat应用服务器的内存、CPU和代码BUG导致的。服务端栗子:方法内部RPC 调用,并发大,方法可用率下降,同时调用次数也会急剧上升。系统外部服务的接入层,对接逻辑容器时,应该添加缓冲队列,最好异步。

问题5:未开启长连接

- keepAliveTimeout=300000 <!--没有请求保持长连接的时间ms -->

- maxKeepAliveRequests=50000 <!--长连接能保持的请求数 -->

 

问题6:dubbo参数优化

现象:随着压测并发线程数递增,tps未能如预期中同步正向增长,达到峰值出现一定的下降。在调整了Tomcat配置参数后进一步优化其他中间件配置

dobbo:protocol-服务提供者协议配置:

- name :协议名称

- port :dubbo协议默认端口为20880,如果配置为-1或没配置port,则会分配一个没被占用的端口

 

本次调优主要关注一下内容:

- heartbeat :心跳间隔,对于长连接当物理层断开(如拔网线,TCP的FIN消息未能及时发送,对方收不到断开事件此时就需要心跳检查连接是否断开)

- dispatcher :协议的消息派发方式,用于指定线程模型,比如:dubbo协议的all, direct, message, execution, connection等

- threadpool : 默认fixed,线程池类型,可选:fixed/cached

- threads : 服务线程池大小,默认值为100

 

dubbo:reference-服务消费者引用服务配置:

本次性能优化主要关注内容

- connections :对每个提供者的最大连接数,rmi、http、hessian等短连接协议表示限制连接数,dubbo等长连接协表示建立的长连接个数

- timeout :服务方法调用超时时间(毫秒),缺省使用<dubbo:consumer>的timeout。

 

问题7:JVM优化

现象:TPS每隔段时间就降为0

 

问题定位:(1)监控tcp的连接数,等待数;(netstat -an |grep 6222 | awk ‘/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}‘)(2)查看服务端FULL GC的次数(过多,FULL GC会导致所有线程)

解决办法:JVM调优+ tomcat参数调优

1、取消飞行记录模式,去除参数(-XX:+UnlockCommercialFeatures -XX:+FlightRecorder)

2、jdk1.8 下取消了-XX:PermSize=500m-XX:MaxPermSize=500m

3、垃圾回收机制改成G1模式(堆内存被划分为固定大小的多个区域,存活的对象从一块区域转移到另一块区域,这样可以进行垃圾回收的同时不停止其他应用程序线程)

 

JVM的常用参数如下:

-Xms设置初始化堆的最大值

-Xmx 设置堆的最大值

PS:-Xms和-Xmx一般是相同的,可以减少Full GC的频率,最大可以到服务器总内存的80%

-Xmn 设置年轻代的大小(年老代=最大值-年轻代),一般为最大值的1/3左右。

 

问题8:java 启动脚本优化

 

 

4. 数据库、缓存等

问题1:DB 优化

(1)优化sql,尽可能少使用join、or 语句,select 出来的字段是必需的字段。

(2) 优化索引,让每条select 都走索引

(3) 设置连接池的最大连接数,设置为10000/14 = 700, (10000 为项目使用的mysql 最

大连接数,14 为机器数)

(4)尝试测试不同的连接池,选择性能最佳的,如图4 为数据库连接池性能测试,最

终确定选择hikari。

(5)不使用数据库事务,因为数据库操作代码都在消费者中,在代码中做幂等性。

查询一条语句性能测试(ms)

 

问题2:Redis优化

1、优化redis 存储数据结构

将db 中的数据load 保存为redis 的hash 结构(全表保存),根据业务优化redis 存储

结构,减少redis 查询次数(例如将phone 和券code 的领取状态单独存储)。

2、redis cpu为单核,进行分片处理

大量查询会成为严重短板,通过hash 值进行分片处理,因为项目不存在热点key 的问

题。优化过后redis 能够承受的量是之前的3 倍。

3、设置redis最大连接数

Redis 最大连接数设置为:3*10000/14 = 2100(这里乘以3 是因为微利项目有三台redis)

问题3:mq 优化

1、优化mq 消息

消息体一般为redis key,可以去redis 拿取数据,优化消息存储大小。按功能不同,拆

分多个队列,加快单逻辑处理速度,微利项目根据业务拆分为5 个队列。

2、加快消费者消费速度

增加消费者数量为20 个,根据下游(DB、业务方)TPS 多次测试得出,可以利用消费者数

量控制下游的负载。

增加消费者预读取数据数量为50 个,从而减少网络请求次数。

优化消费逻辑,完善幂等操作(解决消息重复消费问题),db 操作,业务查询操作。

问题4:Redis连接池瓶颈

优化后的配置:

redis.pool.maxTotal=5000

redis.pool.maxIdle=100

redis.pool.minIdle=50

关键参数说明:

maxTotal:资源池中最大连接池,默认值8

- 最大连接数的配置需要结合实际情况进行调整,而考虑的关键因素包括:

- 业务要求Redis达到的并发量

- 客户端执行命令时间

- Redis资源:如应用个数*maxTotal不能超过Redis的最大连接数

- 资源开销:控制空闲连接,尽量使连接池的频繁创建、释放造成不必要的开销

 

例如:

假如一个命令的平均耗时是1ms,一个连接的QPS(Redis每秒执行指令数)大约1000,而业务要求QPS(每秒执行请求数)是50000。

理论上资源池最大连接池设置应该为50000/1000=50个,但是实际设置上可以比理论值稍大。需要注意的是该值不是越大越好,一是连接太多需要占用客户端和服务端更多资源另一个是Redis假如出现阻塞资源池再大也没作用。

maxIdle:资源池允许最大空闲的连接数,默认值8

minIdle:资源池确保最少空闲的连接数,默认值0

- maxIdle:实际上才是业务需要的最大连接数,该值不能过大(不能大于maxTotal)或过小(过小会导致新增Redis连接开销),而minIdle是为了控制空闲资源监测

 

备注:以上均参考自https://yq.aliyun.com/articles/236383

问题5:DataSource参数优化

spring.datasource.initialSize=10

spring.datasource.minIdle=10

spring.datasource.maxActive=200

spring.datasource.maxWait=60000

- initialSize,连接初始值,连接池启动时创建的连接数量的初始值

- maxActive,连接池的最大值,同一时间可以从池分配的最多连接数量,0时无限制

- maxIdle,最大空闲值.当经过一个高峰时间后,连接池可以慢慢将已经用不到的连接慢慢释放一部分,一直减少到maxIdle为止,0时无限制

- minIdle,最小空闲值.当空闲的连接数少于阀值时,连接池就会预申请去一些连接,以免洪峰来时来不及申请

问题6:领券接口gainTPS 2W/s达到瓶颈

问题现象:6台tomcat服务器+3台redis-cache+2台redis-MQ的TPS仅有2W/s,和理论值6k(单台tomcat的最大值)有差距。

问题定位:(1)增加一台redis-cache,TPS没有改观,初步断定redis-cache存在瓶颈。(2)代码分析:发现gain接口里面有大量的increment操作;热点key避免产生瓶颈落在不同的redis上,但increment时所有的机器都来竞争操作这个key,造成瓶颈。(3)查看redis的监控,发现4台redis-cache中有1台的CPU达到100%,其他3台都在80~90%,形成木桶效应。

解决办法:increment主要是为了实时统计领券量,并显示在看板上方便监控数据。非核心业务,可以去掉increment操作,改成通过elk日志统计。

 

问题7:热点key达到瓶颈

典型的瓶颈问题:并发量大时,操作同一个key(热点key),hash的方式可能会落在同一台redis服务器,达到单台redis服务器的瓶颈。

存在问题的场景:理财市场登录预热(除夕红包活动开始前把所有开户信息加载到缓存中)

解决办法:对热点key进行加工和计算。理想的情况下,集群中有N个缓存节点,那么加工后的key也应该有N个。

问题8:Jms消费慢

问题现象:压测gain接口,jms消息有堆积

优化点:1、redis用的公共组件,有加锁;2、gain接口会产生两台msg消息,分别丢进两条队列(一条入库,一条调腾讯接口),同步改成异步;(3)一个线程取消息多个线程消费-》改成多个线程取消息多个线程消费

问题9:spdata分发有延时

问题现象:云上的数据向IDC推送数据用到了JMS消息,并发量大,容易延时(已知问题)。

影响范围:理财仅响应运营系统发奖,卡牛和微粒影响了云上的兑换,导致用户体验不好。

解决办法:spdata分发的方案不变,再增加方案:领取时前端已加密串形式保存QQ用户信息,给兑换奖券时用。

 

问题10:日志优化(通过日志分析不出来)

1、异步写日志文件

2、减少日志打印,例如正常请求仅打印入参和出参

3、kafka+ELK

 

问题11:spdatad多业务方数据源问题,导致预演并发量时,卡牛和微粒的数据未下发,不能兑换奖券(线上问题)

问题原因:for循环按业务下推数据,每次先推动理财的;如果理财有下推数据,最后会clear掉dataSource,导致其他业务查询为空;如果理财未下推数据,不会调用clear,正常推送其他业务;

代码如下:

 

 

解决办法:dataSource从上文传下来,避免执行clear时,dataSource被清空

规避方法:增加多业务的性能测试场景(跨公司的压测资源和环境受限);

问题12. 业务繁忙(线上问题)

问题原因:

(1)网络原因,例如:静态资源文件未放运营商CDN服务器、网络慢或异常;

(2)receive_api未获取QQ:openid(小概率事件),服务端重新请求腾讯接口获取QQ用户openid,生成数字验签错误;

(3)腾讯云问题,联合腾讯压测初步解决。

 

性能问题汇总

标签:红包   不能   flight   算法   高峰   实时   api   响应   accept   

原文地址:https://www.cnblogs.com/lynnetest/p/10084208.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!