Tomcat NIO

说起Tomcat的NIO,不得不提的就是Connector这个Tomcat组件。Connector是Tomcat的连接器,其主要任务是负责处理收到的请求,并创建一个Request和Response的对象,然后用一个线程用于处理请求,Connector会把Request和Response对象传递给该线程,该线程的具体的处理过程是Container容器的事了。

tomcat启动过程中,会初始化Connector,并调用Connector的startInternal()方法开启Connector,开始监听、处理请求。

 

想了解Tomcat NIO的工作方式,就得先了解一下Connector的实现原理。下面从三个方面来了解一下Connector组件:Connector的数据结构、Connector初始化以及Connector开启。

 

Connector Connector的数据结构

先了解一下Connector的数据结构。Connector的一个主要的属性:ProtocolHandler protocolHandler(协议)

 

protocolHandler(协议)

维护服务器使用的协议,如http1.1等。ProtocolHandler是接口,实现类有Http11Nio2Protocol 、Http11Nio2Protocol等

维护服务提供的IO方式,负责EndPoint的初始化、启动。目前有BIO、NIO、AIO等IO方式,来实现监听端口、读写socket数据的功能。通过EndPoint封装实现不同的IO方式

EndPoint监听到IO读写,交给Tomcat线程池中的一个线程来处理,SocketProcessor会根据protocolHandler采用的协议,调用协议的process方法处理请求。

维护adapter(适配器),可以将请求/响应数据进行适配

 

protocolHandler会找到socket对应的处理器(如Http11Processor),然后进行数据读写、适配,处理。请求由adapter最终会交给servlet处理

 

常说的BIO、NIO,主要的应用就在protocolHandler中。protocolHandler负责维护Connector使用的协议以及IO方式。在protocolHandler中,不同的IO方式,会使用不同的EndPoint,具体采用哪种IO方式,取决于采用哪个EndPoint,每一个EndPoint的实现类,都封装了一种IO策略。若采用NIO,则为NioEndpoint。

 

Connector初始化

 

创建Connector时,会拿到Tomcat目录下conf/server.xml中Connector的协议配置,利用反射创建ProtocolHandler:

/** * Coyote Protocol handler class name. * Defaults to the Coyote HTTP/1.1 protocolHandler. */ protected String protocolHandlerClassName = "org.apache.coyote.http11.Http11NioProtocol"; public Connector(String protocol) { //设置protocolHandlerClassName类名 setProtocol(protocol); // Instantiate protocol handler ProtocolHandler p = null; try { //根据server.xml中<connector/>标签的protocol属性值,获取到对应的http协议类 Class<?> clazz = Class.forName(protocolHandlerClassName); p = (ProtocolHandler) clazz.getConstructor().newInstance(); } catch (Exception e) { log.error(sm.getString( "coyoteConnector.protocolHandlerInstantiationFailed"), e); } finally { this.protocolHandler = p; } if (Globals.STRICT_SERVLET_COMPLIANCE) { uriCharset = StandardCharsets.ISO_8859_1; } else { uriCharset = StandardCharsets.UTF_8; } } //设置protocolHandlerClassName类名 public void setProtocol(String protocol) { boolean aprConnector = AprLifecycleListener.isAprAvailable() && AprLifecycleListener.getUseAprConnector(); //若配置了protocol="HTTP/1.1"或者没配,则默认是Http11NioProtocol或者Http11AprProtocol if ("HTTP/1.1".equals(protocol) || protocol == null) { if (aprConnector) { setProtocolHandlerClassName("org.apache.coyote.http11.Http11AprProtocol"); } else { setProtocolHandlerClassName("org.apache.coyote.http11.Http11NioProtocol"); } } else if ("AJP/1.3".equals(protocol)) { if (aprConnector) { setProtocolHandlerClassName("org.apache.coyote.ajp.AjpAprProtocol"); } else { setProtocolHandlerClassName("org.apache.coyote.ajp.AjpNioProtocol"); } } else { //直接取配置的类名 setProtocolHandlerClassName(protocol); } }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zypsjy.html