tomcat的三种运行模式+JAVA NIO

转载自:https://www.iteye.com/blog/uule-2438763

详解Tomcat三种运行模式(BIO, NIO, APR)的比较和场景分析

在这里插入图片描述NIO 方式:
在这里插入图片描述Tomcat8.0起已经默认nio模式,不需要做修改,BIO模式也已经抛弃了,今天主要介绍下tomcat的三种运行模式:BIO、NIO、ARP。

TOMCAT BIO、NIO、AIO适用场景分析:

BIO方式适用于连接数目比较小且固定的架构,这种方式对服务器资源要求比较高,并发局限于应用中,JDK1.4以前的唯一选择,但程序直观简单易理解。

NIO方式适用于【连接数目多且连接比较短】(轻操作)的架构,比如聊天服务器,并发局限于应用中,编程比较复杂,JDK1.4开始支持。

AIO方式使用于【连接数目多且连接比较长】(重操作)的架构,比如相册服务器,充分调用OS参与并发操作,编程比较复杂,JDK7开始支持。

这三种模式的不同之处如下:

BIO:

【一个线程处理一个请求】。

缺点:【并发量高时,线程数较多,浪费资源】。

Tomcat7或以下,在Linux系统中默认使用这种方式。

NIO:

【利用Java的异步IO处理】,可以通过【少量的线程处理大量的请求】。

Tomcat8在Linux系统中默认使用这种方式。

APR:

即Apache Portable Runtime,从操作系统层面解决io阻塞问题。

Tomcat7或Tomcat8在Win7或以上的系统中启动默认使用这种方式。

=============================================================

NIO是什么?适用于何种场景?
NIO模型,select/epoll的区别,多路复用的原理
原生的 NIO 在 JDK 1.7 版本存在 epoll bug

JAVA BIO:

来一个新的连接,我们就新开一个线程来处理这个连接,之后的操作全部由那个线程来完成。

那么,这个模式下的性能瓶颈在哪里呢?

首先,每次来一个连接都开一个新的线程这肯定是不合适的。当活跃连接数在几十几百的时候当然是可以这样做的,但如果活跃连接数是几万几十万的时候,这么多线程明显就不行了。

【每个线程都需要一部分内存,内存会被迅速消耗】,同时,【线程切换的开销也非常大】。

其次,阻塞操作在这里也是一个问题。首先,【accept() 是一个阻塞操作,当 accept() 返回的时候,代表有一个连接可以使用了】,我们这里是马上就新建线程来处理这个 SocketChannel 了,

但是,【但是这里不代表对方就将数据传输过来了】。所以,SocketChannel#read 方法将阻塞,等待数据,明显这个等待是不值得的。

同理,write 方法也需要等待通道可写才能执行写入操作,这边的阻塞等待也是不值得的。

JAVA NIO:

非阻塞 IO 的核心在于【使用一个 Selector 来管理多个通道】,可以是 SocketChannel,也可以是 ServerSocketChannel,【将各个通道注册到 Selector上,指定监听的事件】。

之后可以【只用一个线程来轮询这个 Selector,看看上面是否有通道是准备好的】,当通道准备好可读或可写,然后才去开始真正的读写,这样速度就很快了。我们就完全没有必要给每个通道都起一个线程。

Channel

所有的 NIO 操作始于通道,通道是数据来源或数据写入的目的地,主要地,我们将关心 java.nio 包中实现的以下几个 Channel:

FileChannel:文件通道,用于文件的读和写,FileChannel 不支持非阻塞

DatagramChannel:用于 UDP 连接的接收和发送

SocketChannel:把它理解为 TCP 连接通道,简单理解就是 TCP 客户端

ServerSocketChannel:TCP 对应的服务端,用于监听某个端口进来的请求

Selector

NIO 三大组件就剩 Selector 了,【Selector 建立在非阻塞的基础之上】,大家经常听到的 【多路复用】 在 Java 世界中指的就是它,【用于实现一个线程管理多个 Channel】。

select:上世纪 80 年代就实现了,它支持注册 FD_SETSIZE(1024) 个 socket,在那个年代肯定是够用的,不过现在嘛,肯定是不行了。

poll:1997 年,出现了 poll 作为 select 的替代者,最大的区别就是,【poll 不再限制 socket 数量】。

【select 和 poll 都有一个共同的问题,那就是它们都只会告诉你有几个通道准备好了,但是不会告诉你具体是哪几个通道】。所以,【一旦知道有通道准备好以后,自己还是需要进行一次扫描】,显然这个不太好,通道少的时候还行,一旦通道的数量是几十万个以上的时候,扫描一次的时间都很可观了,时间复杂度 O(n)。所以,后来才催生了以下实现。

epoll:2002 年随 Linux 内核 2.5.44 发布,【epoll 能直接返回具体的准备好的通道】,时间复杂度 O(1)。

下面对 Java 异步 IO 进行实践性的介绍。

总共有三个类需要我们关注,分别是 AsynchronousSocketChannel,AsynchronousServerSocketChannel 和 AsynchronousFileChannel,只不过是在之前介绍的 FileChannel、SocketChannel 和 ServerSocketChannel 的类名上加了个前缀 Asynchronous。

Java 异步 IO 提供了两种使用方式,分别是返回 Future 实例和使用回调函数。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值