百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

浅析Tomcat高并发之连接池,线程池

haoteby 2024-12-20 15:44 11 浏览

记得大学的《网络工程》有一个课后作业:用Java实现一个web服务器,当时想的是为了提高吞吐量,可以用多线程实现,即对于每一个客户端请求连接,都启动一个线程来处理,处理逻辑大概就是从socket里面读取http请求,解析执行请求,执行完把response写回socket,线程结束销毁。用多线程实现确实提高了吞吐量,但是也有一些问题:1)不断的线程创建销毁需要耗费大量的开销;2)线程之间的切换需要耗费很多开销;3)Java有创建最多线程数量的限制,具体可参考https://www.iteye.com/blog/jzhihui-1271122。


如果要优化上面的实现,可以怎么做呢?其实参考tomcat的发展进程,就是优化的方向。


1

Tomcat处理用户请求的入口组件叫做Connector,其有两个主要的实现:BIO(blocking io)和NIO(non-blocking io)。


简单讲,BIO的实现就是对上面多线程版本的一个改进,主要点在于把“每来一个连接启动一个线程处理”改成“每来一个连接都提交给线程池处理”。虽然线程池根据不同的配置,其工作行为会有所不同,但一般来讲,使用线程池的原则是:只需创建少量的线程就可以完成大量任务的执行,由于同时至多只有固定量的线程执行,剩余的任务会被放进queue里面缓冲起来,从这个角度看,这是一个典型的生产者-消费者模型。回到tomcat BIO,acceptor不断的接收连接,然后提交给线程池执行,acceptor就是生产者;线程池的每一个线程就是消费者,负责处理请求。


由于socket连接是长连接,连接的创建销毁也是很耗资源的,于是http协议增加了一个keep-alive header,这个header的意思是提示服务器端,在返回http response之后,不要断开socket,继续处理后续http请求,这样做的目的就是为了提高资源的可重用性。那么,对于tomcat BIO的实现,在keep-alive场景下,会有什么问题呢?如果一个线程处理的socket需要保持keep-alive,其在执行完一个http请求之后,需要阻塞在那里以等待下一个http请求,不能马上结束(直到timeout);在某些情况下,这样就可能存在大量的阻塞线程,新的连接不能被处理。


基于此,NIO就可以解决这个问题。NIO和BIO在请求处理部分的实现是一致的,都是基于线程池;不同的地方是:NIO的acceptor基于jdk nio实现,在收到一个连接之后,会把socketChannel注册到poller的selector上面,当socketChannel有数据可读时,poller就把此连接提交给线程池处理。回到上面keep-alive的场景,当一个线程处理完一个http请求之后,就可以马上结束,当前连接则回到selector继续监听接下来的http请求。所以,基于NIO的执行线程就不会出现基于BIO的阻塞情况。


NIO的核心在于selector,selector可以识别到已经ready的连接和没有ready的连接;在之前的一篇多线程文章(对比Java和.NET多线程编程)里面提到过,jdk的concurrency API有一个CompletionService类,就有点类似于nio的原理。


由于NIO天生的优势,tomcat从8.0版本开始就把NIO设成默认的Connector,而从8.5版本开始直接就把BIO去掉了。


2

在tomcat的官网有下面一段关于如何高并发处理请求的描述:

Each incoming request requires a thread for the duration of that request. If more simultaneous requests are received than can be handled by the currently available request processing threads, additional threads will be created up to the configured maximum (the value of the maxThreads attribute). If still more simultaneous requests are received, they are stacked up inside the server socket created by the Connector, up to the configured maximum (the value of the acceptCount attribute). Any further simultaneous requests will receive "connection refused" errors, until resources are available to process them.

- https://tomcat.apache.org/tomcat-7.0-doc/config/http.html


个人觉得其没有反映出maxConnections这个参数的作用,所以应该是:如果maxConnections小于maxThreads,最大创建的线程数就是maxConnections的值,最大连接数也是maxConnections的值;但是如果maxConnections大于maxThreads,最大创建的线程数就是maxThreads的值,最大连接数则是maxConnections的值。


由于BIO和NIO底层实现的区别,配置maxConnections的值也需要区别考虑,这在maxConnections的默认值中就有所体现(对于BIO,maxConnections的默认值是maxThreads的值;而对于NIO,maxConnections的默认值则是10000):


3

上面有提到,tomcat接收处理请求的过程其实就是一个生产者-消费者模型,影响tomcat高并发的配置也可以首先分别从这两个方面考虑:

生产者

消费者

Queue


4

小结一下:

  • 线程池的本质就是节省了不断创建销毁线程的开销;加上queue的使用,增加了一层缓冲,一定程度缓解了计算机的压力。当然线程池的配置,需要根据要处理的任务(CPU密集型还是io密集型)来仔细的考虑。
  • Tomcat里面BIO和NIO的最大区别在于读取下一个请求时是否需要阻塞,这对于keep-alive的场景尤其重要,NIO可以大大提高吞吐量。
  • 基于queue的生成者-消费者模型,也常常应用在系统架构层面,以缓冲生产者和消费者之间处理速度的gap,比如秒杀系统。


