Java服务压测遇到的问题
一、线程池数量
实例服务器4C3G
场景:服务A——》服务B; 实例服务器:8台,接口耗时 400ms
现像服务A接口中有使用多线程, 设置线程池核心线程数:8 最大线程数量200 ,队列:10000,当进行压测时吞吐量一直超不过每秒请求量 qps: 500 ,且开始接口耗时也随着请求量上来而增长。
原因:线程池核心线程:8 与最大线程:100 相差较多,可能在请求过程中不断创建新线程 比较耗时。
调整:将线程池核心程调到:40 ,最大线程调到:40 ,qps每秒请求达到700以上;发起服务响应时间也降低。
如:
/** * 自定义线程池 * @return */ @Bean("selfThreadPool") public ThreadPoolExecutor getThreadPool() { log.info("corePoolSize:{},maximumPoolSize:{},queueSize:{}", corePoolSize, maximumPoolSize, queueSize); ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(40, 40, 30 , TimeUnit.SECONDS, new ArrayBlockingQueue<>(200), new ThreadFactory() { @Override public Thread newThread(Runnable r) { Thread thread = new Thread(r); thread.setName("self-thread-pool-" + thread.getId()); return thread; } }, new ThreadPoolExecutor.CallerRunsPolicy()); return threadPoolExecutor; } }
二、 使用java 服务中用HttpClient 请求接口,请求量一直不高
实例服务器4C3G
场景:服务A——》服务B; 实例服务器:8台,接口耗时 300ms 但请求多时接口耗时到800ms
原因:没有设置MaxConnTotal、MaxConnPerRoute 两个属性;
maxTotal 是设置同时间正在使用的最大连接数,默认值是20。
maxPerRoute 是设置一个 host(ip或域名):port 同时间正在使用的最大连接数,默认值是2。 因为默认值maxPerRoute 较低在服务请求并发较多时,会有大部分请求处理等待连接情况,所以qpsi不高,请求耗时变得比较长。
处理:设置maxTotal :100,maxConnTotal:400 使qps提高到700 以上,接口耗时在请求并发较多时也控制在400ms 以内
怎样计算 吞吐量 当cpu(4C3G)和内存都满足情况,假如一个请求耗时 350ms
60000/350ms*200 理想状态,但一般实际情况会降低3-5倍,所以每台实例可承载请求量大概放算应该是 除以(3到5),考虑是否有大量其它接口一起场景。
三、 一个接口中有xml解析,请求qps 一直不高500 以下,耗时较长
原因:每个请求都实例化一次xml 解析对象比较耗时
处理:将xml解新定义成一静态,大大提高qps和请求耗时。