对相同 url 的请求在 http nio 线程池中被阻止
Requests to same url blocked in http nio thread pool
我简单的在springboot(1.5.4.RELEASE)应用中创建了一个RestController,测试了多个请求进来时如何工作。让我困惑的是:
- 相同url:第二个请求阻塞,直到第一个请求执行
- 不同url:非阻塞,2个请求几乎同时执行
我的问题是谁阻止了第二个请求,为什么?
测试代码:
@GetMapping(value = "/sleep")
public String sleep(HttpServletRequest request, @RequestParam boolean status)
{
String requestId = request.toString();
logger.info("request [{}] in and status = {}.", requestId, status);
String result;
if (status)
{
Thread.currentThread().sleep(10 * 1000);
result = "slept";
}
else
{
result = "stay up";
}
logger.info("response [{}] out and result = [{}].", requestId, result);
return result;
}
测试结果:
- 不同url:不阻塞,几乎同时开始执行
http://localhost:20002/sleep?status=false AND http://localhost:20002/sleep?status=true
2018-08-14 15:04:14.139 [http-nio-20002-exec-5]: connection [RequestFacade@46515328] in and status = true.
2018-08-14 15:04:16.452 [http-nio-20002-exec-6]: connection [RequestFacade@1140f857] in and status = false.
2018-08-14 15:04:16.452 [http-nio-20002-exec-6]: connection [RequestFacade@1140f857] out and result = [stay up].
2018-08-14 15:04:24.139 [http-nio-20002-exec-5]: connection [RequestFacade@46515328] out and result = [slept].
- 相同url:块,第一个请求完成后,第二个请求才会执行。
http://localhost:20002/sleep?status=true AND http://localhost:20002/sleep?status=true
2018-08-14 15:10:29.943 [http-nio-20002-exec-9]: connection [RequestFacade@46515328] in and status = true.
2018-08-14 15:10:39.944 [http-nio-20002-exec-9]: connection [RequestFacade@46515328] out and result = [slept].
2018-08-14 15:10:39.960 [http-nio-20002-exec-1]: connection [RequestFacade@1140f857] in and status = true.
2018-08-14 15:10:49.960 [http-nio-20002-exec-1]: connection [RequestFacade@1140f857] out and result = [slept].
我调试了tomcat-embed-core的代码,发现当有不同url的request进来时,Poller线程可以立即捕获并处理;当具有相同 url 的请求进入时,轮询器在返回第一个连接之前无法获取它。
感谢@M.Deinum,阻塞与NIO无关。是 chrome 阻止了第二个请求,出于原因,我在下面找到一些评论:
this behavior is due to Chrome locking the cache and waiting to see the result of one
request before requesting the same resource again.
并且通过chrome Network -> Timing 证明,第2个请求处于[stalled]状态,直到第1个响应返回。
connection_stalled
我简单的在springboot(1.5.4.RELEASE)应用中创建了一个RestController,测试了多个请求进来时如何工作。让我困惑的是:
- 相同url:第二个请求阻塞,直到第一个请求执行
- 不同url:非阻塞,2个请求几乎同时执行
我的问题是谁阻止了第二个请求,为什么?
测试代码:
@GetMapping(value = "/sleep")
public String sleep(HttpServletRequest request, @RequestParam boolean status)
{
String requestId = request.toString();
logger.info("request [{}] in and status = {}.", requestId, status);
String result;
if (status)
{
Thread.currentThread().sleep(10 * 1000);
result = "slept";
}
else
{
result = "stay up";
}
logger.info("response [{}] out and result = [{}].", requestId, result);
return result;
}
测试结果:
- 不同url:不阻塞,几乎同时开始执行
http://localhost:20002/sleep?status=false AND http://localhost:20002/sleep?status=true
2018-08-14 15:04:14.139 [http-nio-20002-exec-5]: connection [RequestFacade@46515328] in and status = true.
2018-08-14 15:04:16.452 [http-nio-20002-exec-6]: connection [RequestFacade@1140f857] in and status = false.
2018-08-14 15:04:16.452 [http-nio-20002-exec-6]: connection [RequestFacade@1140f857] out and result = [stay up].
2018-08-14 15:04:24.139 [http-nio-20002-exec-5]: connection [RequestFacade@46515328] out and result = [slept].
- 相同url:块,第一个请求完成后,第二个请求才会执行。
http://localhost:20002/sleep?status=true AND http://localhost:20002/sleep?status=true
2018-08-14 15:10:29.943 [http-nio-20002-exec-9]: connection [RequestFacade@46515328] in and status = true.
2018-08-14 15:10:39.944 [http-nio-20002-exec-9]: connection [RequestFacade@46515328] out and result = [slept].
2018-08-14 15:10:39.960 [http-nio-20002-exec-1]: connection [RequestFacade@1140f857] in and status = true.
2018-08-14 15:10:49.960 [http-nio-20002-exec-1]: connection [RequestFacade@1140f857] out and result = [slept].
我调试了tomcat-embed-core的代码,发现当有不同url的request进来时,Poller线程可以立即捕获并处理;当具有相同 url 的请求进入时,轮询器在返回第一个连接之前无法获取它。
感谢@M.Deinum,阻塞与NIO无关。是 chrome 阻止了第二个请求,出于原因,我在下面找到一些评论:
this behavior is due to Chrome locking the cache and waiting to see the result of one
request before requesting the same resource again.
并且通过chrome Network -> Timing 证明,第2个请求处于[stalled]状态,直到第1个响应返回。
connection_stalled