V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
esolve
V2EX  ›  问与答

tomcat 是不是来一个 http request 就生成一个线程去处理?

  •  
  •   esolve · 2017-02-28 07:37:57 +08:00 · 9308 次点击
    这是一个创建于 2817 天前的主题,其中的信息可能已经有所发展或是发生改变。

    这样的话 在高并发环境下 岂不是需要很多线程? 感觉不对啊

    22 条回复    2017-03-02 09:12:11 +08:00
    ewBuyVmLZMZE
        1
    ewBuyVmLZMZE  
       2017-02-28 07:40:13 +08:00
    Just read the book: How tomcat works
    guoliang
        2
    guoliang  
       2017-02-28 08:20:18 +08:00 via iPhone
    可以读读这篇 netflix 关于性能调优的帖子: http://techblog.netflix.com/2015/07/tuning-tomcat-for-high-throughput-fail.html?m=1
    Cbdy
        3
    Cbdy  
       2017-02-28 08:21:22 +08:00 via Android
    粒子群 actor : akka 、 erlang
    单线程 reactor : node.js 、 vert.x
    多线程 thread pool : fastcgi 、 servlet
    多进程: cgi

    另这和 tomcat 其实关系不大,是 servlet 标准有相关说明,另外,较新的 serglet 标准支持异步,类似 reactor 。既然 po 有质疑,请问有更好的并发模型吗?说出来分享一下
    kaneg
        4
    kaneg  
       2017-02-28 11:01:11 +08:00
    基于 Java 的,八九不离十都是线程池,线程池大小是可配置的。当然,线程池的大小要和最大的请求数量要协调,否则谁都扛不住。
    esolve
        5
    esolve  
    OP
       2017-02-28 17:31:08 +08:00   ❤️ 1
    @Cbdy

    不懂你在说什么。。。。 我又不是询问什么并发模型好。。。
    我是问, java tomcat 下,高并发是不是意味着高线程数
    10 万个同时的 http request
    就 10 万个线程?
    Cbdy
        6
    Cbdy  
       2017-02-28 17:53:36 +08:00
    @esolve 我可能解释的不是很清楚,是的,每个请求一个线程去处理。 tomcat 实现的是 servlet 标准——很经典的线程池模型。 但线程不可能一直加上去,否则切换线程开销会剧增,系统会抖动,性能会下降。所以一般会丢请求。
    esolve
        7
    esolve  
    OP
       2017-02-28 18:28:04 +08:00   ❤️ 1
    @Cbdy 还是没懂,丢请求?那怎么高并发?
    如果 10 万个请求同时来,线程只能开 1000 个,那 9 万多个请求都被丢掉?
    Cbdy
        8
    Cbdy  
       2017-02-28 19:49:05 +08:00 via Android
    @esolve 是的
    gam2046
        9
    gam2046  
       2017-02-28 19:56:22 +08:00
    相信楼主上网有的时候会看到服务器返回 503 Service Unavailable ,此时页面刷新一下就一切正常仿佛没发生过一样。这就有可能(只是有可能)是因为服务器的前端处理器并发量达到了线程池的上限,此时就不再接受新的请求。直接告诉客户端服务不可用。

    其次....tomcat 其实并发量也不会很大(相比静态服务端而言),毕竟所有东西都要到容器里转一圈,再经过用户代码。这一圈下来资源开销就已经很大了。
    SoloCompany
        10
    SoloCompany  
       2017-03-01 00:00:13 +08:00
    @esolve #7 这个结论明显不正确,还是先读一下资料吧,至少先搞懂 BIO / NIO / AJP 几种不同的 io 模型,还有 sendfile 。

    对于 BIO 而言,也许是正确的,因为 socket 成了最大的瓶颈。所有其它 IO 模型都是异步模型,超过处理能力的请求只会排队, poller 线程(连接及 header 处理)是独立的; sendfile (比如静态文件)还完全不会占用 worker 线程
    esolve
        11
    esolve  
    OP
       2017-03-01 03:04:03 +08:00
    @SoloCompany 我知道阻塞 非阻塞 select poll 等
    我只是针对 servlet 和 tomcat 的状况
    我只是想知道是不是一个 jsp 页面的 http request 对应一个线程调用 servlet 的 service ()
    如果是的,那么假如千万用户同时打开千万个 jsp 页面,那是不是同时千万线程?
    SoloCompany
        12
    SoloCompany  
       2017-03-01 04:03:00 +08:00
    @esolve 脱离谈响应时间谈并发就是耍流氓,难道你用 nodejs 单线程服务就能解决问题了?好好想想这句话是什么意思。多线程不是让问题更加恶劣,而是缓解问题,如果不存在阻塞(典型的是 IO 阻塞),最简单的多线程模型显然是最优解,所有异步框架都是为了解决阻塞问题的。
    esolve
        13
    esolve  
    OP
       2017-03-01 05:43:34 +08:00
    @SoloCompany 我没看懂你在说什么。。。
    我不是来求问解决方案的
    我是来探讨 概念和原理的。。。

    我是想知道是不是一个 jsp 页面的 http request 对应一个线程调用 servlet 的 service ()
    如果是的,那么假如千万用户同时打开千万个 jsp 页面,那是不是同时千万线程?
    SoloCompany
        14
    SoloCompany  
       2017-03-01 13:40:57 +08:00 via iPhone
    @esolve 既然大家不住一个频道上,那就按你想象中的来吧,不再回复了
    haochih
        15
    haochih  
       2017-03-01 16:22:50 +08:00
    Tomcat 假如在未分布式情况,按照 Servlet 标准,未实现 SingleThreadModel 的 Servlet ,如果只声明一次的话,该 Servlet 在服务过程中只会有一个实例,当客户端有请求发起时, Servlet 容器会给每一个请求,从 Servlet 容器维护的线程池(具体线程个数参数配置)里面获取一个线程为其服务( BIO 模型下)。当有大量的请求发起时,线程池里面的线程可能会一下子被用完,这时候剩余请求就会被排在请求队列中(具体可以排多少个,参数配置),等有线程闲下来时继续服务排队请求,假如请求数量超过了最大的排队数,未排进队列的请求就会不予处理。

    按照楼主说的, 10w 个 HTTP Request ,不会有 10w 个线程同时服务, Servlet 容器线程池配置了最多 1000 个线程,那么一瞬间这 1000 个线程将会服务于 1000 个请求,假如剩余 9000 个中 2000 个又排进了待处理队列,那么剩下的 7000 个将会不予处理,当然这是同一时间点 10w 个请求同时到达的情况。实际情况下, 10w 个请求到达时间应该有前有后,所以可能某些请求达到时,某些请求已经被迅速处理掉,线程闲下来可以继续处理了。

    @SoloCompany 想请教一下上面这段在 BIO 模型下理解是否正确,谢谢。
    SoloCompany
        16
    SoloCompany  
       2017-03-01 16:26:41 +08:00
    @haochih #15 这个描述无论是在 BIO NIO 还是 APR 下应该都是正确的, BIO 并不是不能处理高并发, BIO 只是无法处理 keepalive (socket accept 也是专用线程来的不会占用 worker 线程) 以及无法支持 sendfile 而已
    haochih
        17
    haochih  
       2017-03-01 16:37:36 +08:00
    @SoloCompany 谢谢点拨,对 IO 模型学习还不够,将继续学习。
    esolve
        18
    esolve  
    OP
       2017-03-01 19:44:13 +08:00
    @haochih 您好,我想请问一下,如果不是在 BIO 下,例如在 NIO 下,状况是怎样的?在 NIO 下,不是一个 http request 对应一个线程了吗?
    haochih
        19
    haochih  
       2017-03-01 21:15:26 +08:00
    @esolve 按照#16 说的, NIO 应该也应该是我说的这种情况。我对 IO 模型也是处于学习阶段,所以不敢妄言。
    haochih
        20
    haochih  
       2017-03-01 21:45:36 +08:00
    @esolve 嗯,在 NIO 模型下,也是一个请求对应地必须要有一个线程去处理,但 NIO 模型比 BIO 模型线程利用效率要高,其中就有#16 提到的 keep-avlie 请求。
    esolve
        21
    esolve  
    OP
       2017-03-01 23:49:50 +08:00
    @haochih 如果也要一个线程对应一个 http 请求的话
    那高并发怎么能成?
    加入 1 亿用户同时并发
    单机最多能有 1 万个线程
    这意思要用 1 万台机器分压?
    haochih
        22
    haochih  
       2017-03-02 09:12:11 +08:00
    @esolve 分布式肯定是要的,具体需要多少台机器,怎么分压,就不清楚了。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5532 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 06:45 · PVG 14:45 · LAX 22:45 · JFK 01:45
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.