Tomcat线程模型

目录

[1 Linux I/O模型](#1 Linux I/O模型)

[2 Linux I/O模型分类](#2 Linux I/O模型分类)

[3 Tomcat支持的I/O模型](#3 Tomcat支持的I/O模型)

[4 Tomcat I/O模型选型](#4 Tomcat I/O模型选型)

[5 Tomcat NIO实现](#5 Tomcat NIO实现)

[6 Tomcat异步IO实现](#6 Tomcat异步IO实现)


1 Linux I/O模型
  • I/O:在计算机内存和外部设备之间拷贝数据的过程

  • 程序通过cpu向外部设备发出读指令,数据从外部设置拷贝至内存需要一段时间,这段时间cpu是空闲的,此时程序会有两种选择:

    • 让出cpu资源,让其干其他事
    • 继续让cpu不停地查询数据是否拷贝完成
  • 采用哪种策略就是I/O模型需要解决的事

  • 一个进程的地址空间分为用户空间和内核空间

  • 用户程序只能访问用户空间,内核进程可以访问整个进程空间

  • 只有内核才可以直接访问各种硬件资源,比如磁盘和网卡

  • 当cpu从网络读取数据时,分为两个阶段

    • 数据准备阶段:将数据从网卡拷贝到内核空间
    • 数据拷贝阶段:将数据从内核空间拷贝到用户空间
  • 不同的I/O模型对以上两个步骤有不同的实现

2 Linux I/O模型分类
  • 同步阻塞I/O

  • 同步非阻塞I/O

  • I/O多路复用

  • 信号驱动式I/O

  • 异步I/O

  • 阻塞或非阻塞是指应用程序在发起I/O操作时,是立即返回还是等待

  • 同步或异步是指应用程序在与内核通信时,数据从内核空间到应用空间的拷贝,是由内核主动发起还是由应用程序

java中支持的I/O模型有同步阻塞I/O,I/O多路复用,异步I/O等

3 Tomcat支持的I/O模型

tomcat中支持的I/O模型有:

|-------------------|----------------------------------------------------------------------------------------------------------|
| IO模型 | 描述 |
| BIO(BioEndpoint) | 同步阻塞式IO 该模式下每个请求都会占用一个线程,对性能开销大,不适合高并发场景 但是稳定,适合连接数目小并且固定架构 |
| NIO(NioEndpoint) | IO多路复用 tomcat8之后默认采用该IO模型 NIO方式适合连接数多并且连接比较短的架构 |
| AIO(Nio2Endpoint) | 异步非阻塞式IO 启动时执行处理连接方法,此时直接返回 当发生连接事件时,执行回调方法完成连接, 然后执行处理读事件方法,也是直接返回 当发生读事件时,执行对应的回调方法 适用于连接数较多且连接事件较长的应用 |
| APR(AprEndpoint) | Apache Portable Runtime,是Apache HTTP服务器的支持库 AprEndpoint是通过JNI调用APR本地库而实现非阻塞IO的 使用需要编译安装APR库 |

Linux内核没有很完善地支持异步IO模型

因此JVM并没有采用原生的Linux异步IO,而是在应用层面通过epoll模拟了异步IO模型

所以在Linux平台上,Java NIO和Java NIO2底层都是通过epoll来实现的

4 Tomcat I/O模型选型
  • IO调优实际上是连接器类型的选择
  • 一般情况默认都是NIO
  • 当web应用启用TLS加密传输并且对性能要求极高时,考虑使用APR
  • APR是通过openssl来处理TLS握手和加解密的,openssl本身采用c语言开发,并且对TLS通信做了优化,所以性能比java要高的
  • 如果tomcat运行在windows平台,并且http请求的数据量比较大,考虑采用NIO2
  • windows从操作系统平面实现了真正意义上的异步IO,如果传输的数据量较大时,异步IO的效果就能显现出来
  • 当tomcat运行在linux平台上时,建议使用NIO,在linux平台上nio和nio2都是通过epoll来实现的,但是nio更简单高效
  • 指定IO模型时修改Connector标签的protocol属性
5 Tomcat NIO 实现
  • tomcat中Endpoint组件的主要工作就是处理I/O
  • NioEndpoint利用java NIO API实现了多路复用I/O模型
  • NioEndpoint是基于主从Reactor多线程模型设计的
  • LimitLatch是连接控制器,负责控制最大连接数,默认是8192,当连接数达到最大是阻塞线程,直到后续组件处理完一个连接后将连接数减1
  • 到达最大连接数后操作系统底层还是会接受客户端连接,但是用户层已经不在接收
  • Acceptor跑在一个单独的线程里,在死循环内调用acceptor方法接收新连接,一旦有新的连接请求到来,accept方法返回一个Channel对象,将Channel帝乡交给Poller去处理
  • Poller也跑在单独的线程,Poller内部维护一个Selector,将Acceptor传递过来的Channel注册到Selector读事件,一旦发生读事件,就生成一个SockeProcessor任务对象扔给Executor处理
  • Executor就是线程池,负责运行SockeProcessor任务类,SockeProcessor的run方法中会调用Http11Processor来读取和解析请求数据,Http11Processor是应用层协议的封装,它负责调用容器获得响应并将响应通过Channel写出
6 Tomcat 异步 IO 实现
  • NIO和NIO2最大的区别是NIO2时异步的
  • 异步不需要应用程序自己去触发数据从内核空间到用户空间的拷贝
  • NioEndPoint中没有Poller组件,也就是没有Selector
  • 在异步I/O模式下,Selector的工作交给内核来做了
相关推荐
源码_V_saaskw11 分钟前
JAVA图文短视频交友+自营商城系统源码支持小程序+Android+IOS+H5
java·微信小程序·小程序·uni-app·音视频·交友
超浪的晨21 分钟前
Java UDP 通信详解:从基础到实战,彻底掌握无连接网络编程
java·开发语言·后端·学习·个人开发
双力臂4041 小时前
Spring Boot 单元测试进阶:JUnit5 + Mock测试与切片测试实战及覆盖率报告生成
java·spring boot·后端·单元测试
Edingbrugh.南空1 小时前
Aerospike与Redis深度对比:从架构到性能的全方位解析
java·开发语言·spring
QQ_4376643142 小时前
C++11 右值引用 Lambda 表达式
java·开发语言·c++
永卿0012 小时前
设计模式-迭代器模式
java·设计模式·迭代器模式
誰能久伴不乏2 小时前
Linux如何执行系统调用及高效执行系统调用:深入浅出的解析
java·服务器·前端
慕y2742 小时前
Java学习第七十二部分——Zookeeper
java·学习·java-zookeeper
midsummer_woo3 小时前
基于spring boot的医院挂号就诊系统(源码+论文)
java·spring boot·后端
_Aaron___3 小时前
面向对象的三大特性---多态
java