设为首页 - 加入收藏 ASP站长网(Aspzz.Cn)- 科技、建站、经验、云计算、5G、大数据,站长网!
热搜: 数据 创业者 手机
当前位置: 首页 > 服务器 > 系统 > 正文

Tomcat 中的 NIO 源码分析

发布时间:2020-01-07 12:09 所属栏目:52 来源:站长网
导读:
导读:副标题#e# 虽然本文的源码篇幅也不短,但是 Tomcat 的源码毕竟不像 Doug Lea 的并发源码那么变态,对于大部分读者来说,阅读难度比之前介绍的其他并发源码要简单一些,所以读者不要觉得有什么压力。 本文基于 Tomcat 当前(2018-03-20)最新版本 9.0.6。 先简

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

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

Tomcat 中的 NIO 源码分析

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

Tomcat 中的 NIO 源码分析

目录

源码环境准备

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

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

<dependency> 

<groupId>org.apache.tomcat.embed</groupId> 

<artifactId>tomcat-embed-core</artifactId> 

<version>9.0.6</version> 

</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.Htt***rotocol:对应 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 classHttp11NioProtocolextendsAbstractHttp11JsseProtocol<NioChannel> { 

publicHttp11NioProtocol { 

// NioEndpoint 

super(new NioEndpoint); 

... 

// 异步模式 

public classHttp11Nio2ProtocolextendsAbstractHttp11JsseProtocol<Nio2Channel> { 

 

publicHttp11Nio2Protocol { 

// Nio2Endpoint 

super(new Nio2Endpoint); 

... 

这里介绍第二个重要的概念:endpoint。Tomcat 使用不同的 endpoint 来处理不同的协议请求,今天我们的重点是 NioEndpoint,其使用非阻塞 IO 来进行处理 HTTP/1.1 协议的请求。

(编辑:ASP站长网)

网友评论
推荐文章
    热点阅读