tomcat主要组件
Server服务器:可以理解成tomcat,一个Server可以包含多个Service服务
Service服务:管理Connetor和Container,一个service有一个Container和多个Connetor
Connetor:连接器,负责接收请求
Container:容器,主要负责处理请求
Session管理器:负责管理session,例如:session的创建和删除等
上一张架构图:
架构重点是Connetor和Container
Connetor
Connetor连接器,可以看到http请求过来是由Connetor来接收,Connetor接受之后最会使用HttpProcessor类去解析http请求,这边往往为了提高效率,利用了懒加载,如果我们没有程序没有调用到请求过来的信息,是不会去解析的。
大概的解析过程:
读取套接字的输入流
解析请求行
解析请求头
解析Cookie
获取参数
tomcat7中的Connetor部分代码,tomcat7使用的连接器叫Coyote
/**
* Implementation of a Coyote connector.
*
* @author Craig R. McClanahan
* @author Remy Maucherat
*/
public class Connector extends LifecycleMBeanBase {
private static final Log log = LogFactory.getLog(Connector.class);
protected String protocolHandlerClassName =
"org.apache.coyote.http11.Http11Protocol";
/**
* Alternate flag to enable recycling of facades.
*/
public static final boolean RECYCLE_FACADES =
Boolean.parseBoolean(System.getProperty("org.apache.catalina.connector.RECYCLE_FACADES", "false"));
// ------------------------------------------------------------ Constructor
public Connector() {
this(null);
}
//去实例化了一个org.apache.coyote.http11.Http11Protocol
public Connector(String protocol) {
setProtocol(protocol);
// Instantiate protocol handler
try {
Class<?> clazz = Class.forName(protocolHandlerClassName);
this.protocolHandler = (ProtocolHandler) clazz.getDeclaredConstructor().newInstance();
} catch (Exception e) {
log.error(sm.getString(
"coyoteConnector.protocolHandlerInstantiationFailed"), e);
}
// Default for Connector depends on this (deprecated) system property
if (Boolean.parseBoolean(System.getProperty("org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH", "false"))) {
encodedSolidusHandling = EncodedSolidusHandling.DECODE;
}
}
}
Http11Protocal的代码中创建了Processor类
@Override
protected Http11Processor createProcessor() {
Http11Processor processor = new Http11Processor(
proto.getMaxHttpHeaderSize(), proto.getRejectIllegalHeader(),
(JIoEndpoint)proto.endpoint, proto.getMaxTrailerSize(),
proto.getAllowedTrailerHeadersAsSet(), proto.getMaxExtensionSize(),
proto.getMaxSwallowSize(), proto.getRelaxedPathChars(),
proto.getRelaxedQueryChars());
proto.configureProcessor(processor);
processor.setDisableKeepAlivePercentage(proto.getDisableKeepAlivePercentage());
register(processor);
return processor;
}
Container
连接器处理后,会解析请求,生成request对象和response对象,传递给Container
四种Container
- Engine :表示servlet引擎,用来管理多个虚拟站点
- Host:代表一个虚拟主机,一个虚拟主机地址下可以部署多个web引用程序
- Context:表示一个web程序,可以简单的认位tomcat目录webapps下的xxx.war包就是一个Contxt容器
- Wrapper :表示一个servlet
容器实现了相同的Container接口,并且父容器和子容器利用组合联系起来,是1对多的关系,可以看看上面的图。
下图是容器类的关系图。
这样设置有什么好处?
可以看到Container容器中有一个start和stop方法,容器使用了组合模式,所以我们在启动和停止的时候,只要启动/停止最上层容器就可以启动/停止所有的容器了。