Tomcat的默认连接器
剖析tomcat4的默认连接器(现在已不再使用,被另一个运行速度更快的Coyote取代)。
Tomcat的连接器必须满足以下要求:
-
必须实现接口 org.apache.catalina.Connector
-
必须创建请求对象,该请求对象的类必须实现接口 org.apache.catalina.Request
-
必须创建响应对象,该响应对象的类必须实现接口 org.apache.catalina.Response
连接器的主要功能是:等待前来的HTTP请求,创建request 对象和response 对象,然后把request 和response 对象传递给容器。
连接器是通过 org.apache.catalina.Container 的
public void invoke(Request request, Response response) throws IOException, ServletException
方法来传递Request 和Response 对象的。
1.Connector 接口
org.apache.catalina.Connector接口主要有四个方法:
public Container getContainer(); /** 方法返回关联的容器 */
public void setContainer(Container container); /** 方法是用来关联 连接器和容器的 */
public Request createRequest(); /** 为前来的HTTP 请求构造一个请求对象 */
public Response createResponse(); /** 创建一个响应对象 */
2.HttpConnector 类
public final class HttpConnector
implements Connector, Lifecycle, Runnable {
...
}
这个类实现了三个接口。
2.1 创建服务器套接字
该类的initialize()方法会调用一个私有方法open(),open()会返回一个ServerSocket实例,赋值给成员变量serverSocket。
serverSocket = open();
但是,open()方法并没有直接调用ServerSocket类的构造函数,而是从一个服务器套接字工厂得到一个实例。
2.2 维护HttpProcessor实例
HttpConnector类维护了一个HttpProcessor实例池,存储在Stack中。minProcessor的默认值为5,maxProcessor的默认值为20。初始,依据minProcessor的值创建HttpProcessor实例。若请求超过了目前所能处理的范围,则会继续创建。但当实例值达到maxProcessor后,引入的HTTP请求就会被忽略掉。
while (curProcessors < minProcessors) {
if ((maxProcessors > 0) && (curProcessors >= maxProcessors) {
break;
}
HttpProcessor processor = newProcessor();
recycle(processor);
}
其中newProcessor()方法负责创建HttpProcessor实例,并将curProcessors值加一。recycle()方法将新创建的HttpProcessor实例入栈。
每个HttpProcessor实例负责解析HTTP请求行和请求头,填充request对象。因此每个HttpProcessor对象都关联一个request对象和一个response对象。HttpProcessor类的构造函数会调用HttpConnector类的createRequest()和createResponse()方法。
2.3 提供HTTP请求服务
在线程中持续等待客户端的连接请求,当有客户但请求时,他会调用私有方法createProcessor()获得一个HttpProcessor对象。
HttpProcessor processor = createProcessor();
但是大多数时间里,createProcessor()方法并不会创建新的实例,而是从池中获取。如果栈中还有HttpProcessor实例,createProcessor()方法就会从栈中弹出一个HttpProcessor实例,将其返回。如果栈空,已经创建的HttpProcessor实例的数量还没有超过限定的最大值,createProcessor()方法就会创建一个新的实例。但如果HttpProcessor实例的数量已经达到了限定的最大值,createProcessor()方法返回null。此时服务器会简单的关闭套接字,部队这个HTTP请求进行处理:
if (procesor == null) {
try {
log (sm.getString("httpConnector.noProcessor"));
socket.close();
}
...
continue;
}
若createProcessor()方法放回的不是null,则会将客户端套接字传入到HttpProcessor类的assign()方法中:
processor.assign(socket);
3.HttpProcessor 类
该类和上篇博客无大差异。主要通过process()方法解析连接,解析请求行,解析请求头。
3.1解析连接:
private void parseConnection(Socket socket) throws IOException, ServletException {
if (debug >= 2)
log("parseConnection: address=" + socket.getInetAddress() + ", port=" + connector.getPort());
((HttpRequestImpl) request).setInet(socket.getInetAddress());
if (proxyPort != 0)
request.setServerPort(proxyPort);
else
request.setServerPort(serverPort);
request.setSocket(socket);
}
解析请求行和请求头在上篇博客parseRequest 和 parseHeaders 方法中有详细描述。
这就是tomcat4自带的连接器。