上一讲讲解过NIO的框图,可以看来,NIO通道是目前Tomcat7以后的默认的通道的推荐配置,在Tomcat6和以前的配置中,BIO是主流的配置:

只需要修改protocol协议部分即可,而后续还有APR协议,NIO2.0的协议,都是修改这个字段。

对于BIO的整体框图,基本和NIO保持类似,整体流程变化不大:




1.Http11Protocol
与NIO一样,这个Http11Protocol是默认的BIO的http1.1协议的处理类,Tomcat除了有NIO,BIO,其实还有两个通道:

APR是高性能通道,NIO2是基于纯异步IO的通道,这个会在后面的Tomcat中进行讲解。

Http11Protocol类中,依然持有Endpoint和handler的引用:

只不过,BIO对应的Endpoint是JIOEndpoint,对应的handler是Http11ConnectionHandler。

2.JIoEndpoint
JIoEndpoint是BIO的端点类,它和NIO一样,也是维护着线程池,只不过因为没有Selector.select,没有SocketChannel的通道的注册,所以相比NIO模式,没有Poller线程是非常容易理解的,反倒是NIO的三个线程不容易理解,BIO可以看做就是基于Socket进行操作。

首先,初始化的JIoEndpoint的时候,会调用bind方法绑定Serversocket到对应的端口:

bind方法是初始化构造JIoEndpoint的重要步骤,他的主要作用就是建立ServerSocketFactory。
根据SSL信道或者是普通的http的信道,Tomcat都实现了ServerSocketFactory,
普通的http通道的ServerSocketFactory就是DefaultServerSocketFactory类,其工厂方法就是创建ServerSocket,很简单:

对于SSL通道的ServerSocketFactory是JSSEServerSocketFactory,这个类创建的是SSLServerSocket:


其次,JIoEndpoint启动的时候,会将Acceptor线程和工作线程池启动起来:

除此之外,还启动了一个专门的线程,这个线程就是检查异步请求的Timeout的,后续会有专门的介绍针对于Tomcat的异步请求。

工作线程池,使用的就是JDK自带的ThreadPoolExecutor:

可以从线程的堆栈看到,对应的http-bio-8443-exec-n 这种线程都是工作的线程池:

如果在tomcat中没有指定工作线程池的设置,那么都走的是JDK自带的ThreadPoolExecutor的默认值。

3.Acceptor线程
Acceptor线程的主要作用和NIO一样,如果没有网络IO数据,该线程会一直serversocket.accept进行阻塞住。
当有数据的时候,首先将socekt数据设置Connector配置的一些属性,然后将该接力棒传递给工作线程池:

最后一步processSocket方法,非常简单:

直接调用工作线程池,将SocketProcessor作为工作任务传入到工作线程池中,进行执行。

这一步相比NIO的架构,缺少了NIO通道中的PollerEvent一个缓存的队列,NIO中有这样的一个队列是因为需要从Acceptor到Poller线程,中间传递需要一个缓存的地方,而可以看到上述的BIO中的代码,如果工作线程池已经满载了,会根据JDK的ThreadPoolExecutor的策略是缓存,还是直接拒绝,或者是timeout等待,只不过BIO将这块的策略决断交给了ThreadPoolExecutor来做了。

对于Acceptor线程中还有一个重要的作用,就是控制连接的个数,这个在NIO通道的分析中没有讲解,这里看一下
Acceptor线程在while轮询的时候,每一次最开始都会检查一下当前的最大的连接数超出没有,
如果超出了,直接按照上图的序列调用LimitLatch进行锁定。
我们发现,实际上LimitLatch也是模仿JDK中的读写锁,内部持有一个Sync的类,这个类继承了JDK中隐藏功与名的AQS队列,这个AQS队列还是比较著名的,去年在分析JDK源码的时候,多次在n个并发类中都看到过他的踪迹,其实现中几乎全部是CAS锁的实现。

4.SocketProcessor工作任务
SocketProcessor是工作任务,用于传入到工作线程池中,输入就是Acceptor传过来的socketWapper包装:

如果是SSL交互的话,Tomcat开放了握手的这个环节,但是并没有对应的实现,这个是因为SSL下的握手实现在SUN的包中做的,JDK提供的SSLServerSocket的接口已经隐藏了这个细节,我们可以从handshake这个第二步看到:

Tomcat中直接就可以拿到SSLSession,这个类可以获得相当于SSL已经是握手成功了,否则就会出现失败。
对于为什么保留beforeHandShake和handshake这两个步骤,是为了和NIO通道中的SSLEngine交互的接口做个兼容而已。
暂且不用管它,最重要的步骤就是第3步,也就是handler.process这一步,通过Http11ConenctionHandler进行处理http协议,并疯转出Response和Request两个对象,传递给后端的容器。

总结
后续的流程基本上和NIO通道一样,总结一下,BIO的结构因为缺少了selector和轮询,相比NIO少了一部分的内容,整体上就是使用的ServerSocket来进行通信的,一线程一请求的模式,代码看起来清晰易懂,但是,由于BIO的模型比较落后,在大多数的场景下,不如NIO,而现在Tomcat新版本也是NIO是默认的配置。


