tomcat是怎么处理请求的

一、tomcat目录结构

tomcat也是一个应用服务器,下载tomcat源码可以看到tomcat的源码目录如下:


image.png

/bin、/conf、/webapps 这些目录就是在我们本地的安装目录可以看到的工具、配置、部署目录,/java目录就是具体的代码实现了

二、tomcat请求处理基本框架

tomcat是个很庞大的项目,这里只会涉及到请求处理部分,并且不涉及具体细节。
注:了解tomcat的大致结构可以先去看下tomcat安装目录中的conf/server.xml文件,文章末尾有样例。

首先,不管是tomcat还是什么其他的web服务器容器,基本功能一定都是监听请求、接受并处理请求,tomcat也是,核心在于请求监听与请求处理。

涉及的接口主要有:


image.png
1、Lifecycle

它算是tomcat最顶层的接口,从代码可以看出接口中定义了tomcat的整个生命周期状态一起一些生命周期函数。

package org.apache.catalina;

public interface Lifecycle {

// ----------------------------------------------------- Manifest Constants

/**
 * The LifecycleEvent type for the "component before init" event.
 */
public static final String BEFORE_INIT_EVENT = "before_init";
public static final String AFTER_INIT_EVENT = "after_init";
public static final String START_EVENT = "start";
public static final String BEFORE_START_EVENT = "before_start";
public static final String AFTER_START_EVENT = "after_start";
public static final String STOP_EVENT = "stop";
public static final String BEFORE_STOP_EVENT = "before_stop";
public static final String AFTER_STOP_EVENT = "after_stop";
public static final String AFTER_DESTROY_EVENT = "after_destroy";
public static final String BEFORE_DESTROY_EVENT = "before_destroy";
public static final String PERIODIC_EVENT = "periodic";
public static final String CONFIGURE_START_EVENT = "configure_start";
public static final String CONFIGURE_STOP_EVENT = "configure_stop";

// --------------------------------------------------------- Public Methods

public void addLifecycleListener(LifecycleListener listener);

public LifecycleListener[] findLifecycleListeners();

public void removeLifecycleListener(LifecycleListener listener);

public void init() throws LifecycleException;

public void start() throws LifecycleException;

public void stop() throws LifecycleException;

public void destroy() throws LifecycleException;

public LifecycleState getState();

public String getStateName();

public interface SingleUse {
}
}

这里重点注意start() 和 stop() 这两个函数,tomcat作为服务器来处理客户端请求,底层也是通过监听socket端口来建立socket连接,然后对请求进行一步步处理的,这里的start() 和 stop() 函数就是用来进行一些开始和结束的操作,包括初始化和终止 socket监听。

2、Connector

tomcat通过Connector来建立socket端口监听,进而接受外部请求进行处理。
说到通过端口来监听socket连接,这就和我们经常接触的tomcat安装目录下的server.xml配置联系起来了,下面是里面的部分配置信息:


image.png

可以看出在Connector标签中配置了监听的端口号以及其他一些信息,这个Connector在服务器的代码实现中也有对应的处理类,就是前面说的Connector类。

从server.xml可以理解每个Connector是作为一个连接器,每个Connector对象会监听一个端口,Connector类继承自Lifecycle 接口,监听端口的初始化操作也就在start()方法中实现:


image.png

image.png

image.png

在Connector连接器配置监听的过程中主要有个需要注意的接口ProtocolHandler:

从命名可以看出它是不同协议请求的处理接口,下面是它的所有实现类:

image.png

ProtocolHandler由包含了三个部件:Endpoint、Processor、Adapter。
Endpoint用来处理底层Socket连接
Processor用于将Endpoint接收到的Socket封装成Request
Adapter充当适配器,用于将Request转换为ServletRequest交给Container进行具体的处理。

如AbstractEndpoint:它里面封装了socket连接的处理逻辑,下面是它的所有实现类,目前最新版的tomcat都使用NIO的方式。

3、Container

Server.xml中的整个Engine即Container。
Connector进行请求监听,Container是进行连接建立后的请求处理的,它的实现类ContainerBase同样实现了Lifecycle 接口,所以在应用开始时ContainerBase也会执行其start()方法

与Container相关的概念有Engine、Host、Context、Wrapper

