项目分为:
联机组,负责与各交易来源的交易,进行接口开发,信息交互;
批量组,对联机组做出的数据,进行处理,已经日志、等相关业务、技术api等调用;
管理台,对数据库表的整理查询,以及相关技术的便捷开发等;
就拿这次参与的项目来说,甲方对项目重要程度、项目类型震荡型等因素考虑下,选择抽取了不同的指标进行项目非功能技术压测,分为:
1:脚本组:脚本开发老师,和项目开发老师沟通,讨论,各压测交易,怎么样合理的以脚本的方式,对每支交易做出参数话数据,之后以jmter发出交易,之后提交压测组进行压测性能,jmter不能支持太大的性能,以另一个工具进行性能接口压测;
2:联机性能压测组:对联机交易的整理功能压测,压测整个交易链路下的各配置,是否正确,符合指标规范;同时负责对管理台交易的压测(接口少);
3:批量性能压测组:对批量组交易的整体功能压测,压测数据处理、等相关业务;
4:环境组:负责整个非功能环境的服务维护、服务资源监控、压测出现问题,,提供工具进行分析问题,
例如出现位置响应时间突刺问题、内存12小时稳定增长问题,搭建监控探针项目,监控服务器整体资源、线程栈、堆内存、网络、等资源情况,
也负责非功能环境服务f5IP资源等;
5:公共执行组:对项目整体的测试,例如、超时时间、日志、启动时间等测试;
也负责数据库相关指标测试;
6:其余各组,等各dbs、系统管理员等人员提供帮助;
下面展示一些常用的命令、和优化方式:
-- 数据库最大连接数:
select value from v$parameter where name = 'processes';
或服务器查询:
show parameter process'
其中,process 10000(最大连接数)
-- 查询当前连接数
select count(*) from v$pocess
-- 查看阻塞进程,关闭
select * from v$session t1,v$locked_object t2 where t1.sid = t2.session_id;
alter system kill session '38,2023';
压测过程中,出现无法解决的问题时、或者响应时间波动难以排查问题时等,可能会用到线程栈、堆内存、tcp网络等dump来排查问题:
-- 1.当前服务器tcp查看到下一服务器之间的tcp握手、数据处理、挥手等操作dump分析
注:需要到各服务器去执行,一个服务器节点执行一次
-- 1.1 时刻打印tcpdump信息
tcpdump -i eth0 host 110.110.110.110
-- 1.2tcpdump信息输出到日志文件中
nohup tcpdump -i eth0 -nn 'host 10.200.11.11' > /bsts/xsf/log/tcpdump/tcpdump_2022030801.log 2>&1 &
nohup tcpdump -i eth0 -nn 'port 22601' > /bsts/xsf/log/tcpdump/tcpdump_2022030801.log 2>&1 &
-- 2.查询目标IP服务器,和我服务器的连接数
注:服务端会多一条监听线程(以ip监控或者以端口好监控)
netstat -n |grep "1.1.1.1" |awk '/^tcp/ {++state[$NF]} END {for(key in state) print key,"t",state[key]}';
netstat -nat|grep -i "22601" |wc -1
-- 3.最后一种,查询先出dump,
-- 3.1 项目配置javaopts,配置jdk jvm访问登录
--3.2 服务器实时打印
每5秒生成一个先出栈
while true;do echo "hello"$system_date;
jstack -1 1 > /bsts/log/stackdump/xiangmuming_123_$system_date;sleep 5;
system_date=$(date '+%Y%m%d%H%M%S');done
-- 4.生产一个堆内存文件
system_date=$(date '+%Y%m%d%H%M%S');jmap -dump:live,format=b,file=/bats/log/jmapdump/xiangmuming$system_date.hprof 1
压测相关注意点
银行部分交易来源用的深证通封装消息传递;类似之前保险行业封装的mq一样,作为消息的传递;
1.需要了解消息在深证通mr里面的停留时间(配置文件配置,默认40秒)
2.压测时,需要了解,:(稍后补充mr13个异常案例,作为了解)
2.1 压测时,如果你不能及时从mr或者mq中接收消息,怎么办,交易难道要让他自己销毁吗?
解决方案:起多个线程的方式,来尽可能多的来接收mr或者mq里面的亲亲贵;
获取交易后,以okhttp连接池异步消费请求;
优化交易,响应时间尽量500ms以内;
2.2 在接收mr或者mq里面交易里,应该时调用一个api来手动获取请求报文;
这时候需要考虑到,高并发时,可以1ms接收一次请求,没有高并发的场景时,1s或者100ms接收一次请求;
3.压测时,毕竟时多个线程进行交易,
理想情况下,一个cpu独赢一个线程(或者cpu大于线程),这样可以保证请求不会过于竞争;
一般情况下,肯定线程数远大于cpu数据,竞争使用资源,最完美的线程数,就是从jvm里看,每一个线程碎片时间、空闲时间很少,没有大量的浪费,那就是完美的,如果线程数据设置过大,浪费内存资源(一个线程1M空间)或者浪费cpu资源(切换线程也浪费上下文资源);
5.脚本开发过程中,发现部分交易因第三方api问题,windows环境发压不高,要用linux环境相关api包,
6.注意fegin线程池数量,(其他文章补充配置)
使用httpclient作为feign的实现,默认线程时10,是否需要增加,看业务进行判断
7.mr作为类似mq的消息传递工具,测试负载策略,(其他文章补充)
8.联机组个服务,线程池配置(随tps不同,可进行占比分配)
server.undertow.io-threads=3
server.undertow.work-thread=64
9.各服务跳转,都可以配置线程池
注意连接数、连接超时时间、响应超时时间;
10.交易整体容量测试,无错误问题,但是cpu不达标,(不考虑增加负载的服务个数,例如仓4台扩到8台)
a.jvm监控线程,又无效的线程一直在增加,
例如,去除ons依赖,
<dependency>
<groupId>com.orcal.ojdbc</groupId>
<artifactId>ojdbc8</artifactId>
<exclusions>
<exclusion>
<groupId>com.orcal.ojdbc</groupId>
<artifactId>ons</artifactId>
</exclusion>
</exclusions>
</dependency>
b:调整线程池,多余线程影响cpu使用
例如:
1):调整tps占比较多的服务线程池,以及减少tps占比较少的服务线程池
server.undertow.io-threads=3
server.undertow.worker-threads=64
2):网关http线程配置
cloud:
gateway:
httpclient:
connect-time:6000
response-timeout:45s
pool:
max-idle-time:${MAX_IDLE_TIME:1000}
max-connections:${MAX_CONNECTIONS:200}
-- 服务器非feign跳转,优化线程池配置(来年结束、连接时间)
例如:网关配置
//网关中通讯的http连接池
private OkHttpClient clientInstance = null;
//接收线程池
pivate static ExecutorService recvThread;;
okThreadPool= new ThreadPoolExecutor(100,300,oL,TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>());
Dispatcher dispatcher = new Dispatcher(okThreadPool);
dispatcher.setMaxRequests(300);//不设置源码默认配置
dispatcher.setMaxRequestsPerHost(300);//不设置源码默认设置
clientInstance = new OkHttpClient.Builder().connectionPool(new ConnectionPool(100,50,timeUnit.SECONDS))
.dispatcher(dispatcher).connectionTimeout(6,TimeUnit.SECONDS)
.writeTimeout(5,TimeUnit.SECONDS).readTimeOut(50,TimeUnit.SECONDS)
.retryOnConnectionFailure(true).build();
c:优化代码,例如
去除无效的依赖注入类,浪费资源,
优化打印日志(去除公共的无用的、大量 的日志打印)、调整相关打印日志级别;
关闭sql打印:
spring.jpa.database=${poin.database.type}
spring.jpa.show-sql=false
等(最终不行可以增加cpu资源、或者服务节点)
d:调整配置,确认是否有无用的配置开启,影响资源,或者调整有用的配置(降低性能)
例如关闭,hibernate的日志打印;
关闭限流和链路等配置:
spring.slenth.enabled=false
spring.zipkin.enabled=false
e:增加或者说提高业务服务和consul的cpu配置、或者增加负载节点(服务个数)
12:性能压测过程中,consul有时会健康检查不通过,consul cpu资源不高,只不过一个服务挂载了一个consul,做出以下优化,
a.扩大consul cpu和内存
b.增加服务线程数
c:tps压力过高的服务,增加服务节点(负载个数,分担压力,效果显著)
13:feign的重发机制,性能测试时优先关掉,生产可恢复默认配置,一定时间内,5次
#同一实例最大重试次数,不包括首次调用
ribbon.MaxAutoRetries=0
#同一个服务其他实例的最大重试次数,不包括第一次调用的实例
ribbon.MaxAutoRetriesNextServer=0
#是否开始重试,
ribbon.OkToRetryOnAllOperations=false
14,响应时间突刺问题,每个系统可能不一样,我方是,固定时间范围内,响应时间超长、或者远程feign调用返回参数到了网关(流水号,记录网关日志、打印日志文件,无其他操作),之后响应时间超长;
最终发现是两个主要原因导致的:
1.日志翻新,会导致锁,响应时间超长,日志转储的磁盘、服务器也有点问题;
2.feign远程调用的服务,短连接理论上不会有问题,网关是此链接空闲300ms后销毁,最终是将远程访问的服务用netty初始化设置为长连接配置即可,
具体优化如下:
首先调整联机项目,部分关键入参以及提示信息日志级别为error,以防生产调整日志级别,获取不到有用信息;
a.log日志
1.我方,打印日志实现方式,由RollingFile调整为,RollingandomAccessFile,使用异步刷盘的方式打印日志;immediateFlush=“false” 打印日志,使用缓冲区进行打印日志,可以设置缓冲区大小;
2.两个网关的打印日志,调整为异步,
3.去除联机无效、大量的打印日志,
4.log配置文件,加载项目配置,开启全异步、混合异步
b:feign调用,
1.采用okhttp,连接池远程调用网关服务,默认线程池数量即可
2.feign.httpclient.max-connections-per-route:150,单服务(ip)访问feign的最大连接数调为150
c:线程池配置、数据库连接池配置根据交易tps进行不同配置,哪些参数例如第10点;
d:jvm监控可去除无效的、占用资源的线程配置