1. 压测端硬件、网络或软件
问题1:域名压测致使大量请求流向外网,并出现流量清洗前端
现象:测试结果显示tps很是低,请求量压测端统计与服务端统计相差很大java
解决思路:mysql
确认压测域名是否走内网IP,ping + 压测域名获取到的ip地址与运维确认是否为内网ip,若不支持ping(腾讯云机器不支持ping)可尝试tracert。nginx
肯定未走内网可能须要运维协助,在入口机器(nginx)配置host将域名指定到某台或多台服务器上。web
问题2:jmeter测试报告显示出现各类异常报错信息,如500、50二、Non Http responsecoderedis
现象:控制台错误请求量增长、测试报告显示相应错误提示、错误算法
解决思路:肯定错误类型,根据错误类型寻找错误真实缘由。spring
Non HTTP response code: java.net.ConnectException,java.net.ConnectException,通常是链接超时(查日志)。从几个方面排查,脚本问题、网络、服务器承受能力到了极限(监控系统资源),并发量超过系统处理能力会出现这种状况(可参考http://confluence.sui.work/pages/viewpage.action?pageId=13182064)sql
问题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,分别设置值为6553四、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参数调优
一、取消飞行记录模式,去除参数(-XX:+UnlockCommercialFeatures -XX:+FlightRecorder)
二、jdk1.8 下取消了-XX:PermSize=500m-XX:MaxPermSize=500m
三、垃圾回收机制改为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消息有堆积
优化点:一、redis用的公共组件,有加锁;二、gain接口会产生两台msg消息,分别丢进两条队列(一条入库,一条调腾讯接口),同步改为异步;(3)一个线程取消息多个线程消费-》改为多个线程取消息多个线程消费
问题9:spdata分发有延时
问题现象:云上的数据向IDC推送数据用到了JMS消息,并发量大,容易延时(已知问题)。
影响范围:理财仅响应运营系统发奖,卡牛和微粒影响了云上的兑换,致使用户体验很差。
解决办法:spdata分发的方案不变,再增长方案:领取时前端已加密串形式保存QQ用户信息,给兑换奖券时用。
问题10:日志优化(经过日志分析不出来)
一、异步写日志文件
二、减小日志打印,例如正常请求仅打印入参和出参
三、kafka+ELK
问题11:spdatad多业务方数据源问题,致使预演并发量时,卡牛和微粒的数据未下发,不能兑换奖券(线上问题)
问题缘由:for循环按业务下推数据,每次先推进理财的;若是理财有下推数据,最后会clear掉dataSource,致使其余业务查询为空;若是理财未下推数据,不会调用clear,正常推送其余业务;
代码以下:
解决办法:dataSource从上文传下来,避免执行clear时,dataSource被清空
规避方法:增长多业务的性能测试场景(跨公司的压测资源和环境受限);
问题12. 业务繁忙(线上问题)
问题缘由:
(1)网络缘由,例如:静态资源文件未放运营商CDN服务器、网络慢或异常;
(2)receive_api未获取QQ:openid(小几率事件),服务端从新请求腾讯接口获取QQ用户openid,生成数字验签错误;
(3)腾讯云问题,联合腾讯压测初步解决。