线程池满了请求是报错还是排队?accept-count 和 max-connections 到底管什么?为什么慢接口会把快接口也拖慢?排队的请求会不会超时?这篇把 Tomcat 线程数、连接数和等待队列调小,用并发请求在本机回环上逐个测量(平台是 macOS,Linux 的表现没有验证)。
threads.max=200 threads.min-spare=10 max-connections=8192 accept-count=100 connection-timeout=null
200 个线程、8192 个连接、100 的等待队列。
8 个并发请求:成功 8,失败 0
成功请求的总耗时(ms,从小到大):[1054, 1054, 2061, 2062, 3065, 3067, 4071, 4072]
成功请求建立 TCP 连接的耗时(ms,从小到大):[0, 0, 0, 0, 0, 1, 1, 1]
压力期间另发一个 /fast:ok,总耗时 3770 ms,状态 200;exec 线程数=2排队不报错,快请求也会被慢请求拖慢。
max-connections=4、accept-count=2:
第 1 轮:12 个同时发起的请求 → {'成功': 2, '失败:ConnectionResetError@连接阶段': 9, '失败:BrokenPipeError@发请求阶段': 1};成功的里最慢的总耗时 1051 ms;失败请求耗时最长 1 ms
第 2 轮:12 个同时发起的请求 → {'成功': 6, '失败:ConnectionResetError@连接阶段': 5, '失败:BrokenPipeError@发请求阶段': 1};成功的里最慢的总耗时 3020 ms;失败请求耗时最长 1 ms
第 3 轮:12 个同时发起的请求 → {'成功': 5, '失败:ConnectionResetError@等响应阶段': 1, '失败:ConnectionResetError@连接阶段': 6};成功的里最慢的总耗时 3020 ms;失败请求耗时最长 1 ms
max-connections=4、accept-count=5:
第 1 轮:12 个同时发起的请求 → {'成功': 5, '失败:ConnectionResetError@连接阶段': 5, '失败:BrokenPipeError@发请求阶段': 2};成功的里最慢的总耗时 3071 ms;失败请求耗时最长 1 ms
第 2 轮:12 个同时发起的请求 → {'成功': 9, '失败:ConnectionResetError@连接阶段': 2, '失败:BrokenPipeError@发请求阶段': 1};成功的里最慢的总耗时 5020 ms;失败请求耗时最长 0 ms
第 3 轮:12 个同时发起的请求 → {'成功': 9, '失败:ConnectionResetError@连接阶段': 3};成功的里最慢的总耗时 5025 ms;失败请求耗时最长 0 ms
max-connections=4、accept-count=8:
第 1 轮:12 个同时发起的请求 → {'成功': 7, '失败:ConnectionResetError@连接阶段': 5};成功的里最慢的总耗时 4072 ms;失败请求耗时最长 1 ms
第 2 轮:12 个同时发起的请求 → {'成功': 12};成功的里最慢的总耗时 6026 ms;失败请求耗时最长 0 ms
第 3 轮:12 个同时发起的请求 → {'成功': 12};成功的里最慢的总耗时 6035 ms;失败请求耗时最长 0 ms
max-connections=4、accept-count=100:
第 1 轮:12 个同时发起的请求 → {'成功': 12};成功的里最慢的总耗时 6077 ms;失败请求耗时最长 0 ms
第 2 轮:12 个同时发起的请求 → {'成功': 12};成功的里最慢的总耗时 6033 ms;失败请求耗时最长 0 ms
第 3 轮:12 个同时发起的请求 → {'成功': 12};成功的里最慢的总耗时 6027 ms;失败请求耗时最长 0 ms
max-connections=100、accept-count=2:
第 1 轮:12 个同时发起的请求 → {'成功': 2, '失败:ConnectionResetError@连接阶段': 6, '失败:ConnectionResetError@等响应阶段': 1, '失败:OSError@连接阶段': 1, '失败:BrokenPipeError@发请求阶段': 2};成功的里最慢的总耗时 1066 ms;失败请求耗时最长 1 ms
第 2 轮:12 个同时发起的请求 → {'成功': 12};成功的里最慢的总耗时 6036 ms;失败请求耗时最长 0 ms
第 3 轮:12 个同时发起的请求 → {'成功': 12};成功的里最慢的总耗时 6032 ms;失败请求耗时最长 0 msaccept-count 很小时,多余的连接被立即重置,每轮成功数波动。
8 个并发请求:成功 8,失败 0
成功请求的总耗时(ms,从小到大):[1052, 1053, 2056, 2059, 3064, 3064, 4070, 4070]
成功请求建立 TCP 连接的耗时(ms,从小到大):[0, 0, 0, 0, 0, 0, 0, 1]
压力期间另发一个 /fast:ok,总耗时 3764 ms,状态 200;exec 线程数=2connection-timeout 踢不掉排队等线程的请求,要在更外层限时。