Tomcat高性能测试(一)

tomcat说明
tomcat参数说明:

tomcat核心参数: max-threads,accept-count,max-connections,connection-timeout

  • max-threads:
    tomcat起动的最大线程数,即同时处理的任务个数,默认值为200

  • accept-count:
    当accept队列中连接的个数达到acceptCount时,队列满,进来的请求一律被拒绝。默认值是100

  • max-connections
    tomcat在任意时刻接收和处理的最大连接数。当Tomcat接收的连接数达到maxConnections时,Acceptor线程不会读取accept队列中的连接;这时accept队列中的线程会一直阻塞着,直到Tomcat接收的连接数小于maxConnections。如果设置为-1,则连接数不受限制。

    默认值与连接器使用的协议有关:NIO的默认值是10000(万级别),APR/native的默认值是8192,而BIO的默认值为maxThreads200(如果配置了Executor,则默认值是Executor的maxThreads)。

    在windows下,APR/native的maxConnections值会自动调整为设置值以下最大的1024的整数倍;如设置为2000,则最大值实际是1024

  • connection-timeout
    配置为10000,这个配置导致建立一个socket连接后,如果一直没有收到客户端的FIN,也没有数据过来,那么此连接也必须等到10s后,才能被超时释放。从最后一次接收到数据开始计算,如果在此后10s内没有请求过来的话,tomcat会自动断开连接

tomcat参数之间的关系:

有新请求过来以后,会被存放到tomcat底层用于保存连接的数据结构中,当管理的连接数超过maxConnections值的时候,新来的请求会被存放到accept-count大小的请求队列中。当accept-count请求队列满了以后,新进来的请求将会直接拒绝


测试说明
测试目的:

测试目的了解tomcat中max-threads,accept-count,max-connections,connection-timeout参数之间的关系,做深度测试。

客户端每次请求tomcat请求时,让其挂起2秒钟

服务端测试代码:

@RequestMapping(value = "/test/tomcat/hang", method = RequestMethod.GET)
    @ResponseBody
    public void testTomcatHang() {
        try {
            Thread.sleep(1000L * 2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(DateUtil.getTime("yyyy-MM-HH mm:ss") + ":" + Thread.currentThread().getName());
    }
测试
测试案例1:
  • 服务端参数设置:
tomcat:
    uri-encoding: UTF-8
    max-threads: 1
    accept-count: 1
    max-connections: 1
    connection-timeout: 1000
  • 客户端参数设置:
每个线程请求数: 100 
开启线程数: 1 
开启连接数: 1 
选择测试类型: 2 
url地址: localhost:8089
  • 服务端测试结果:
    测试结果符合预期,由于服务端每次接收请求,让其挂起2s。那么每个请求处理间隔的时间就是2s

  • 客户端测试结果:
    在这里插入图片描述客户端的测试结果是0.49/s,理论值是0.5/s。涉及到建立连接过程等,0.49/s符合预期

  • 原理说明:
    我们设置的服务端最大的处理线程数为1,最大的连接数为1,此时客户端也只开启了一个连接。在这种情况下,服务端的出了和客户端的处理是一对一的。一个线程处理一个连接请求

  • tomcat参数状态:

# 当前处理的线程数
max-threads: 1
# accept-count中等待连接数
accept-count: 0 
# max-connections中管理连接数
max-connections: 1

测试案例2:
tomcat:
    uri-encoding: UTF-8
    max-threads: 1
    accept-count: 1
    max-connections: 1
    connection-timeout: 1000
  • 客户端参数设置:
每个线程请求数: 100 
开启线程数: 1 
开启连接数: 2 
选择测试类型: 2 
url地址: localhost:8089
ConnectTimeout : 500ms
  • 服务端测试结果:
    在这里插入图片描述
    服务端测试结果,请求有间隔2秒,也有间隔3秒
  • 客户端测试结果:
    在这里插入图片描述
  • 原理说明:
    当一个线程共享两个连接的时候,意思是在这两个连接之间随机切换。有时候可能是连接A,有时候可能是连接B。但是整体是1/2概率的。
    当线程第一次创建连接A的时候,连接A会被放入到connections队列里面,且完成当前请求。当第二次如果随机获得到的连接还是A的情况下,那么直接使用A连接即可,因为服务端设置的超时时间是1s。所以看到处理的间隔时间有2s的。当线程第二次获取到的连接是B,此时的A连接在connections中并没有过期,需要等待1s的时间,所以此时的连接B被放入到accept队列中。当connections中连接A达到过期时间1s的时候,会从connections中移除A连接,同时将accept中的B连接加入到connections中。所以输出的日志中会存在3秒的间隔时间,其中多出来的一秒时间就是连接A的过期时间。
  • -tomcat参数状态:
# 当前处理的线程数
max-threads: 1
# accept-count中等待连接数
accept-count: 1 
# max-connections中管理连接数
max-connections: 1

测试案例3:

测试案例3,服务端参数不变,客户端参数中,将连接数设置为1。访问线程数设置为2

  • 服务端参数设置:
tomcat:
    uri-encoding: UTF-8
    max-threads: 1
    accept-count: 1
    max-connections: 1
    connection-timeout: 1000
  • 客户端参数设置:
每个线程请求数: 100 
开启线程数: 2 
开启连接数: 1 
选择测试类型: 2 
url: localhost:8089
ConnectTimeout : 500ms
  • 服务端测试结果:
    在这里插入图片描述
    服务的请求处理时间间隔2秒,符合预期

  • 客户端测试结果:
    在这里插入图片描述

    通过检测,同时开启2个线程,共享一个连接的时候。一个连接只能被一个线程使用

  • 原理说明:
    http客户端连接是线程安全的。同一个连接只能被一个线程使用

  • tomcat参数状态:

# 当前处理的线程数
max-threads: 1
# accept-count中等待连接数
accept-count: 0 
# max-connections中管理连接数
max-connections: 1

测试案例4:

测试案例4,服务端参数最大连接数设置为2,客户端参数中,将连接数设置为2,线程数设置为2

  • 服务端参数设置:
tomcat:
    uri-encoding: UTF-8
    max-threads: 1
    accept-count: 1
    max-connections: 2
    connection-timeout: 1000
  • 客户端参数设置:
每个线程请求数: 100 
开启线程数: 2 
开启连接数: 2 
选择测试类型: 2 
url: localhost:8089
ConnectTimeout : 500ms
  • 服务端测试结果:
    在这里插入图片描述
    请求结果每隔2s请求一次
  • 客户端测试结果:
    在这里插入图片描述
    线程1和线程2的请求交替出现
  • 原理说明:
    服务端开启connections为2,同时保持两个连接的请求。当客户端线程1,线程2请求发送连接的时候,该连接都被存储到connections中。但是此时服务端的处理线程数设置为1,所以一次只能处理一个请求。

客户端中的线程1,线程2的请求结果交替出现。因为在connections中,会把有请求状态的连接放到消费队列中进行消费。队列的属性是先进先出。所以客户端的测试结果是交替出现的

  • tomcat参数状态:
# 当前处理的线程数
max-threads: 1
# accept-count中等待连接数
accept-count: 0 
# max-connections中管理连接数
max-connections: 2

测试案例5:

测试案例5,服务端最大连接数为2,最大线程数设置为2,客户端参数中,将连接数设置为2,请求线程数设置为2

  • 服务端参数设置:
tomcat:
    uri-encoding: UTF-8
    max-threads: 2
    accept-count: 1
    max-connections: 2
    connection-timeout: 1000
  • 客户端参数设置:
每个线程请求数: 100 
开启线程数: 2
开启连接数: 2 
选择测试类型: 2 
url: localhost:8089
ConnectTimeout : 500ms
  • 服务端测试结果:
    在这里插入图片描述
    在这里插入图片描述
    查看JVM中的线程情况,发现服务端开启两个处理http-nio-8089-exec的处理线程。同时服务端的输出结果中我们分发现,同一时刻输出两个请求结果。符合预期值
  • 客户端测试结果:
    在这里插入图片描述
    客户端开开启两个线程进行请求,这样QPS达到0.87/s,符合预期
  • 原理说明:
    服务端的最大处理线程数设置为2时,可以同时处理2个客户端连接请求。这样服务端的请求结果同一时刻会出现两次,同时客户端的qps会扩大两倍左右
  • tomcat参数状态:
# 当前处理的线程数
max-threads: 2
# accept-count中等待连接数
accept-count: 0 
# max-connections中管理连接数
max-connections: 2

总结
  1. httpclient的连接是线程安全的,同一时刻只能有一个线程可以使用该连接
  2. 客户端请求连接的时候,首先会被放入到connections中,当connections满了以后,会被存放到accept-count队列中
  3. 服务端的线程一次只能处理一个请求。当需要处理多个请求的时候,需要开启多个线程
  4. 当存放在connections队列中的连接,最后一次请求开始计时,当超过其设置的connection-timeout时,会从连接队列中移除。
  5. connections中默认同时可以管理多个连接,采用的是NIO模式。假设1w个连接,当然这1w个链接也不是都会有读写请求事件发生。当有连接有读写请求事件发生的时候,会把该连接的事件放到Tomcat的TaskQueue中,处理线程会从TaskQueue调用take()方法获取
    在这里插入图片描述
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值