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的工作交给内核来做了
相关推荐
callJJ34 分钟前
从 0 开始理解 Spring 的核心思想 —— IoC 和 DI(1)
java·开发语言·spring boot·后端·spring·restful·ioc di
编程乐学(Arfan开发工程师)6 小时前
56、原生组件注入-原生注解与Spring方式注入
java·前端·后端·spring·tensorflow·bug·lua
周某某~7 小时前
七.适配器模式
java·设计模式·适配器模式
奔跑的小十一8 小时前
JDBC接口开发指南
java·数据库
刘大猫.8 小时前
业务:资产管理功能
java·资产管理·资产·资产统计·fau·bpb·mcb
YuTaoShao8 小时前
Java八股文——JVM「内存模型篇」
java·开发语言·jvm
开开心心就好9 小时前
电脑扩展屏幕工具
java·开发语言·前端·电脑·php·excel·batch
零叹10 小时前
篇章十 数据结构——排序
java·数据结构·算法·排序算法