本文分享自微信公众号 - 天马行空布鲁斯(gh_2feda5c053bd)。
如有侵权,请联系 删除。

相关推荐

一日一技:用Python程序将十进制转换为二进制

用Python程序将十进制转换为二进制通过将数字连续除以2并以相反顺序打印其余部分,将十进制数转换为二进制。在下面的程序中,我们将学习使用递归函数将十进制数转换为二进制数,代码如下:...

十进制转化成二进制你会吗?#数学思维

六年级奥赛起跑线:抽屉原理揭秘。同学们好,我是你们的奥耀老师。今天一起来学习奥赛起跑线第三讲二进制计数法。例一:把十进制五十三化成二进制数是多少?首先十进制就是满十进一,二进制就是满二进一。二进制每个...

二进制、十进制、八进制和十六进制,它们之间是如何转换的?

在学习进制时总会遇到多种进制转换的时候,学会它们之间的转换方法也是必须的,这里分享一下几种进制之间转换的方法,也分享两个好用的转换工具,使用它们能够大幅度的提升你的办公和学习效率,感兴趣的小伙伴记得点...

c语言-2进制转10进制_c语言 二进制转十进制

#include<stdio.h>intmain(){charch;inta=0;...

二进制、八进制、十进制和十六进制数制转换

一、数制1、什么是数制数制是计数进位的简称。也就是由低位向高位进位计数的方法。2、常用数制计算机中常用的数制有二进制、八进制、十进制和十六进制。...

二进制、十进制、八进制、十六进制间的相互转换函数

二进制、十进制、八进制、十六进制间的相互转换函数1、输入任意一个十进制的整数,将其分别转换为二进制、八进制、十六进制。2、程序代码如下:#include<iostream>usingna...

二进制、八进制、十进制和十六进制等常用数制及其相互转换

从大学开始系统的接触计算机专业,到现在已经过去十几年了,今天整理一下基础的进制转换,希望给还在上高中的表妹一个入门的引导,早日熟悉这个行业。一、二进制、八进制、十进制和十六进制是如何定义的?二进制是B...

二进制如何转换成十进制?_二进制如何转换成十进制例子图解

随着社会的发展,电器维修由继电器时代逐渐被PLC,变频器,触摸屏等工控时代所替代,特别是plc编程,其数据逻辑往往涉及到数制二进制,那么二进制到底是什么呢?它和十进制又有什么区别和联系呢?下面和朋友们...

二进制与十进制的相互转换_二进制和十进制之间转换

很多同学在刚开始接触计算机语言的时候,都会了解计算机的世界里面大多都是二进制来表达现实世界的任何事物的。当然现实世界的事务有很多很多,就拿最简单的数字,我们经常看到的数字大多都是十进制的形式,例如:我...

十进制如何转换为二进制,二进制如何转换为十进制

用十进制除以2,除的断的,商用0表示;除不断的,商用1表示余0时结束假如十进制用X表示,用十进制除以2,即x/2除以2后为整数的(除的断的),商用0表示;除以2除不断的,商用1表示除完后的商0或1...

十进制数如何转换为二进制数_十进制数如何转换为二进制数举例说明

我们经常听到十进制数和二进制数,电脑中也经常使用二进制数来进行计算,但是很多人却不清楚十进制数和二进制数是怎样进行转换的,下面就来看看,十进制数转换为二进制数的方法。正整数转二进制...

二进制转化为十进制,你会做吗?一起来试试吧

今天孩子问把二进制表示的110101改写成十进制数怎么做呀?,“二进制”简单来说就是“满二进一”,只用0和1共两个数字表示,同理我们平常接触到的“十进制”是“满十进一”,只用0-9共十个数字表示。如果...

Mac终于能正常打游戏了!苹果正逐渐淘汰Rosetta转译

Mac玩家苦转译久矣!WWDC2025苹果正式宣判Rosetta死刑,原生游戏时代终于杀到。Metal4光追和AI插帧技术直接掀桌,连Steam都连夜扛着ARM架构投诚了。看到《赛博朋克2077》...

怎么把视频的声音提出来转为音频?音频提取,11款工具实测搞定

想把视频里的声音单独保存为音频文件(MP3/AAC/WAV/FLAC)用于配音、播客、听课或二次剪辑?本文挑出10款常用工具,给出实测可复现的操作步骤、优缺点和场景推荐。1)转换猫mp3转换器(操作门...

6个mp4格式转换器测评:转换速度与质量并存!

MP4视频格式具有兼容性强、视频画质高清、文件体积较小、支持多种编码等特点,适用于网络媒体传播。如果大家想要将非MP4格式的视频转换成MP4的视频格式的话,可以使用MP4格式转换器更换格式。本文分别从...