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

2017-02-28 07:37:57 +08:00
 esolve

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

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

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

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

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

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

我是想知道是不是一个 jsp 页面的 http request 对应一个线程调用 servlet 的 service ()
如果是的,那么假如千万用户同时打开千万个 jsp 页面,那是不是同时千万线程?
SoloCompany
2017-03-01 13:40:57 +08:00
@esolve 既然大家不住一个频道上,那就按你想象中的来吧,不再回复了
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
2017-03-01 16:26:41 +08:00
@haochih #15 这个描述无论是在 BIO NIO 还是 APR 下应该都是正确的, BIO 并不是不能处理高并发, BIO 只是无法处理 keepalive (socket accept 也是专用线程来的不会占用 worker 线程) 以及无法支持 sendfile 而已
haochih
2017-03-01 16:37:36 +08:00
@SoloCompany 谢谢点拨,对 IO 模型学习还不够,将继续学习。
esolve
2017-03-01 19:44:13 +08:00
@haochih 您好,我想请问一下,如果不是在 BIO 下,例如在 NIO 下,状况是怎样的?在 NIO 下,不是一个 http request 对应一个线程了吗?
haochih
2017-03-01 21:15:26 +08:00
@esolve 按照#16 说的, NIO 应该也应该是我说的这种情况。我对 IO 模型也是处于学习阶段,所以不敢妄言。
haochih
2017-03-01 21:45:36 +08:00
@esolve 嗯,在 NIO 模型下,也是一个请求对应地必须要有一个线程去处理,但 NIO 模型比 BIO 模型线程利用效率要高,其中就有#16 提到的 keep-avlie 请求。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/343692

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX