概述
Tomcat最底层是使用Socket来进行连接的,而Connector的作用就是将接受到的请求转换为Request和Response。Request和Response是按照HTTP协议来封装的,封装完成后就交给Container进行处理。Container处理完成后又返回给Connector,由Connector返给客户端
Connector的结构
Connector主要是通过ProtocolHandler来处理请求的。不用的ProtocolHandler代表不同的连接类型。例如Http11Protocal使用普通的socket(同步处理),http11NioProtocal使用的NioSocket来链接。ProtocolHandler里面有3个很重要的组件:
- Endpoint:处理最底层的Socket链接(一串字符流)
- Processor:用户将Endpoint收到的内容封装成Requst(也就是需要解析HTTP协议)
- Adapter将请求适配到合适的Sevlet容器
ProtocolHandler
<!-- 定义一个Connector,在8080端口箭头HTTP的请求 -->
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
<!-- 定义一个Connector,在8009端口箭头AJP的请求 -->
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
在server.xml中就有Connector的配置。图中配置了监听HTTP请求和AJP请求
ProtocolHandler有一个抽象实现类AbstractProtocal,下面有3个子类,分别是对Ajp,Http,spdy协议的实现
- Ajp(apache JServ Protocol),Apache的定向包协议,主要用于前端服务器(如Apache)之间的通信,他是长连接。
- Http:略
- Spdy: 是google开发的协议,效率比Http搞,但使用不广泛
在Connector中默认是使用org.apache.coyote.http11.Http11NioProtocol。
Endpoint
Endpoint用于处理具体的连接和数据传输,实现是比较复杂的。NioEndpoint集成AnstractEndpoint,AnstractEndpoint也是一个模板类,例如start()方法在AnstractEndpoint中,其中bind()方法由子类去实现
public final void start() throws Exception {
if (bindState == BindState.UNBOUND) {
bind();
bindState = BindState.BOUND_ON_START;
}
startInternal();
}
public abstract void bind() throws Exception;
NioEndpoint的bind()方法就是初始化ServerSocketChannel和Selector
public void bind() throws Exception {
serverSock = ServerSocketChannel.open();
socketProperties.setProperties(serverSock.socket());
InetSocketAddress addr = (getAddress()!=null?new InetSocketAddress(getAddress(),getPort()):new InetSocketAddress(getPort()));
serverSock.socket().bind(addr,getBacklog());
serverSock.configureBlocking(true); //mimic APR behavior
serverSock.socket().setSoTimeout(getSocketProperties().getSoTimeout());
// Initialize thread count defaults for acceptor, poller
if (acceptorThreadCount == 0) {
// FIXME: Doesn't seem to work that well with multiple accept threads
acceptorThreadCount = 1;
}
if (pollerThreadCount <= 0) {
//minimum one poller thread
pollerThreadCount = 1;
}
stopLatch = new CountDownLatch(pollerThreadCount);
// Initialize SSL if needed
initialiseSsl();
selectorPool.open();
}
启动是在startInternal()方法中,主要做了2个事情,初始化Poller线程和Accept线程,Accept负责接收Socket请求,然后具体的处理方法是在Poller线程中。(Accept和Poller是内部类)
public void startInternal() throws Exception {
if (!running) {
running = true;
paused = false;
processorCache = new SynchronizedStack<>(SynchronizedStack.DEFAULT_SIZE,
socketProperties.getProcessorCache());
eventCache = new SynchronizedStack<>(SynchronizedStack.DEFAULT_SIZE,
socketProperties.getEventCache());
nioChannels = new SynchronizedStack<>(SynchronizedStack.DEFAULT_SIZE,
socketProperties.getBufferPool());
// Create worker collection
if ( getExecutor() == null ) {
createExecutor();
}
initializeConnectionLatch();
// Start poller threads
pollers = new Poller[getPollerThreadCount()];
for (int i=0; i<pollers.length; i++) {
pollers[i] = new Poller();
Thread pollerThread = new Thread(pollers[i], getName() + "-ClientPoller-"+i);
pollerThread.setPriority(threadPriority);
pollerThread.setDaemon(true);
pollerThread.start();
}
startAcceptorThreads();
}
}
Processor
主要用于处理应用层协议(如HTTP),分别由3个基本协议对应3个基本的抽象类
Adapter
Adapter只有一个实现类,就是CoyoteAdapter类。
- 把org.apache.coyote包下的Request和Response封装为org.apache.catalina.connector的Request和Response
- 从Serivce中的Container获取第一个管道,然后调用管道的invoker方法(管道可以理解为一个过滤链,最后会调用StandardWrapperValue来处理Filter和Servlet)