b.BIO连接器整体框图的更多相关文章

  1. j.APR连接器整体框图(含SSL实现分析)

    APR连接器的思路和bio,nio的整体架构也是类似的,可以看到下面的整体框图: 第一个区别是,对于从Acceptor线程中的socket解析这块,无论是nio还是bio都是在Acceptor线程内直 ...

  2. c.BIO连接器与NIO连接器的对比

    前面两节,我们分别看了BIO和NIO的两种模式Tomcat的实现方式. BIO的方式,就是传统的一线程,一请求的模式,也就是说,当同时又1000个请求过来,如果Tomcat设置了最大Accept线程数 ...

  3. d.BIO连接器与NIO连接器的对比之二

    前面在Tomcat中讲解了两个通道,BIO和NIO,我们这里来通过两端程序,简单模拟两个通道,找找异同点: BIO: 1. public class SocketServer {    public ...

  4. 基于Hi3559AV100的视频采集(VDEC-VPSS-VO)整体框图设计

    下面给出基于Hi3559AV100的视频采集整体设计,具体设计将在后续给出: 图形采集端整体设计 Hi3559AV100软件程序按结构划分可分为4层,第一层是硬件驱动层,第二层是操作系统层,第三层是媒 ...

  5. h.SSL协议栈整体分解

    1.SSL整体框图 SSL协议是应用层次(http协议)和TCP层级的一个可选的位置,可以从下面的图中非常清楚看到该层次: 绿色的框图就是这个SSL./TLS的位置,最右面的SSL/TLS图可以进一步 ...

  6. Vertx.vertx()初始框图和模块

    Vertx.vertx()实例 一.构造方法 1. VertxImpl构造方法 选择 transports protocol , default select 模型 if (options.getPr ...

  7. Tomcat 七 HTTP 连接器

    摘要 本文尝试翻译Tomcat官方文档Apache Tomcat 7连接器,不足之处敬请指正.该文先介绍了Tomcat7 HTTP连接器的属性,包括:公共属性.标准实现.Java TCP套接字属性.B ...

  8. Linux文件IO与通用块层的请求合并

    本文参考https://mp.weixin.qq.com/s/Imt4BW-zoHPpcOpcKZs_AQ, 公众号“Linux阅码场” 请求合并就是将进程内或者进程间产生的在物理地址上连续的多个IO ...

  9. Tomcat SSL的安装及配置中遇到问题

    配置tomcat服务器利用SSL进行加密. 一.生成密钥库 具体生成方式就不讲了,tomcat支持的keystore的格式有JKS,PKCS11和PKCS12 JKS是jdk /bin目录下keyto ...

随机推荐

  1. 列出本机JCE提供者,支持消息摘要算法,支持公钥私钥算法

    import java.security.Provider; import java.security.Security; public class TestBouncyCastle { public ...

  2. Android超类

    android.test.AndroidTestCase    android写测试类的超类 android.database.sqlite.SQLiteOpenHelper   sqllite的超类

  3. SqlSever基础 delete 删除符合特定条件的元素

    y 镇场诗:---大梦谁觉,水月中建博客.百千磨难,才知世事无常.---今持佛语,技术无量愿学.愿尽所学,铸一良心博客.---------------------------------------- ...

  4. 02scala基础

    1.数组操作 1.定长数组:val nums = new Array[Int](10) val s=Array("tom","lisi") *在jvm中,Sca ...

  5. 八、java集合类

    与数组的区别: 数组的长度是固定的,集合的长度是可变的.数组用来存放基本类型的数据,集合用来存放对象的引用. 1.集合类接口的常用方法 COllection接口是层次结构中的根接口,该接口提供了添加和 ...

  6. AOD.net

    ADO.NET中的五个主要对象 Connection 物件Connection 对象主要是开启程序和数据库之间的连结.没有利用连结对象将数据库打开,是无法从数据库中取得数据的.这个物件在ADO.NET ...

  7. poj 3122 (二分查找)

    链接:http://poj.org/problem?id=3122 Pie Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 1 ...

  8. php 连接mysql的问题

    当前我的情况是安装上mysql配置了my.cnf中的socket,并且在指定位置也生成了 mysql.sock 的sock文件,此时我通过php.ini来设置php连接mysql.sock的文件,但是 ...

  9. C# 线程(二):关于线程的相关概念

    From : http://kb.cnblogs.com/page/42528/ 什么是进程? 当一个程序开始运行时,它就是一个进程,进程包括运行中的程序和程序所使用到的内存和系统资源. 而一个进程又 ...

  10. BeanUtils框架的简单运用

    Sun公司的内省API过于繁琐,所以Apache组织结合很多实际开发中的应用场景开发了一套简单.易用的API操作Bean的属性——BeanUtils Beanutils工具包的常用类: •BeanUt ...