java nio源码_Java编程架构详解——Tomcat 中的 NIO 源码分析

文将介绍 Tomcat 中的 NIO 使用,使大家对 Java NIO 的生产使用有更加直观的认识。

虽然本文的源码篇幅也不短,但是 Tomcat 的源码毕竟不像 Doug Lea 的并发源码那么“变态”,对于大部分读者来说,阅读难度比之前介绍的其他并发源码要简单一些,所以读者不要觉得有什么压力。

本文基于 Tomcat 当前(2018-03-20)最新版本 9.0.6。

先简单画一张图示意一下本文的主要内容:

AAffA0nNPuCLAAAAAElFTkSuQmCC

目录

源码环境准备

endpoint

init 过程分析

start 过程分析

Acceptor

Poller

processKey

总结

源码环境准备

Tomcat 9.0.6 下载地址:https://tomcat.apache.org/download-90.cgi

由于上面下载的 tomcat 的源码并没有使用 maven 进行组织,不方便我们看源码,也不方便我们进行调试。这里我们将使用 maven 仓库中的 tomcat-embed-core,自己编写代码进行启动的方式来进行调试。

首先,创建一个空的 maven 工程,然后添加以下依赖。

org.apache.tomcat.embedgroupId>

tomcat-embed-coreartifactId>

9.0.6version>

dependency>

上面的依赖,只会将 tomcat-embed-core-9.0.6.jar 和 tomcat-annotations-api-9.0.6.jar 两个包引进来,对于本文来说,已经足够了,如果你需要其他功能,需要额外引用其他的依赖,如 Jasper。

然后,使用以下启动方法:

public static void main(String[] args) throws LifecycleException {

Tomcat tomcat = new Tomcat();

Connector connector = new Connector("HTTP/1.1");

connector.setPort(8080);

tomcat.setConnector(connector);

tomcat.start();

tomcat.getServer().await();

}

经过以上的代码,我们的 Tomcat 就启动起来了。

Tomcat 中的其他接口感兴趣的读者请自行探索,如设置 webapp 目录,设置 resources 等

这里,介绍第一个重要的概念:Connector。在 Tomcat 中,使用 Connector 来处理连接,一个 Tomcat 可以配置多个 Connector,分别用于监听不同端口,或处理不同协议。

在 Connector 的构造方法中,我们可以传 HTTP/1.1 或 AJP/1.3 用于指定协议,也可以传入相应的协议处理类,毕竟协议不是重点,将不同端口进来的连接对应不同处理类才是正道。典型地,我们可以指定以下几个协议处理类:

org.apache.coyote.http11.Http11NioProtocol:对应非阻塞 IO

org.apache.coyote.http11.Http11Nio2Protocol:对应异步 IO

org.apache.coyote.http2.Http2Protocol:对应 http2 协议,对 http2 感兴趣的读者,赶紧看起来吧。

本文的重点当然是非阻塞 IO 了,之前已经介绍过异步 IO的基础知识了,读者看完本文后,如果对异步 IO 的处理流程感兴趣,可以自行去分析一遍。

如果你使用 9.0 以前的版本,Tomcat 在启动的时候是会自动配置一个 connector 的,我们可以不用显示配置。

9.0 版本的 Tomcat#start() 方法:

public void start() throws LifecycleException {

getServer();

server.start();

}

8.5 及之前版本的 Tomcat#start() 方法:

public void start() throws LifecycleException {

getServer();

// 自动配置一个使用非阻塞 IO 的 connector

getConnector();

server.start();

}

endpoint

前面我们说过一个 Connector 对应一个协议,当然这描述也不太对,NIO 和 NIO2 就都是处理 HTTP/1.1 的,只不过一个使用非阻塞,一个使用异步。进到指定 protocol 代码,我们就会发现,它们的代码及其简单,只不过是指定了特定的 endpoint。

打开 Http11NioProtocol 和 Http11Nio2Protocol源码,我们可以看到,在构造方法中,它们分别指定了 NioEndpoint 和 Nio2Endpoint。

// 非阻塞模式

public class Http11NioProtocol extends AbstractHttp11JsseProtocol {

public Http11NioProtocol() {

// NioEndpoint

super(new NioEndpoint());

}

...

}

// 异步模式

public class Http11Nio2Protocol extends AbstractHttp11JsseProtocol {

public Http11Nio2Protocol() {

// Nio2Endpoint

super(new Nio2Endpoint());

}

...

}

作者:慕容千语

链接:https://www.jianshu.com/p/c6d57441da5b

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值