浅谈tomcat运行模式

栏目: 服务器 · 发布时间: 5年前

内容简介:写这篇文章的起因源于笔者对一个小问题的不断追溯,并非是先去看类似的文章然后总结得到,这样做的好处就是在于具有目的性,找答案时也会更有兴趣。这个小问题大家平时在springMVC项目中基本都会碰到:生产日志down下来发现经常会有穿插打印两个接口日志的现象,经过分析发现第一个request执行到一部分还没执行完时第二个request又上来了,因为2个request对应的接口都会调用一些其它系统或者创建,关闭sqlSession这类需要等待耗时的操作,在某个接口执行到这种等待期时,另一个接口就会在这个间隙继续往

引言

写这篇文章的起因源于笔者对一个小问题的不断追溯,并非是先去看类似的文章然后总结得到,这样做的好处就是在于具有目的性,找答案时也会更有兴趣。这个小问题大家平时在springMVC项目中基本都会碰到:生产日志down下来发现经常会有穿插打印两个接口日志的现象,经过分析发现第一个request执行到一部分还没执行完时第二个request又上来了,因为2个request对应的接口都会调用一些其它系统或者创建,关闭sqlSession这类需要等待耗时的操作,在某个接口执行到这种等待期时,另一个接口就会在这个间隙继续往下执行,最终造成日志一会打印A接口的执行,一会打印B接口的执行。基于此现象,笔者产生了以下猜想。

正文

两个接口的执行是否对应了2个线程?如果是这样,是否意味着容器每收到一个请求都会创建1个线程?

有个显而易见的东西,某个request没执行完,也就是没返回response前系统是可以处理其它请求的。

笔者想要确定出现这种情况时,是否是两个不同的线程在分别跑两个接口,想通过测试搞清楚,原理是在两个接口执行过程中把线程地址打出来,通过比较是否一样确定是否是2个线程,将原来的springMVC项目找到2个查询接口。

在A接口中间某个程序段加上如下代码块

logger.info("A1>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"+Thread.currentThread());
try {
   Thread.sleep(new Long(10000));
} catch (InterruptedException e) {
   e.printStackTrace();
}
logger.info("A2>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"+Thread.currentThread());复制代码

在B接口中间某个程序段加上如下代码块

logger.info("B1>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"+Thread.currentThread());
try {
   Thread.sleep(new Long(10000));
} catch (InterruptedException e) {
   e.printStackTrace();
}
logger.info("B2>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"+Thread.currentThread());复制代码

然后写了2个测试类,用来模拟http请求,测试类1向A接口发请求,测试类2向B接口发请求

使用tomcat启动项目,然后执行测试类1,间隔3秒左右启动测试类2,等待了几秒钟,测试类1,2都分别收到了回复,查看日志,发现打印顺序如下

......
A1>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>Thread[http-apr-8090-exec-2,5,main]
......
B1>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>Thread[http-apr-8090-exec-4,5,main]
......
A2>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>Thread[http-apr-8090-exec-2,5,main]
......
B2>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>Thread[http-apr-8090-exec-4,5,main]
......复制代码

由打印日志不难发现,的确是2个线程

那么能否据此推测说容器每接收到1个请求就会创建1个线程呢?答案是否定的

以tomcat为例,暂不考虑其它容器,经过大量的资料查询,发现和tomcat的运行模式有关系,tomcat有3种运行模式,分别是

  • bio模式

即每1个请求,tomcat都会创建1个线程,现在的tomcat基本都用线程池处理,类似数据库的连接池,提前创建好一定数量的连接,比起请求来了再创建省很多时间。很容易想到,如果并发量很大时,就会需要很多线程,内存肯定很容易溢出的。tomcat配置文件中的Connector节点下默认maxConnections=maxThreads,如果是bio模式,如果想要改变maxThreads(默认75),只需要配置maxThreads

  • nio模式

maxConnections>maxThreads,即nio模式相对bio模式同等情况下减少了线程数,笔者的理解就是通过某种优化最大化压榨CPU,把时间片都更好利用起来,这里也说明了1个请求未必对应1个线程,之前做过netty项目其通讯就是nio模式,这里附上1篇高质量讲解NIO模式的文章: www.jianshu.com/p/76ff17bc6… ,有兴趣可以看下

  • apr 模式

和nio模式类似,主要区别在于处理静态资源的能力更强

如何查看你的项目是什么运行模式?

查看启动日志,会发现类似这样的东西:

信息: Initializing ProtocolHandler ["http-nio-8090"]
四月 10, 2019 9:16:19 下午 org.apache.tomcat.util.net.NioSelectorPool getSharedSelector
信息: Using a shared selector for servlet write/read
四月 10, 2019 9:16:19 下午 org.apache.coyote.AbstractProtocol init
信息: Initializing ProtocolHandler ["http-bio-8443"]
复制代码

从日志看出,tomcat在8090端口以nio模式运行,8443端口以bio模式运行

3种运行模式的适用情况:

bio方式基本被淘汰了

nio方式适用于连接数多,连接时间短的架构,比如QQ,微信

apr方式使用于连接数多,  连接时间长的架构,比如相册服务器,QQ空间相册

如果不指定,tomcat有默认的运行模式,7.0.30以后默认是apr模式

运行模式修改:

平时大家应该很少涉及,这篇文章主要是用来理解的,修改很简单,大把教程,如有需要自行百度


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

创业无畏

创业无畏

彼得· 戴曼迪斯、史蒂芬· 科特勒 / 贾拥民 / 浙江人民出版社 / 2015-8 / 69.90元

 您是否有最大胆的商业梦想?您是否想把一个好主意快速转化为一家市值几百亿甚至几千亿元的公司?《创业无畏》不仅分享了成功创业家的真知灼见,更为我们绘制了一幅激情创业的行动路线图!  创业缺人手怎么办?如何解决钱的问题?把握指数型大众工具,互联网就是你车间,你的仓库。拥有好的创意,自然有人把钱“白白地送给你用”。当你大海捞针的时候,激励性大奖赛会让针自己跑到你的眼前来!  掌握指数级......一起来看看 《创业无畏》 这本书的介绍吧!

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

MD5 加密
MD5 加密

MD5 加密工具

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具