Connector用于接收请求并将请求封装成Request和Response具体处理,底层使用Socket进行连接,Request和Response是按照HTTP协议来封装的,所以Connector同时实现了TCP/IP协议和HTTP协议。
Request和Response封装完后交给Container进行处理,Container就是Servlet的容器,Container处理完返回给Connector,最后Connector使用Socket将处理结果返回给客户端,整个请求就处理结束。
5.1 Connector的结构
Connector中具体是用ProtocolHandler处理请求的,不同的ProtocolHandler代表不同的连接类型。
Http11Protocol使用普通Socket连接,Http11NioProtocol使用NioSocket连接的
ProtocolHandler有三个重要组件:Endpoint、Processor和Adapter。
Endpoint 处理底层Socket的网络连接 —— 实现TCP/IP协议
Process 将Endpoint接收到的Socket封装成Request —— 实现HTTP协议
Adapter 用于将封装好的Request交给Container进行具体处理 —— 将请求适配到Servlet容器进行处理
Endpoint的抽象实现AbstractEndpoint里面定义的Acceptor和AsyncTimeout两个内部类和一个Handler接口
Acceptor 用于监听请求
AsyncTimeout 检查异步request的超时
Handler 处理接收到的Socket,在内部调用Process进行处理
5.2 Connector自身类
Connector类的作用是为了在它创建时 创建ProtocolHandler,然后在生命周期的相关方法中调用了ProtocolHandler的相关生命周期方法。
Connector的使用方法是通过Connector标签配置在conf/server.xml文件中,所以Connector是在Catalina的load方法中根据conf/server.xml配置文件创建Server对象时创建的。Connector的生命周期方法是在Service中调用的。
###Connector的创建
Connector的创建过程主要是初始化ProtocolHandler。根据server.xml配置的Connector的protocol属性,会设置到Connector构造函数的参数中,用于指定ProtocolHandler的类型。
根据protocol参数指定protocolHandlerClassName,根据反射实例化ProtocolHandler并赋值给当前的protocolHandler属性
public Connector(String protocol) {
setProtocol(protocol);
try {
Class<?> clazz = Class.forName(protocolHandlerClassName);
this.protocolHandler = (ProtocolHandler) clazz.getDeclaredConstructor().newInstance();
} catch (Exception e) {
}
}
setProtocol方法设置了protocolHandlerClassName属性
APr是Apache Protable Runtime的缩写,是Apache提供的一个运行时环境,使用它需要安装,Tomcat可以自己检测出来,并使用apr里面的协议。
没有安装apr,会根据配置的HTTP/1.1属性将protocolHandlerClassName设置为org.apache.coyote.http11.Http11Protocol
tomcat8 默认使用 org.apache.coyote.http11.Http11NioProtocol
public void setProtocol(String protocol) {
if (AprLifecycleListener.isAprAvailable()) {
if ("HTTP/1.1".equals(protocol)) {
setProtocolHandlerClassName
("org.apache.coyote.http11.Http11AprProtocol");
} else if ("AJP/1.3".equals(protocol)) {
setProtocolHandlerClassName
("org.apache.coyote.ajp.AjpAprProtocol");
} else if (protocol != null) {
setProtocolHandlerClassName(protocol);
} else {
setProtocolHandlerClassName
("org.apache.coyote.http11.Http11AprProtocol");
}
} else {
if ("HTTP/1.1".equals(protocol)) {
setProtocolHandlerClassName
("org.apache.coyote.http11.Http11Protocol");
} else if ("AJP/1.3".equals(protocol)) {
setProtocolHandlerClassName
("org.apache.coyote.ajp.AjpProtocol");
} else if (protocol != null) {
setProtocolHandlerClassName(protocol);
}
}
}
Connector生命周期处理方法
主要调用了ProtocolHandler的相应生命周期方法
public class Connector extends LifecycleMBeanBase
protected void initInternal() throws LifecycleException {
super.initInternal();
//新建adapter,并设置到protocolHandler
adapter = new CoyoteAdapter(this);
protocolHandler.setAdapter(adapter);
if( null == parseBodyMethodsSet ) {
setParseBodyMethods(getParseBodyMethods());
}
try {
protocolHandler.init();
} catch (Exception e) {
}
// 初始化Initialize mapper listener
mapperListener.init();
}
protected void startInternal() throws LifecycleException {
//判断端口小于0抛出异常
if (getPort() < 0) {
throw new LifecycleException(sm.getString(
"coyoteConnector.invalidPort", Integer.valueOf(getPort())));
}
setState(LifecycleState.STARTING);
try {
protocolHandler.start();
} catch (Exception e) {
}
mapperListener.start();
}
protected void stopInternal() throws LifecycleException {
setState(LifecycleState.STOPPING);
try {
protocolHandler.stop();
} catch (Exception e) {
}
mapperListener.stop();
}
protected void destroyInternal() throws LifecycleException {
//调用MapperListener的destory方法
mapperListener.destroy();
try {
//调用protocolHandler的destory方法
protocolHandler.destroy();
} catch (Exception e) {
}
if (getService() != null) {
//将当前的Connector从service中删除
getService().removeConnector(this);
}
//调用父类的destoryInternel方法
super.destroyInternal();
}
##5.3 ProtocolHandler
Tomcat的ProtocolHandler的继承结构图
ProtocolHandler有一个抽象实现类AbstractProtocol,下面分了两类
1. AbstractAjpProtocol 又分为AjpApr、AjpNio和Ajp协议
2. AbstractHTTP11Protocol 分为AbstractHttp11jsse(Http11Nio和Http11)、Http11Apr
Http11Nio的构造函数中创建了NioEndpoint类型的Endpoint,并新建了Http11ConnectionHandler类型的Handler然后设置到了Endpoint
public class Http11NioProtocol extends AbstractHttp11JsseProtocol<NioChannel> {
public Http11NioProtocol() {
endpoint=new NioEndpoint();
cHandler = new Http11ConnectionHandler(this);
((NioEndpoint) endpoint).setHandler(cHandler);
setSoLinger(Constants.DEFAULT_CONNECTION_LINGER);
setSoTimeout(Constants.DEFAULT_CONNECTION_TIMEOUT);
setTcpNoDelay(Constants.DEFAULT_TCP_NO_DELAY);
}
四个生命周期方法是在父类AbstractProtocol中实现的,主要调用了Endpoing的生命周期方法。
5.4 处理TPC/IP协议的Endpoint
Endpoint用于处理具体连接和传输数据,NioEndpoint继承子AbstractEndpoing,在NioEndpoint中新增了Poller和SocketProcessor内部类
NioEndpoint的init和start方法在父类AbstractEndpoint中
public abstract class AbstractEndpoint<S> {
public void init() throws Exception {
if (this.bindOnInit) {
this.bind();
this.bindState = AbstractEndpoint.BindState.BOUND_ON_INIT;
}
}
public final void start() throws Exception {
if (this.bindState == AbstractEndpoint.BindState.UNBOUND) {
this.bind();
this.bindState = AbstractEndpoint.BindState.BOUND_ON_START;
}
this.startInternal();
}
这两个方法主要调用bind和startInternal方法,他们是模版方法,在NioEndpoint中实现
acceptor用于接收请求,然后交给poller处理
public class NioEndpoint extends AbstractEndpoint<NioChannel> {
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());
// 初始化需要启动accrptor线程的个数,为0则改为1,否则不能工作
// Initialize thread count defaults for acceptor, poller
if (acceptorThreadCount == 0) {
// FIXME: Doesn't seem to work that well with multiple accept threads
acceptorThreadCount = 1;
}
// 初始化需要启动poller的线程个数,<=0 改为1
if (pollerThreadCount <= 0) {
//minimum one poller thread
pollerThreadCount = 1;
}
stopLatch = new CountDownLatch(pollerThreadCount);
// Initialize SSL if needed 是否需要初始化SSL
if (isSSLEnabled()) {
SSLUtil sslUtil = handler.getSslImplementation().getSSLUtil(this);
sslContext = sslUtil.createSSLContext();
sslContext.init(wrap(sslUtil.getKeyManagers()),
sslUtil.getTrustManagers(), null);
SSLSessionContext sessionContext =
sslContext.getServerSessionContext();
if (sessionContext != null) {
sslUtil.configureSessionContext(sessionContext);
}
// Determine which cipher suites and protocols to enable
enabledCiphers = sslUtil.getEnableableCiphers(sslContext);
enabledProtocols = sslUtil.getEnableableProtocols(sslContext);
}
if (oomParachute>0) reclaimParachute(true);
selectorPool.open();
}
public void startInternal() throws Exception {
if (!running) {
running = true;
paused = false;
// Create worker collection 创建Executor
if ( getExecutor() == null ) {
createExecutor();
}
initializeConnectionLatch();
// Start poller threads 启动poller线程
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();
}
//启动acceptor线程
startAcceptorThreads();
}
}
startAcceptorThreads方法,getAcceptorThreadCount()是获取的init方法中处理过的acceptorThreadCount属性,然后启动相应数量的Acceptor线程来接收请求。
protected final void startAcceptorThreads() {
int count = getAcceptorThreadCount();
acceptors = new Acceptor[count];
for (int i = 0; i < count; i++) {
acceptors[i] = createAcceptor();
String threadName = getName() + "-Acceptor-" + i;
acceptors[i].setThreadName(threadName);
Thread t = new Thread(acceptors[i], threadName);
t.setPriority(getAcceptorThreadPriority());
t.setDaemon(getDaemon());
t.start();
}
}
5.5 处理HTTP协议的Processor
Processor用于处理应用层协议(如HTTP),有两个AbstractProcessor抽象类,分别在coyote包和upgrade包。(左边和右边),右边是Servlet3.1后新增的,用于处理HTTP的升级协议。
如http升级WebSocket协议,当正常的Processor处理后如果Socket状态是UPGRADING,那么Endpoint中的Handler将会接着创建并调用upgrade包中的processor进行处理。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qOF5CAUD-1587140773097)(images/image-20200417104222859.png)]
coyote包中的Processor和前面的ProtocolHandler对应,具体实现层协议处理请求的是AbstractAjpProcess和AbstractHttp11Processor中的process方法,这个方法首先封装了Request和Response,然后调用Adapter将请求传递到了Container中,最后对处理的结果进行处理,如有没有启动异步处理、处理过程中有没有抛出异常。
5.6 适配器Adapter
Adapter只有一个实现类,就是connector包下的CoyoteAdapter类。
Processor在process方法中会调用Adapter的sevice方法处理请求
Adapter的service方法主要调用Container管道中的invoke方法处理请求
处理前对Request和Response做了处理,将原来创建的coyote包下的Request和Response封装成connector的Request和Response,并在处理完成后判断是否启动了Comet(长连接模式)和是否启动了异步模式,并作出相应处理。
调用Container管道的相应代码
public class CoyoteAdapter implements Adapter {
public void service(org.apache.coyote.Request req,
org.apache.coyote.Response res)
throws Exception {
Request request = (Request) req.getNote(ADAPTER_NOTES);
Response response = (Response) res.getNote(ADAPTER_NOTES);
if (request == null) {
// Create objects
request = connector.createRequest();
request.setCoyoteRequest(req);
response = connector.createResponse();
response.setCoyoteResponse(res);
// Link objects
request.setResponse(response);
response.setRequest(request);
// Set as notes
req.setNote(ADAPTER_NOTES, request);
res.setNote(ADAPTER_NOTES, response);
// Set query string encoding
req.getParameters().setQueryStringEncoding
(connector.getURIEncoding());
req.getRequestProcessor().setWorkerThreadName(Thread.currentThread().getName());
postParseSuccess = postParseRequest(req, request, res, response);
if (postParseSuccess) {
//check valves if we support async
request.setAsyncSupported(connector.getService().getContainer().getPipeline().isAsyncSupported());
// Calling the container
connector.getService().getContainer().getPipeline().getFirst().invoke(request, response);
这里首先从Connector中获取Service(Connector在initInternal方法中创建CoyoteAdapter时将自己设置到了CoyoteAdapter中),
然后Service中获取Container,接着获取管道的第一个Value,最后调用invoke方法执行请求。
Service中保存的是最顶层的容器,当调用最顶层容器管道的invoke方法时,管道将逐层调用各层容器管道中的Value的invoke方法,知道最后调用Wrapper的管道中的BaseValue(StandardWrapperValve)来处理Filter和Servlet。