Engine:服务器引擎,对应一个Container,用于处理请求,其中可以包含多个Host
Host:主机,服务器,我们通过主机名+端口号访问我们的应用,主机就是这里的Host,其中包含多个Context
Context:一个应用上下文,即webapps目录下的一个项目
Wrapper:是对Context中处理请求的Servlet的封装

***附录:tomcat中默认的server.xml:
<?xml version="1.0" encoding="UTF-8"?>

                                                                                       
<Server port="8005" shutdown="SHUTDOWN">                       //Server代表一个tomcat应用服务器
  <Listener className="org.apache.catalina.startup.VersionLoggerListener" />
  <!-- Security listener. Documentation at /docs/config/listeners.html
  <Listener className="org.apache.catalina.security.SecurityListener" />
  -->
  <!--APR library loader. Documentation at /docs/apr.html -->
  <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
  <!-- Prevent memory leaks due to use of particular java/javax APIs-->
  <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
  <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
  <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />

  <!-- Global JNDI resources
     Documentation at /docs/jndi-resources-howto.html
  -->
  <GlobalNamingResources>
    <!-- Editable user database that can also be used by
     UserDatabaseRealm to authenticate users
    -->
    <Resource name="UserDatabase" auth="Container"
          type="org.apache.catalina.UserDatabase"
          description="User database that can be updated and saved"
          factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
          pathname="conf/tomcat-users.xml" />
  </GlobalNamingResources>

  <!-- A "Service" is a collection of one or more "Connectors" that share
   a single "Container" Note:  A "Service" is not itself a "Container",
   so you may not define subcomponents such as "Valves" at this level.
   Documentation at /docs/config/service.html
   -->
  <Service name="Catalina">        //Service中包含了多个Connector和一个Container(即Engine),
                                                         相当于将两者封装起来表示这些Connector监听的请求由该Engine处理


    <Connector port="80" protocol="HTTP/1.1"
           connectionTimeout="20000"
           redirectPort="8443" />


    <!-- Define an AJP 1.3 Connector on port 8009 -->
    <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />


    <Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"  
            maxThreads="150" scheme="https" secure="true"  
            clientAuth="false" sslProtocol="TLS"   
        keystoreFile="d:\tomcat.keystore"  
        keystorePass="123456" />  

    <!-- An Engine represents the entry point (within Catalina) that processes
     every request.  The Engine implementation for Tomcat stand alone
     analyzes the HTTP headers included with the request, and passes them
     on to the appropriate Host (virtual host).
     Documentation at /docs/config/engine.html -->

    <!-- You should set jvmRoute to support load-balancing via AJP ie :
<Engine name="Catalina" defaultHost="localhost" jvmRoute="jvm1">
-->
    <Engine name="Catalina" defaultHost="localhost">   //服务器引擎,对应源码中的Container,用于处理请求,其中可以包含多个Host,
                                                                                              默认是localhost,也就是说还可以配置其他域名的请求由该服务器处理?

  <!--For clustering, please take a look at documentation at:
      /docs/cluster-howto.html  (simple how to)
      /docs/config/cluster.html (reference documentation) -->
  <!--
  <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>
  -->

  <!-- Use the LockOutRealm to prevent attempts to guess user passwords
       via a brute-force attack -->
      <Realm className="org.apache.catalina.realm.LockOutRealm">
    <!-- This Realm uses the UserDatabase configured in the global JNDI
         resources under the key "UserDatabase".  Any edits
         that are performed against this UserDatabase are immediately
         available for use by the Realm.  -->
          <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
               resourceName="UserDatabase"/>
      </Realm>

      <Host name="localhost"  appBase="webapps"     //主机,就是我们在webapps目录下部署的所有项目,                                                 
            unpackWARs="true" autoDeploy="true">          我们通过主机名+端口号访问我们的应用,主机名就是这里的localhost。

          <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
               prefix="localhost_access_log" suffix=".txt"
               pattern="%h %l %u %t &quot;%r&quot; %s %b" />
      </Host>
    </Engine>
  </Service>
</Server>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,686评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,668评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,160评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,736评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,847评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,043评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,129评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,872评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,318评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,645评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,777评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,470评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,126评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,861评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,095评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,589评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,687评论 2 351