【问题标题】:Requests to same url blocked in http nio thread pool在 http nio 线程池中阻止对相同 url 的请求
【发布时间】:2019-01-20 23:52:30
【问题描述】:

我只是简单的在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;
}

测试结果:

  1. 不同的url:不阻塞,几乎同时开始执行。

http://localhost:20002/sleep?status=falsehttp://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].
  1. 相同的 url: 块,第二个请求在第一个请求完成之前不会执行。

http://localhost:20002/sleep?status=truehttp://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的请求进来时,Poller线程可以立即捕获并处理;当具有相同 url 的请求进来时,轮询器在返回第一个连接之前无法获取它。

【问题讨论】:

  • 如果您使用 Jetty 或更新版本的 Spring Boot(1.5.14 而不是 1.5.4)会发生什么?
  • 在 Jetty 和 SpringBoot 1.5.14.RELEASE 上测试,结果没有区别。
  • 试图重现它,但在我这边按预期工作。为同一个 URL 触发 8 个并发请求,它们同时到达。你如何测试这个?从浏览器、测试或命令行上的 cUrl 或 Httpie 之类的东西?我怀疑浏览器可能会阻止调用相同的 URL(并在再次调用之前等待第一个请求完成)。
  • 是的,谢谢。使用不同的客户端,请求同时到达。是 chrome 停止了对同一资源的请求。

标签: spring-boot tomcat nio spring-restcontroller


【解决方案1】:

感谢@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. 

https://stackoverflow.com/a/27514611/10222882

而且经过 chrome Network 证明 -> 计时,第 2 个请求处于 [stalled] 状态,直到第 1 个响应返回。

connection_stalled

【讨论】:

    猜你喜欢
    • 2013-05-10
    • 1970-01-01
    • 2017-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-07
    • 2021-01-05
    • 2018-01-28
    相关资源
    最近更新 更多