tomcat 简介
官网:Apache Tomcat 10 (10.0.14) - Documentation Index
****************
tomcat 架构
组件说明
bootstrap:应用服务器启动入口,通过反射调用创建catalina实例
catalina:解析server.xml创建各个组件,启动、停止应用服务器
server:表示这个servlet容器,整个tomcat只有一个server实例
service:包含一个或者多个connector集合、以及一个由所有connector共享的container组成,
同一个tomcat(server)实例中可有任意多个service实例,彼此之间相互独立
connector:tomcat链接器,监听读取scoket请求,将其交由container处理
protocolhandler:协议处理器,针对不同协议和i/o方式,提供不同的实现
abstractEndpoint:socket监听端口,监听请求
processor:读取请求数据
mapper:维护容器映射信息,按照映射规则查找容器
mapperListener:容器组件状态变更时,注册或者取消对应的容器信息
coyoteAdapter:使用适配器模式实现connector、mapper、container的解耦,
coyote是connector的默认实现,coyoteAdapter是coyote的适配器
container:处理客户端请求,并返回响应数据,包括engine、host、context、wrapper
engine:表示servlet容器引擎,是获取目标容器的入口,不直接处理请求
host:servlet引擎的虚拟机,与服务器的网名(如www.baidu.com)有关,客户端可使用这个网名连接服务器
context:表示servletContext,是一个独立的web应用
wrapper:表示servletContext定义的servlet
pipeline:构造容器职责链,一次处理容器接收到的请求
pipeline维护了一个最基本的valve,位于职责链的末端,负责请求处理和响应输出
valve:位于职责链上,负责处理请求,按顺序依次添加到pipeline,后添加的valve位于pipeline最前面
executor:tomcat组件使用的线程池,实现对客户端请求的并发处理
bootstrap:服务器启动入口,反射调用创建catalina
public final class Bootstrap {
private static final Log log = LogFactory.getLog(Bootstrap.class);
private static final Object daemonLock = new Object();
private static volatile Bootstrap daemon = null;
private static final File catalinaBaseFile;
private static final File catalinaHomeFile;
private static final Pattern PATH_PATTERN = Pattern.compile("(\"[^\"]*\")|(([^,])*)");
private Object catalinaDaemon = null;
ClassLoader commonLoader = null;
ClassLoader catalinaLoader = null;
ClassLoader sharedLoader = null;
public Bootstrap() {
}
public void init() throws Exception {
this.initClassLoaders();
Thread.currentThread().setContextClassLoader(this.catalinaLoader);
SecurityClassLoad.securityClassLoad(this.catalinaLoader);
if (log.isDebugEnabled()) {
log.debug("Loading startup class");
}
Class<?> startupClass = this.catalinaLoader.loadClass("org.apache.catalina.startup.Catalina");
//使用类加载器加载Catalina类
Object startupInstance = startupClass.getConstructor().newInstance();
//反射调用创建catalina实例
if (log.isDebugEnabled()) {
log.debug("Setting startup class properties");
}
String methodName = "setParentClassLoader";
Class<?>[] paramTypes = new Class[]{Class.forName("java.lang.ClassLoader")};
Object[] paramValues = new Object[]{this.sharedLoader};
Method method = startupInstance.getClass().getMethod(methodName, paramTypes);
method.invoke(startupInstance, paramValues);
this.catalinaDaemon = startupInstance;
}
public static void main(String[] args) {
synchronized(daemonLock) {
if (daemon == null) {
Bootstrap bootstrap = new Bootstrap();
try {
bootstrap.init(); //调用初始化方法,创建catalina实例
} catch (Throwable var5) {
handleThrowable(var5);
var5.printStackTrace();
return;
}
daemon = bootstrap;
} else {
Thread.currentThread().setContextClassLoader(daemon.catalinaLoader);
}
}
try { //根据命令参数启动或者关闭应用服务器
String command = "start";
if (args.length > 0) {
command = args[args.length - 1];
}
if (command.equals("startd")) {
args[args.length - 1] = "start";
daemon.load(args);
daemon.start();
} else if (command.equals("stopd")) {
args[args.length - 1] = "stop";
daemon.stop();
} else if (command.equals("start")) {
daemon.setAwait(true);
daemon.load(args);
daemon.start();
if (null == daemon.getServer()) {
System.exit(1);
}
} else if (command.equals("stop")) {
daemon.stopServer(args);
} else if (command.equals("configtest")) {
daemon.load(args);
if (null == daemon.getServer()) {
System.exit(1);
}
System.exit(0);
} else {
log.warn("Bootstrap: command \"" + command + "\" does not exist.");
}
} catch (Throwable var7) {
Throwable t = var7;
if (var7 instanceof InvocationTargetException && var7.getCause() != null) {
t = var7.getCause();
}
handleThrowable(t);
t.printStackTrace();
System.exit(1);
}
}
public void init(String[] arguments) throws Exception {
public void start() throws Exception {
public void stop() throws Exception {
public void stopServer() throws Exception {
public void stopServer(String[] arguments) throws Exception {
public void setAwait(boolean await) throws Exception {
public boolean getAwait() throws Exception {
public void destroy() {
public static String getCatalinaHome() {
public static String getCatalinaBase() {
public static File getCatalinaHomeFile() {
public static File getCatalinaBaseFile() {
static void handleThrowable(Throwable t) {
static Throwable unwrapInvocationTargetException(Throwable t) {
protected String replace(String str) {
protected static String[] getPaths(String value) {
private void initClassLoaders() {
private ClassLoader createClassLoader(String name, ClassLoader parent) throws Exception {
private void load(String[] arguments) throws Exception {
private Object getServer() throws Exception {
catalina:解析server.xml,创建容器组件
public class Catalina {
protected static final StringManager sm = StringManager.getManager("org.apache.catalina.startup");
public static final String SERVER_XML = "conf/server.xml";
protected boolean await = false;
protected String configFile = "conf/server.xml";
protected ClassLoader parentClassLoader = Catalina.class.getClassLoader();
protected Server server = null;
protected boolean useShutdownHook = true;
protected Thread shutdownHook = null;
protected boolean useNaming = true;
protected boolean loaded = false;
protected boolean generateCode = false;
protected File generatedCodeLocation = null;
protected String generatedCodeLocationParameter = null;
protected String generatedCodePackage = "catalinaembedded";
protected boolean useGeneratedCode = false;
private static final Log log = LogFactory.getLog(Catalina.class);
public Catalina() {
public void setAwait(boolean b) {
public void setServer(Server server) {
public void setConfigFile(String file) {
public void setUseNaming(boolean useNaming) {
public void setGenerateCode(boolean generateCode) {
public void setUseShutdownHook(boolean useShutdownHook) {
public void setUseGeneratedCode(boolean useGeneratedCode) {
public void setParentClassLoader(ClassLoader parentClassLoader) {
public void setGeneratedCodePackage(String generatedCodePackage) {
public void setGeneratedCodeLocation(File generatedCodeLocation) {
public boolean isAwait() {
public boolean isUseNaming() {
public boolean getUseShutdownHook() {
public boolean getUseGeneratedCode() {
public Server getServer() {
public String getConfigFile() {
public boolean getGenerateCode() {
public File getGeneratedCodeLocation() {
public String getGeneratedCodePackage() {
public ClassLoader getParentClassLoader() {
protected Digester createStartDigester() { //解析server.xml,返回创建server的digester
Digester digester = new Digester();
digester.setValidating(false);
digester.setRulesValidation(true);
Map<Class<?>, List<String>> fakeAttributes = new HashMap();
List<String> objectAttrs = new ArrayList();
objectAttrs.add("className");
fakeAttributes.put(Object.class, objectAttrs);
List<String> contextAttrs = new ArrayList();
contextAttrs.add("source");
fakeAttributes.put(StandardContext.class, contextAttrs);
List<String> connectorAttrs = new ArrayList();
connectorAttrs.add("portOffset");
fakeAttributes.put(Connector.class, connectorAttrs);
digester.setFakeAttributes(fakeAttributes);
digester.setUseContextClassLoader(true);
//创建server实例,默认为StandardServer,也可通过className属性指定自定义的server
digester.addObjectCreate("Server", "org.apache.catalina.core.StandardServer", "className");
digester.addSetProperties("Server"); //设置server属性
digester.addSetNext("Server", "setServer", "org.apache.catalina.Server");
//调用StandardServer的setServer方法设置server
//创建全局命名上下文
digester.addObjectCreate("Server/GlobalNamingResources", "org.apache.catalina.deploy.NamingResourcesImpl");
digester.addSetProperties("Server/GlobalNamingResources");
digester.addSetNext("Server/GlobalNamingResources", "setGlobalNamingResources", "org.apache.catalina.deploy.NamingResourcesImpl");
//添加生命周期监听器
digester.addRule("Server/Listener", new ListenerCreateRule((String)null, "className"));
digester.addSetProperties("Server/Listener");
digester.addSetNext("Server/Listener", "addLifecycleListener", "org.apache.catalina.LifecycleListener");
//构造service实例
digester.addObjectCreate("Server/Service", "org.apache.catalina.core.StandardService", "className");
digester.addSetProperties("Server/Service");
digester.addSetNext("Server/Service", "addService", "org.apache.catalina.Service");
//为service实例添加生命周期监听器
digester.addObjectCreate("Server/Service/Listener", (String)null, "className");
digester.addSetProperties("Server/Service/Listener");
digester.addSetNext("Server/Service/Listener", "addLifecycleListener", "org.apache.catalina.LifecycleListener");
//为service添加executor,添加后catalina共享executor的级别为service,默认不共享
digester.addObjectCreate("Server/Service/Executor", "org.apache.catalina.core.StandardThreadExecutor", "className");
digester.addSetProperties("Server/Service/Executor");
digester.addSetNext("Server/Service/Executor", "addExecutor", "org.apache.catalina.Executor");
//为service添加connector
digester.addRule("Server/Service/Connector", new ConnectorCreateRule());
digester.addSetProperties("Server/Service/Connector", new String[]{"executor", "sslImplementationName", "protocol"});
digester.addSetNext("Server/Service/Connector", "addConnector", "org.apache.catalina.connector.Connector");
digester.addRule("Server/Service/Connector", new AddPortOffsetRule());
//为connector添加虚拟主机ssl配置
digester.addObjectCreate("Server/Service/Connector/SSLHostConfig", "org.apache.tomcat.util.net.SSLHostConfig");
digester.addSetProperties("Server/Service/Connector/SSLHostConfig");
digester.addSetNext("Server/Service/Connector/SSLHostConfig", "addSslHostConfig", "org.apache.tomcat.util.net.SSLHostConfig");
digester.addRule("Server/Service/Connector/SSLHostConfig/Certificate", new CertificateCreateRule());
digester.addSetProperties("Server/Service/Connector/SSLHostConfig/Certificate", new String[]{"type"});
digester.addSetNext("Server/Service/Connector/SSLHostConfig/Certificate", "addCertificate", "org.apache.tomcat.util.net.SSLHostConfigCertificate");
digester.addObjectCreate("Server/Service/Connector/SSLHostConfig/OpenSSLConf", "org.apache.tomcat.util.net.openssl.OpenSSLConf");
digester.addSetProperties("Server/Service/Connector/SSLHostConfig/OpenSSLConf");
digester.addSetNext("Server/Service/Connector/SSLHostConfig/OpenSSLConf", "setOpenSslConf", "org.apache.tomcat.util.net.openssl.OpenSSLConf");
digester.addObjectCreate("Server/Service/Connector/SSLHostConfig/OpenSSLConf/OpenSSLConfCmd", "org.apache.tomcat.util.net.openssl.OpenSSLConfCmd");
digester.addSetProperties("Server/Service/Connector/SSLHostConfig/OpenSSLConf/OpenSSLConfCmd");
digester.addSetNext("Server/Service/Connector/SSLHostConfig/OpenSSLConf/OpenSSLConfCmd", "addCmd", "org.apache.tomcat.util.net.openssl.OpenSSLConfCmd");
//为connector添加生命周期监听器
digester.addObjectCreate("Server/Service/Connector/Listener", (String)null, "className");
digester.addSetProperties("Server/Service/Connector/Listener");
digester.addSetNext("Server/Service/Connector/Listener", "addLifecycleListener", "org.apache.catalina.LifecycleListener");
//为connector添加升级协议
digester.addObjectCreate("Server/Service/Connector/UpgradeProtocol", (String)null, "className");
digester.addSetProperties("Server/Service/Connector/UpgradeProtocol");
digester.addSetNext("Server/Service/Connector/UpgradeProtocol", "addUpgradeProtocol", "org.apache.coyote.UpgradeProtocol");
//添加子元素解析规则
digester.addRuleSet(new NamingRuleSet("Server/GlobalNamingResources/"));
digester.addRuleSet(new EngineRuleSet("Server/Service/"));
digester.addRuleSet(new HostRuleSet("Server/Service/Engine/"));
digester.addRuleSet(new ContextRuleSet("Server/Service/Engine/Host/"));
this.addClusterRuleSet(digester, "Server/Service/Engine/Host/Cluster/");
digester.addRuleSet(new NamingRuleSet("Server/Service/Engine/Host/Context/"));
digester.addRule("Server/Service/Engine", new Catalina.SetParentClassLoaderRule(this.parentClassLoader));
this.addClusterRuleSet(digester, "Server/Service/Engine/Cluster/");
return digester;
}
protected Digester createStopDigester() { //创建停止服务器的digester
Digester digester = new Digester();
digester.setUseContextClassLoader(true);
digester.addObjectCreate("Server", "org.apache.catalina.core.StandardServer", "className");
digester.addSetProperties("Server");
digester.addSetNext("Server", "setServer", "org.apache.catalina.Server");
return digester;
}
public void stopServer() {
public void stopServer(String[] arguments) {
public void load() {
public void load(String[] args) {
public void start() {
public void stop() {
public void await() {
protected void usage() {
protected File configFile() {
protected void initNaming() {
protected void initStreams() {
protected void generateLoader() {
protected void setSecurityProtection() {
protected boolean arguments(String[] args) {
protected void parseServerXml(boolean start) {
protected void generateClassFooter(Digester digester) {
protected void generateClassHeader(Digester digester, boolean start) {
private void addClusterRuleSet(Digester digester, String prefix) {
*********
内部类:SetParentClassLoaderRule
final class SetParentClassLoaderRule extends Rule {
ClassLoader parentClassLoader = null;
public SetParentClassLoaderRule(ClassLoader parentClassLoader) {
public void begin(String namespace, String name, Attributes attributes) throws Exception {
*********
内部类:CatalinaShutdownHook
protected class CatalinaShutdownHook extends Thread {
protected CatalinaShutdownHook() {
}
public void run() {
*********
内部接口:
public interface ServerXml {
LifeCycle:组件的生命周期
public interface Lifecycle {
String BEFORE_INIT_EVENT = "before_init"; //初始化事件
String AFTER_INIT_EVENT = "after_init";
String START_EVENT = "start"; //start事件
String BEFORE_START_EVENT = "before_start";
String AFTER_START_EVENT = "after_start";
String STOP_EVENT = "stop"; //stop事件
String BEFORE_STOP_EVENT = "before_stop";
String AFTER_STOP_EVENT = "after_stop";
String AFTER_DESTROY_EVENT = "after_destroy"; //destroy事件
String BEFORE_DESTROY_EVENT = "before_destroy";
String PERIODIC_EVENT = "periodic"; //周期性事件
String CONFIGURE_START_EVENT = "configure_start"; //配置开始事件
String CONFIGURE_STOP_EVENT = "configure_stop"; //配置停止事件
void addLifecycleListener(LifecycleListener var1);
LifecycleListener[] findLifecycleListeners();
void removeLifecycleListener(LifecycleListener var1);
void init() throws LifecycleException; //组件初始化
void start() throws LifecycleException; //组件启动
void stop() throws LifecycleException; //组件停止
void destroy() throws LifecycleException; //组件销毁
LifecycleState getState();
String getStateName();
public interface SingleUse {
}
}
Server:servlet容器
public interface Server extends Lifecycle {
void setPort(int var1);
void setPortOffset(int var1);
void setAddress(String var1);
void setShutdown(String var1);
void setCatalinaHome(File var1);
void setCatalina(Catalina var1);
void setCatalinaBase(File var1);
void setUtilityThreads(int var1);
void setParentClassLoader(ClassLoader var1);
void setGlobalNamingResources(NamingResourcesImpl var1);
int getPort();
int getPortOffset();
int getPortWithOffset();
int getUtilityThreads();
String getAddress();
String getShutdown();
Catalina getCatalina();
File getCatalinaBase();
File getCatalinaHome();
Object getNamingToken();
Context getGlobalNamingContext();
ClassLoader getParentClassLoader();
ScheduledExecutorService getUtilityExecutor();
NamingResourcesImpl getGlobalNamingResources();
void await();
void addService(Service var1);
void removeService(Service var1);
Service[] findServices();
Service findService(String var1);
}
Service:应用服务
public interface Service extends Lifecycle {
void setName(String var1);
void setServer(Server var1);
void setParentClassLoader(ClassLoader var1);
String getName();
Server getServer();
Mapper getMapper();
String getDomain();
ClassLoader getParentClassLoader();
void addConnector(Connector var1); //连接器
Connector[] findConnectors();
void removeConnector(Connector var1);
void setContainer(Engine var1); //应用容器
Engine getContainer();
void addExecutor(Executor var1); //线程池
Executor[] findExecutors();
Executor getExecutor(String var1);
void removeExecutor(Executor var1);
}
Container:应用容器
public interface Container extends Lifecycle {
String ADD_CHILD_EVENT = "addChild";
String ADD_VALVE_EVENT = "addValve";
String REMOVE_CHILD_EVENT = "removeChild";
String REMOVE_VALVE_EVENT = "removeValve";
void backgroundProcess(); //后台执行任务
void addChild(Container var1);
Container[] findChildren();
Container findChild(String var1);
void removeChild(Container var1);
void addContainerListener(ContainerListener var1);
void removeContainerListener(ContainerListener var1);
ContainerListener[] findContainerListeners();
void addPropertyChangeListener(PropertyChangeListener var1);
void removePropertyChangeListener(PropertyChangeListener var1);
void fireContainerEvent(String var1, Object var2);
void logAccess(Request var1, Response var2, long var3, boolean var5);
void setRealm(Realm var1);
void setName(String var1);
void setCluster(Cluster var1);
void setParent(Container var1);
void setStartStopThreads(int var1);
void setBackgroundProcessorDelay(int var1);
void setParentClassLoader(ClassLoader var1);
Log getLogger();
Realm getRealm();
String getName();
String getDomain();
String getLogName();
Cluster getCluster();
Container getParent();
Pipeline getPipeline();
File getCatalinaBase();
File getCatalinaHome();
AccessLog getAccessLog();
int getStartStopThreads();
ObjectName getObjectName();
String getMBeanKeyProperties();
int getBackgroundProcessorDelay();
ClassLoader getParentClassLoader();
static String getConfigPath(Container container, String resourceName) {
static Service getService(Container container) {
}
Engine:处理引擎
public interface Engine extends Container {
void setService(Service var1);
void setJvmRoute(String var1);
void setDefaultHost(String var1);
Service getService();
String getJvmRoute();
String getDefaultHost();
}
Host:servlet引擎(engine)虚拟机,客户端可根据网名连接服务器
public interface Host extends Container {
String ADD_ALIAS_EVENT = "addAlias";
String REMOVE_ALIAS_EVENT = "removeAlias";
void setAppBase(String var1);
void setXmlBase(String var1);
void setAutoDeploy(boolean var1);
void setConfigClass(String var1);
void setCreateDirs(boolean var1);
void setDeployIgnore(String var1);
void setDeployOnStartup(boolean var1);
ExecutorService getStartStopExecutor();
void setUndeployOldVersions(boolean var1);
boolean getCreateDirs();
boolean getAutoDeploy();
boolean getDeployOnStartup();
boolean getUndeployOldVersions();
String getXmlBase();
String getAppBase();
File getAppBaseFile();
String getConfigClass();
String getDeployIgnore();
File getConfigBaseFile();
Pattern getDeployIgnorePattern();
void addAlias(String var1);
String[] findAliases();
void removeAlias(String var1);
}
****************
web 应用加载
web应用加载由standardHost、hostConfig、standardContext、contextConfig、standardWrapper五个类完成
standardHost:读取server.xml,创建并启动context
如果server.xml的Host标签中存在context子标签,则读取配置创建context实例,
将其添加到host中,在host启动时,启动context实例
<Host name="localhost" appBase="webapps" uppackWARs="true" autoDepoly="true">
<Context docBase="myApp" path="/myApp" reloadable="true"/>
</Host>
# docBase:web应用根目录地址
# path:web应用根请求地址
# 如果使用端口默认,则项目请求根路径为:http://localhost:8080/myApp
hostConfig:自动扫描部署目录,创建context实例并启动
standardContext:web应用初始化及启动,包括创建启动会话管理器、过滤器、监听器等
contextConfig:web应用生命周期监听,负责处理各类监听事件
after_init_event:context属性配置
before_start_event:更新context的docBase属性和web目录锁
configure_start_event:创建wrapper、filter、servletContextListener等实例,完成web容器初始化
standardWrapper:具体维护servlet实例
通过contextConfig完成web容器初始化后,线雕用standardWrapper.start,组建状态变为started;
对于启动时加载的servlet,调用standardWrapper.load,完成servlet加载
# servlet加载过程:
创建servlet实例,如果添加了JNDI注解,则进行依赖注入;
读取multipartConfig注解配置,用于处理multipart/form-data请求,包括上传文件最大字节数、临时存储路径等;
读取servletConfig配置,添加安全配置
调用init方法,完成servlet初始化
****************
web 请求处理
coyoteAdapter:将connector、mapper、connector联系起来,connector读取数据后,调用coyoteAdapter.service()方法处理请求
mapper:维护请求链接与host、context、wrapper之间的映射
mapperListener:监听host、context、wrapper,在组件启动、停止时注册或者移除映射关系
CoyoteAdapter
public class CoyoteAdapter implements Adapter {
。。。
public void service(Request req, Response res) throws Exception {
org.apache.catalina.connector.Request request = (org.apache.catalina.connector.Request)req.getNote(1);
//创建servlet请求
org.apache.catalina.connector.Response response = (org.apache.catalina.connector.Response)res.getNote(1);
//创建servlet响应
if (request == null) {
request = this.connector.createRequest();
request.setCoyoteRequest(req);
response = this.connector.createResponse();
response.setCoyoteResponse(res);
request.setResponse(response);
response.setRequest(request);
req.setNote(1, request);
res.setNote(1, response);
req.getParameters().setQueryStringCharset(this.connector.getURICharset());
}
if (this.connector.getXpoweredBy()) {
response.addHeader("X-Powered-By", POWERED_BY);
}
boolean async = false;
boolean postParseSuccess = false;
req.getRequestProcessor().setWorkerThreadName((String)THREAD_NAME.get());
boolean var21 = false;
Host host;
long time;
AtomicBoolean error;
Context context;
label411: {
try {
var21 = true;
postParseSuccess = this.postParseRequest(req, request, res, response);
//转换请求参数,完成请求映射
if (postParseSuccess) {
request.setAsyncSupported(this.connector.getService().getContainer().getPipeline().isAsyncSupported());
this.connector.getService().getContainer().getPipeline().getFirst().invoke(request, response);
//得到当前engine的第一个valve并执行,完成客户端请求处理
}
if (request.isAsync()) { //如果是异步请求
async = true;
ReadListener readListener = req.getReadListener();
//获取请求读取事件监听器
if (readListener != null && request.isFinished()) {
ClassLoader oldCL = null;
try {
oldCL = request.getContext().bind(false, (ClassLoader)null);
if (req.sendAllDataReadEvent()) {
req.getReadListener().onAllDataRead();
//如果请求读取已经结束,触发ReadListener的onAllDataRead方法
}
} finally {
request.getContext().unbind(false, oldCL);
}
}
Throwable throwable = (Throwable)request.getAttribute("javax.servlet.error.exception");
if (!request.isAsyncCompleting()) {
if (throwable != null) {
request.getAsyncContextInternal().setErrorState(throwable, true);
var21 = false;
} else {
var21 = false;
}
} else {
var21 = false;
}
} else { //如果是同步请求
request.finishRequest(); //flush并关闭请求输入流
response.finishResponse(); //flush并关闭响应输出流
var21 = false;
}
break label411;
} catch (IOException var26) {
var21 = false;
} finally {
if (var21) {
AtomicBoolean error = new AtomicBoolean(false);
res.action(ActionCode.IS_ERROR, error);
if (request.isAsyncCompleting() && error.get()) {
res.action(ActionCode.ASYNC_POST_PROCESS, (Object)null);
async = false;
}
if (!async && postParseSuccess) {
Context context = request.getContext();
Host host = request.getHost();
long time = System.currentTimeMillis() - req.getStartTime();
if (context != null) {
context.logAccess(request, response, time, false);
} else if (response.isError()) {
if (host != null) {
host.logAccess(request, response, time, false);
} else {
this.connector.getService().getContainer().logAccess(request, response, time, false);
}
}
}
req.getRequestProcessor().setWorkerThreadName((String)null);
if (!async) {
this.updateWrapperErrorCount(request, response);
request.recycle();
response.recycle();
}
}
}
error = new AtomicBoolean(false);
res.action(ActionCode.IS_ERROR, error);
if (request.isAsyncCompleting() && error.get()) {
res.action(ActionCode.ASYNC_POST_PROCESS, (Object)null);
async = false;
}
if (!async && postParseSuccess) {
context = request.getContext();
host = request.getHost();
time = System.currentTimeMillis() - req.getStartTime();
if (context != null) {
context.logAccess(request, response, time, false);
} else if (response.isError()) {
if (host != null) {
host.logAccess(request, response, time, false);
} else {
this.connector.getService().getContainer().logAccess(request, response, time, false);
}
}
}
req.getRequestProcessor().setWorkerThreadName((String)null);
if (!async) {
this.updateWrapperErrorCount(request, response);
request.recycle();
response.recycle();
}
return;
}
error = new AtomicBoolean(false);
res.action(ActionCode.IS_ERROR, error);
if (request.isAsyncCompleting() && error.get()) {
res.action(ActionCode.ASYNC_POST_PROCESS, (Object)null);
async = false;
}
if (!async && postParseSuccess) {
context = request.getContext();
host = request.getHost();
time = System.currentTimeMillis() - req.getStartTime();
if (context != null) {
context.logAccess(request, response, time, false);
} else if (response.isError()) {
if (host != null) {
host.logAccess(request, response, time, false);
} else {
this.connector.getService().getContainer().logAccess(request, response, time, false);
}
}
}
req.getRequestProcessor().setWorkerThreadName((String)null);
if (!async) {
this.updateWrapperErrorCount(request, response);
request.recycle();
response.recycle();
}
}
}
****************
tomcat 网络协议
http协议
# 配置方式
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443"/>
属性说明
port:8080,默认端口为8080
protocol="HTTP/1.1":当前链接器支持的协议为HTTP/1.1
protocol采用此种配置方式,会自动检测tomcat是否安装了apr,
如果安装了apr,tomcat使用apr处理http,否则使用nio
protocol="org.apache.coyote.http11.Http11NioProtocol"
使用nio处理http
connectionTimeout:connector接收到链接后等待的超时时间,单位为毫秒,默认为20s
redirectPost:ssl请求重定向端口,默认为8443
说明:The APR/Native HTTP Connector is deprecated and will be removed in Tomcat 10.1.x onwards
ajp协议
# 配置方式
<Connector port="8080" protocol="AJP/1.3" connectionTimeout="20000" redirectPort="8443"/>
属性说明
port:8080,默认端口为8080
protocol="AJP/1.3":当前链接器支持的协议为ajp
protocol采用此种配置方式,会自动检测tomcat是否安装了apr,
如果安装了apr,tomcat使用apr处理请求,否则使用nio
protocol="org.apache.coyote.ajp.AjpNioProtocol"
使用nio处理http
http2协议
# UpgradeProtocol提供http2升级支持
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443">
<UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol">
<Connector>
# http2添加ssl配置(openSSL的tls,java8的tls不支持alpn)
<Connector port="8080" protocol="HTTP/1.1" SSLEnabled="true" sslImplementionName="org.apache.tomcat.util.net.openssl.OpenSSLImplementation" connectionTimeout="20000" redirectPort="8443">
<UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol">
<SSLHostConfig>
<Certificate certificateKeyFile="./key.pem" certificateFile="./cert.pem" certificateChainFile="./chain.pem"/>
</SSLHostConfig>
</Connector>
protocol如果指定Http11AprProtocol,且tomcat安装了apr,
则不需要指定sslImplementationName,http11AprProtocol默认使用的openssl
****************
tomcat i/o
BIO:同步阻塞读取数据,8.5之后移除BIO
NIO:同步非阻塞io,对应的protocol
org.apache.coyote.ajp.AjpNioProtocol
org.apache.coyote.http11.Http11NioProtocol
NIO2(AIO):异步非阻塞io,对应的的协议
org.apache.coyote.ajp.AjpNio2Protocol
org.apache.coyote.http11.Http11Nio2Protocol
APR:一般在与web服务器集成时使用,对应的协议(10.1.x开始禁用,后续会移除)
org.apache.coyote.ajp.AjpAprProtocol
org.apache.coyote.http11.Http11AprProtocol
说明:The APR/Native HTTP Connector is deprecated and will be removed in Tomcat 10.1.x onwards