精华内容
下载资源
问答
  • Tomcat处理HTTP请求过程分析

    千次阅读 2018-12-14 14:43:02
    Tomcat处理HTTP请求过程分析 一、Tomcat是什么? Tomcat是一个web应用服务器,是一个Servlet/Jsp容器,主要负责将客户端请求传递给对应的Servlet,并且将Servlet的响应数据返回给客户端。 Tomcat是基于组件的...

    Tomcat处理HTTP请求过程分析

    一、Tomcat是什么?

    Tomcat是一个web应用服务器,是一个Servlet/Jsp容器,主要负责将客户端请求传递给对应的Servlet,并且将Servlet的响应数据返回给客户端。

    Tomcat是基于组件的服务器。

    二、Tomcat体系结构

    Tomcat是一个基于组件的服务器,它的构成组件都是可配置的。其各个组件都在Tomcat安装目录下的../conf/server.xml文件中配置

    server.xml文件源代码如下

    <?xml version="1.0" encoding="UTF-8"?>
    
    <!--顶层类元素,可以包含多个Service-->
    
    <Server port="8005" shutdown="SHUTDOWN">  
    
      <Listener className="org.apache.catalina.startup.VersionLoggerListener" />
    
      <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
    
      <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
    
      <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
    
      <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
    
      <GlobalNamingResources>
    
        <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>
    
      <!--顶层类元素,可包含一个Engine(container),多个connector-->
    
      <Service name="Catalina">
    
      <!--连接器类元素,代表通信接口-->
    
        <Connector port="8080" protocol="HTTP/1.1"
    
                   connectionTimeout="20000"
    
                   redirectPort="8443" />
    
        <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
    
        <!--容器类元素,为特定的service组件处理客户请求-->
    
        <Engine name="Catalina" defaultHost="localhost">
    
            <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
    
                   resourceName="UserDatabase"/>
    
            </Realm>
    
            <!--容器类元素,为特定的虚拟主机组件处理客户请求-->
    
          <Host name="localhost"  appBase="webapps"
    
                unpackWARs="true" autoDeploy="true">
    
            <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
    
                   prefix="localhost_access_log" suffix=".txt"
    
                   pattern="%h %l %u %t "%r" %s %b" />
    
          </Host>
    
        </Engine>
    
      </Service>
    
    </Server>

     

    由上图可以看出Tomcat的心脏是两个核心组件:Connector(连接器)和Container(容器)。其中一个Container可以选择多个Connector

    扩展:Tomcat默认提供两个Connector连接器,一个默认监听8080端口,一个默认监听8009端口,这两种连接器有什么区别呢?redirectPort有什么作用?

    (1)8080端口监听的是通过HTTP/1.1协议访问的连接,而8009端口主要负责和其他HTTP服务器(如Apache、IIS)建立连接,使用AJP/1.3协议,当Tomcat和其他服务器集成时就会使用到这个连接器。如下图。

    Web1和Web2都是访问服务器的index.jsp页面。Web1直接访问Tomcat服务器,访问地址是http://localhost:8080/index.jsp。Web2访问HTTP服务器,HTTP服务器再通过访问Tomcat的8009端口找到index.jsp。假设HTTP服务器的端口为80端口,则访问地址为http://localhost:80/index.jsp 或者 http://localhost/index.jsp。

    Apache、IIS服务器一般只支持静态页面,如HTML,不支持JSP动态页面。Tomcat对HTML的解析速度不如Apache、IIS服务器。因此一般将两者整合使用。

    (2)redirectPort字面意思是重定向端口。当用户用http请求某个资源,而该资源本身又被设置了必须要https方式访问,此时Tomcat会自动重定向到这个redirectPort设置的https端口。

     

    三、组件

    1、Connector组件

    Connector 最重要的功能就是接收连接请求然后分配线程让 Container来处理这个请求,所以这必然是多线程的,多线程的处理是 Connector 设计的核心。Connector监听指定端口上请求,当请求到来时创建一个request和response对象交换数据,然后新建一个线程来处理请求并把request和response传递给Engine组件,最后从Engine获取一个响应并返回给客户端。

    Connector组件常用属性说明:

    (1) address:指定连接器监听的地址,默认为所有地址,即0.0.0.0可以自己指定地。(2) maxThreads:支持的最大并发连接数,默认为200;

    (3) port:监听的端口;

    (4) protocol:连接器使用的协议,默认为HTTP/1.1,定义AJP协议时通常为AJP/1.3;

    (5) redirectPort:如果某连接器支持的协议是HTTP,当接收客户端发来的HTTPS请求时,则转发至此属性定义的端口;

    (6) connectionTimeout:等待客户端发送请求的超时时间,单位为毫秒,默认为60000,即1分钟;

    (7) enableLookups:是否通过request.getRemoteHost()进行DNS查询以获取客户端的主机名;默认为true; 进行反解的,可以设置为false

    (8) acceptCount:设置等待队列的最大长度;通常在tomcat所有处理线程均处于繁忙状态时,新发来的请求将被放置于等待队列中;

     

     

    1. container组件

    Container是容器的父接口,该容器的设计用的是典型的责任链的设计模式,它由四个自容器组件构成,分别是Engine、Host、Context、Wrapper。这四个组件是负责关系,存在包含关系。通常一个Servlet class对应一个Wrapper,如果有多个Servlet则定义多个Wrapper,如果有多个Wrapper就要定义一个更高的Container,如Context。 Context定义在父容器 Host 中,其中Host 不是必须的,但是要运行 war 程序,就必须要 Host,因为 war 中必有 web.xml 文件,这个文件的解析就需要 Host 了,如果要有多个 Host 就要定义一个 top 容器 Engine 了。而 Engine 没有父容器了,一个 Engine 代表一个完整的 Servlet 引擎。

    2.1、Engine

    Engine是Servlet处理器的一个实例,即servlet引擎,默认为定义在server.xml中的Catalina。Engine需要defaultHost属性来为其定义一个接收所有请求的虚拟主机host组件

    2.2、Host

    Host是Engine的子容器。一个 Host 在 Engine 中代表一个虚拟主机,这个虚拟主机的作用就是运行多个应用、接收并处理请求、保存一个主机应该有的信息。

    常用属性说明:

    (1)appBase:此Host的webapps目录,项目存放路径,可以使用绝对路径

    (2)autoDeploy:在Tomcat处于运行状态时放置于appBase目录中的应用程序文件是否自动进行deploy;默认为true;

    (3)unpackWars:在启用此webapps时是否对WAR格式的归档文件先进行展开;默认为true;

    2.3、Context

    Context 代表 Servlet 的 Context,它具备了 Servlet 运行的基本环境,理论上只要有 Context 就能运行 Servlet 了。简单的 Tomcat 可以没有 Engine 和 Host。Context 最重要的功能就是管理它里面的 Servlet 实例,Servlet 实例在 Context 中是以 Wrapper 出现的,还有一点就是 Context 如何才能找到正确的 Servlet 来执行它呢? Tomcat5 以前是通过一个 Mapper 类来管理的,Tomcat5 以后这个功能被移到了 request 中,在前面的时序图中就可以发现获取子容器都是通过 request 来分配的

    常用属性定义:

    (1) docBase:相应的Web应用程序的存放位置;也可以使用相对路径,起始路径为此Context所属Host中appBase定义的路径;切记,docBase的路径名不能与相应的Host中appBase中定义的路径名有包含关系,比如,如果appBase为deploy,而docBase绝不能为deploy-bbs类的名字;

    (2)path:相对于Web服务器根路径而言的URI;如果为空“”,则表示为此webapp的根路径;如果context定义在一个单独的xml文件中,此属性不需要定义,有可能是别名;

    (3) reloadable:是否允许重新加载此context相关的Web应用程序的类;默认为false;

    2.4、Wrapper

    Wrapper 代表一个 Servlet,它负责管理一个 Servlet,包括Servlet 的装载、初始化、执行以及资源回收。Wrapper 是最底层的容器,它没有子容器了,所以调用它的 addChild 将会报错。 Wrapper 的实现类是 StandardWrapper,StandardWrapper 还实现了 ServletConfig,由此看出 StandardWrapper 将直接和 Servlet 的各种信息打交道。

    2.5、Realm

    Wrapper 代表一个 Servlet,它负责管理一个 Servlet,包括的 Servlet 的装载、初始化、执行以及资源回收。Wrapper 是最底层的容器,它没有子容器了,所以调用它的 addChild 将会报错。 Wrapper 的实现类是 StandardWrapper,StandardWrapper 还实现了拥有一个 Servlet 初始化信息的 ServletConfig,由此看出 StandardWrapper 将直接和 Servlet 的各种信息打交道。

    2.6、Value

    Valve类似于过滤器,它可以工作于Engine和Host/Context之间、Host和Context之间以及Context和Web应用程序的某资源之间。一个容器内可以建立多个Valve,而且Valve定义的次序也决定了它们生效的次序。

    四、Tomcat处理一个HTTP请求的过程

     

    1.用户在浏览器中输入网址localhost:8080/test/index.jsp,请求被发送到本机端口8080,被在那里监听的Coyote HTTP/1.1 Connector获得;

    2.Connector把该请求交给它所在的Service的Engine(Container)来处理,并等待Engine的回应;

    3.Engine获得请求localhost/test/index.jsp,匹配所有的虚拟主机Host;

    4.Engine匹配到名为localhost的Host(即使匹配不到也把请求交给该Host处理,因为该Host被定义为该Engine的默认主机)名为localhost的Host获得请求/test/index.jsp,匹配它所拥有的所有Context。Host匹配到路径为/test的Context(如果匹配不到就把该请求交给路径名为 的Context去处理);

    5.path=/test的Context获得请求/index.jsp,在它的mapping table中寻找出对应的Servlet。Context匹配到URL Pattern为*.jsp的Servlet,对应于JspServlet类;

    6.构造HttpServletRequest对象和HttpServletResponse对象,作为参数调用JspServlet的doGet()或doPost(),执行业务逻辑、数据存储等;

    7.Context把执行完之后的HttpServletResponse对象返回给Host;

    8.Host把HttpServletResponse对象返回给Engine;

    9.Engine把HttpServletResponse对象返回Connector;

    10.Connector把HttpServletResponse对象返回给客户Browser。

     

    参考:https://www.cnblogs.com/small-boy/p/8042860.html

     

    展开全文
  • tomcat中server配置文件的结构,以及处理一个http请求的全过程
  • Tomcat处理HTTP请求原理&线程池

    千次阅读 2019-07-26 14:13:19
    Tomcat处理HTTP请求原理&线程池 一.Tomcat是什么? Tomcat是一个Web应用服务器,同时也是一个Servlet/JSP容器。Tomcat作为Servlet容器,负责处理客户端请求,把请求传送给Servlet,并将Servlet的响应返回给...

    Tomcat处理HTTP请求原理&线程池

    一.Tomcat是什么?

    Tomcat是一个Web应用服务器,同时也是一个Servlet/JSP容器。Tomcat作为Servlet容器,负责处理客户端请求,把请求传送给Servlet,并将Servlet的响应返回给客户端。

     

    三.Tomcat的两个核心组件:Connector和Container

    1.Connector组件

    一 个Connector组件将在某个指定的端口上侦听客户请求,接收浏览器发过来的tcp连接请求,创建一个Request和一个Response对象分别 用于和其你去端交换数据,然后会产生一个线程来处理这个请求并把产生的Request和Response对象传给Engine,从Engine中获得响应 并返回给客户端。 Tomcat有两个经典的Connector,一个直接侦听来自浏览器的HTTP请求,另外一个侦听来自其他的WebServer的请求。Cotote HTTP/1.1 Connector在端口8080处侦听来自客户浏览器的HTTP请求,Coyote JK2 Connector在端口8009处侦听其他WebServer的Servlet/JSP请求。 Connector 最重要的功能就是接收连接请求然后分配线程让 Container来处理这个请求,所以这必然是多线程的,多线程的处理是 Connector 设计的核心。

    2.Container组件

    Container组件的体系结构如下:

    Container

    Container是容器的父接口,该容器的设计用的是典型的 责任链的设计模式,它由四个自容器组件构成,分别是Engine、Host、Context、Wrapper。这四个组件是负责关系,存在包含关系。通常 一个Servlet class对应一个Wrapper,如果有多个Servlet则定义多个Wrapper,如果有多个Wrapper就要定义一个更高的 Container,如Context。 Context定义在父容器 Host 中,其中Host 不是必须的,但是要运行 war 程序,就必须要 Host,因为 war 中必有 web.xml 文件,这个文件的解析就需要 Host 了,如果要有多个 Host 就要定义一个 top 容器 Engine 了。而 Engine 没有父容器了,一个 Engine 代表一个完整的 Servlet 引擎。

    Engine

    Engine 容器比较简单,它只定义了一些基本的关联关系 Host 容器

    Host

    Host 是 Engine 的字容器,一个 Host 在 Engine 中代表一个虚拟主机,这个虚拟主机的作用就是运行多个应用,它负责安装和展开这些应用,并且标识这个应用以便能够区分它们。它的子容器通常是 Context,它除了关联子容器外,还有就是保存一个主机应该有的信息。

    Context

    Context 代表 Servlet 的 Context,它具备了 Servlet 运行的基本环境,理论上只要有 Context 就能运行 Servlet 了。简单的 Tomcat 可以没有 Engine 和 Host。Context 最重要的功能就是管理它里面的 Servlet 实例,Servlet 实例在 Context 中是以 Wrapper 出现的,还有一点就是 Context 如何才能找到正确的 Servlet 来执行它呢? Tomcat5 以前是通过一个 Mapper 类来管理的,Tomcat5 以后这个功能被移到了 request 中,在前面的时序图中就可以发现获取子容器都是通过 request 来分配的

    Wrapper

    Wrapper 代表一个 Servlet,它负责管理一个 Servlet,包括的 Servlet 的装载、初始化、执行以及资源回收。Wrapper 是最底层的容器,它没有子容器了,所以调用它的 addChild 将会报错。 Wrapper 的实现类是 StandardWrapper,StandardWrapper 还实现了拥有一个 Servlet 初始化信息的 ServletConfig,由此看出 StandardWrapper 将直接和 Servlet 的各种信息打交道。

    说明:除了上述组件外,Tomcat中还有其他重要的组件,如安全组件security、logger日志组件、session、mbeans、naming等其他组件。这些组件共同为Connector和Container提供必要的服务。

    四.Tomcat 处理一个HTTP请求的过程

     

    1.用户在浏览器中输入网址localhost:8080/test/index.jsp,请求被发送到本机端口8080,被在那里监听的Coyote HTTP/1.1 Connector获得;

    2.Connector把该请求交给它所在的Service的Engine(Container)来处理,并等待Engine的回应;

    3.Engine获得请求localhost/test/index.jsp,匹配所有的虚拟主机Host;

    4.Engine 匹配到名为localhost的Host(即使匹配不到也把请求交给该Host处理,因为该Host被定义为该Engine的默认主机),名为 localhost的Host获得请求/test/index.jsp,匹配它所拥有的所有Context。Host匹配到路径为/test的 Context(如果匹配不到就把该请求交给路径名为“ ”的Context去处理);

    5.path=“/test”的Context获得请求/index.jsp,在它的mapping table中寻找出对应的Servlet。Context匹配到URL Pattern为*.jsp的Servlet,对应于JspServlet类;

    6.构造HttpServletRequest对象和HttpServletResponse对象,作为参数调用JspServlet的doGet()或doPost(),执行业务逻辑、数据存储等;

    7.Context把执行完之后的HttpServletResponse对象返回给Host;

    8.Host把HttpServletResponse对象返回给Engine;

    9.Engine把HttpServletResponse对象返回Connector;

    10.Connector把HttpServletResponse对象返回给客户Browser。

     --------------------------------------------------------------------------------------------------------------------------------------------------------------------

    二、3个参数:acceptCount、maxConnections、maxThreads

    再回顾一下Tomcat处理请求的过程:在accept队列中接收连接(当客户端向服务器发送请求时,如果客户端与OS完成三次握手建立了连接,则OS将该连接放入accept队列);在连接中获取请求的数据,生成request;调用servlet容器处理请求;返回response。

    相对应的,Connector中的几个参数功能如下:

    1、acceptCount

    accept队列的长度;当accept队列中连接的个数达到acceptCount时,队列满,进来的请求一律被拒绝。默认值是100。

    2、maxConnections

    Tomcat在任意时刻接收和处理的最大连接数。当Tomcat接收的连接数达到maxConnections时,Acceptor线程不会读取accept队列中的连接;这时accept队列中的线程会一直阻塞着,直到Tomcat接收的连接数小于maxConnections。如果设置为-1,则连接数不受限制。

    默认值与连接器使用的协议有关:NIO的默认值是10000,APR/native的默认值是8192,而BIO的默认值为maxThreads(如果配置了Executor,则默认值是Executor的maxThreads)。

    在windows下,APR/native的maxConnections值会自动调整为设置值以下最大的1024的整数倍;如设置为2000,则最大值实际是1024。

    3、maxThreads

    请求处理线程的最大数量。默认值是200(Tomcat7和8都是的)。如果该Connector绑定了Executor,这个值会被忽略,因为该Connector将使用绑定的Executor,而不是内置的线程池来执行任务。

    maxThreads规定的是最大的线程数目,并不是实际running的CPU数量;实际上,maxThreads的大小比CPU核心数量要大得多。这是因为,处理请求的线程真正用于计算的时间可能很少,大多数时间可能在阻塞,如等待数据库返回数据、等待硬盘读写数据等。因此,在某一时刻,只有少数的线程真正的在使用物理CPU,大多数线程都在等待;因此线程数远大于物理核心数才是合理的。

    换句话说,Tomcat通过使用比CPU核心数量多得多的线程数,可以使CPU忙碌起来,大大提高CPU的利用率。

    4、参数设置

    (1)maxThreads的设置既与应用的特点有关,也与服务器的CPU核心数量有关。通过前面介绍可以知道,maxThreads数量应该远大于CPU核心数量;而且CPU核心数越大,maxThreads应该越大;应用中CPU越不密集(IO越密集),maxThreads应该越大,以便能够充分利用CPU。当然,maxThreads的值并不是越大越好,如果maxThreads过大,那么CPU会花费大量的时间用于线程的切换,整体效率会降低。

    (2)maxConnections的设置与Tomcat的运行模式有关。如果tomcat使用的是BIO,那么maxConnections的值应该与maxThreads一致;如果tomcat使用的是NIO,那么类似于Tomcat的默认值,maxConnections值应该远大于maxThreads。

    (3)通过前面的介绍可以知道,虽然tomcat同时可以处理的连接数目是maxConnections,但服务器中可以同时接收的连接数为maxConnections+acceptCount 。acceptCount的设置,与应用在连接过高情况下希望做出什么反应有关系。如果设置过大,后面进入的请求等待时间会很长;如果设置过小,后面进入的请求立马返回connection refused。

    三、线程池Executor

    Executor元素代表Tomcat中的线程池,可以由其他组件共享使用;要使用该线程池,组件需要通过executor属性指定该线程池。

    Executor是Service元素的内嵌元素。一般来说,使用线程池的是Connector组件;为了使Connector能使用线程池,Executor元素应该放在Connector前面。Executor与Connector的配置举例如下:

    1

    2

    <Executor name="tomcatThreadPool" namePrefix ="catalina-exec-" maxThreads="150" minSpareThreads="4" />

    <Connector executor="tomcatThreadPool" port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" acceptCount="1000" />

    Executor的主要属性包括:

    • name:该线程池的标记
    • maxThreads:线程池中最大活跃线程数,默认值200(Tomcat7和8都是)
    • minSpareThreads:线程池中保持的最小线程数,最小值是25
    • maxIdleTime:线程空闲的最大时间,当空闲超过该值时关闭线程(除非线程数小于minSpareThreads),单位是ms,默认值60000(1分钟)
    • daemon:是否后台线程,默认值true
    • threadPriority:线程优先级,默认值5
    • namePrefix:线程名字的前缀,线程池中线程名字为:namePrefix+线程编号

    四、查看当前状态

    上面介绍了Tomcat连接数、线程数的概念以及如何设置,下面说明如何查看服务器中的连接数和线程数。

    查看服务器的状态,大致分为两种方案:(1)使用现成的工具,(2)直接使用Linux的命令查看。

    现成的工具,如JDK自带的jconsole工具可以方便的查看线程信息(此外还可以查看CPU、内存、类、JVM基本信息等),Tomcat自带的manager,收费工具New Relic等。下图是jconsole查看线程信息的界面:

    下面说一下如何通过Linux命令行,查看服务器中的连接数和线程数。

    1、连接数

    假设Tomcat接收http请求的端口是8083,则可以使用如下语句查看连接情况:

    1

    netstat –nat | grep 8083

    2、线程

    ps命令可以查看进程状态,如执行如下命令:

    1

    ps –e | grep java

    结果如下图:

     

    可以看到,只打印了一个进程的信息;27989是线程id,java是指执行的java命令。这是因为启动一个tomcat,内部所有的工作都在这一个进程里完成,包括主线程、垃圾回收线程、Acceptor线程、请求处理线程等等。

    通过如下命令,可以看到该进程内有多少个线程;其中,nlwp含义是number of light-weight process。

    1

    ps –o nlwp 27989

     

    可以看到,该进程内部有73个线程;但是73并没有排除处于idle状态的线程。要想获得真正在running的线程数量,可以通过以下语句完成:

    1

    ps -eLo pid ,stat | grep 27989 | grep running | wc -l

    其中ps -eLo pid ,stat可以找出所有线程,并打印其所在的进程号和线程当前的状态;两个grep命令分别筛选进程号和线程状态;wc统计个数。其中,ps -eLo pid ,stat | grep 27989输出的结果如下:

     

    图中只截图了部分结果;Sl表示大多数线程都处于空闲状态。

    展开全文
  • 面试官:tomcat是如何处理http请求的?

    千次阅读 多人点赞 2021-01-17 10:09:29
    Servlet技术是我们java后端工程师必须掌握的,这里我们可以把java web技术路线可以大致归纳为如下过程:因为tomcat实现了Servlet规范,所以我们得掌握什么是Serv...

    Servlet技术是我们java后端工程师必须掌握的,这里我们可以把java web技术路线可以大致归纳为如下过程:

    因为tomcat实现了Servlet规范,所以我们得掌握什么是Servlet?什么是Servlet规范?

    什么是Servlet呢?

    Servlet是JavaEE规范的一种,主要是为了扩展Java作为Web服务的功能,统一接口。由其他内部厂商如tomcat,jetty内部实现web的功能。如一个http请求到来:容器将请求封装为servlet中的HttpServletRequest对象,调用init(),service()等方法输出response,由容器包装为httpresponse返回给客户端的过程。

    什么是Servlet规范?

    • 从 Jar 包上来说,Servlet 规范就是两个 Jar 文件。servlet-api.jar 和 jsp-api.jar,Jsp 也是一种 Servlet。

    • 从package上来说,就是 javax.servlet 和 javax.servlet.http 两个包。

    • 从接口来说,就是规范了 Servlet 接口、Filter 接口、Listener 接口、ServletRequest 接口、ServletResponse 接口等。类图如下:

    为什么我们将tomcat称为Web容器或者Servlet容器 ?

    我们用一张图来表示他们之间的关系:

    简单的理解:启动一个ServerSocket,监听8080端口。Servlet容器用来装我们开发的Servlet。

    tomcat架构介绍

    tomcat架构图

    架构图与tomcat中conf下面的server.xml中内容对比:

    <?xml version="1.0" encoding="UTF-8"?>
    <Server port="8005" shutdown="SHUTDOWN">
      <Listener className="org.apache.catalina.startup.VersionLoggerListener" />
      <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
      <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
      <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
      <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
      <GlobalNamingResources>
        <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>
      <Service name="Catalina">
        <Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />
        <Engine name="Catalina" defaultHost="localhost">
          <Realm className="org.apache.catalina.realm.LockOutRealm">
            <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
                   resourceName="UserDatabase"/>
          </Realm>
          <Host name="localhost"  appBase="webapps"
                unpackWARs="true" autoDeploy="true">
            <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" />
            <Context docBase="F:/workspace/my-web-maven/target" path="/" reloadable="true" /> 
            <Context docBase="F:/workspace/my-web-maven/target" path="/tian" reloadable="true" /> 
      </Host>
        </Engine>
      </Service>
    </Server>
    

    架构图和server.xml内容对比,server.xml就是架构图的xml版本,由此可以猜测我们java代码中也应该有与之对应的类。

    比如说:Listener类、Service类、Host类、Engine类等,这个后面再具体分析,这里只是猜测一下我们java代码中的实现。

    看过前面Mybatis源码分析文章的同学,这里也应该能猜到,这个server.xml配置文件解析方式以及如何存放这些配置信息。

    tomcat启动时是通过读取server.xml配置文件的参数,加载每个对应的组件,同时该文件中配置了tomcat的相关可调控参数,实际项目中对tomcat的优化工作大部分都是这个配置文件里的参数调整。

    tomcat组件介绍

    server

    关于server和tomcat的关系,可以理解为我们说的启动一个tomcat就是启动一个server。

    作为Tomcat最外层的核心组件,Server组件的作用主要有以下几个。

    • 提供了监听器机制,用于在Tomcat整个生命周期中对不同事件进行处理;

    • 提供了Tomcat容器全局的命名资源实现;

    • 监听某个端口以接收SHUTDOWN命令;

    service

    Service 表示一个或多个 Connector 的集合,这些 Connector 共享同一个 Container 来处理其请求。在同一个 Tomcat 实例内可以包含任意多个 Service 实例,它们彼此独立

    Connector

    Connector用于接受请求并将请求封装成Request和Response,然后交给Container进行处理,Container处理完之后在交给Connector返回给客户端。

    Container

    Container用于封装和管理Servlet,以及具体处理Request请求;包含4大请求处理组件:引擎(engine)、虚拟主机、上下文(context)组件。Container是容器的父接口,用于封装和管理Servlet,以及具体处理Request请求,该容器的设计用的是典型的责任链的设计模式,它由四个自容器组件构成,分别是Engine、Host、Context、Wrapper。这四个组件是负责关系,存在包含关系。只包含一个引擎。

    Engine

    表示整个 Servlet 引擎。在 Tomcat 中, Engine 为最高层级的容器对象。尽管 Engine 不是直接处理请求的容器,却是获取目标容器的入口。引擎表示可运行的Catalina的servlet引擎实例,并且包含了servlet容器的核心功能。在一个服务中只能有一个引擎。同时,作为一个真正的容器,Engine元素之下可以包含一个或多个虚拟主机Host。

    Host

    代表一个站点,也可以叫虚拟主机,通过配置Host就可以添加站点。Host容器是Engine容器的子容器,上面也说到Host是受Engine容器管理的,就是指一个虚拟主机,比如我们在访问具体jsp页面URL中localhost就是一个虚拟主机,其作用是运行多个应用,并对这些应用进行管理,其子容器是Context,而且一个主机还保存了主机的相关信息。

    Context

    Context 作为一类容器,用于表示 Servletcontext ,在 Servlet 规范中,一个 Servletcontext 即表示一个独立的 Web 应用。代表一个应用程序,对应着平时研发的一套程序,或者WEB-INF目录以及下面的web.xml文件 。

    Wapper

    Wapper 作为一类容器,用于表示 Web 应用中定义的 Servlet,每一个Wrapper封装这一个Servlet。

    组件关系

    tomcat两个核心组件

    Connector:主要负责处理Socket连接,以及Request与Response的转化。

    Container:包括Engine、Host、Context和Wrapper,主要负责内部的处理以及Servlet的管理

    tomcat处理Http请求流程

    上面说完了tomcat整体架构,下面我们来说说,假设来我们在浏览器上输入

    http://localhost:8080/my-web-mave/index.jsp

    在tomcat中是如何处理这个请求流程的:

    1. 我们的请求被发送到本机端口8080,被在那里侦听的Coyote HTTP/1.1 Connector获得。

    2. Connector把该请求交给它所在的Service的Engine来处理,并等待来自Engine的回应 。

    3. Engine获得请求localhost/my-web-maven/index.jsp,匹配它所拥有的所有虚拟主机Host ,我们的虚拟主机在server.xml中默认配置的就是localhost。

    4. Engine匹配到name=localhost的Host(即使匹配不到也把请求交给该Host处理,因为该Host被定义为该Engine的默认主机)。

    5. localhost Host获得请求/my-web-maven/index.jsp,匹配它所拥有的所有Context。

    6. Host匹配到路径为/my-web-maven的Context(如果匹配不到就把该请求交给路径名为”"的Context去处理)。

    7. path=”/my-web-maven”的Context获得请求/index.jsp,在它的mapping table中寻找对应的servlet 。

    8. Context匹配到URL PATTERN为*.jsp的servlet,对应于JspServlet类。

    9. 构造HttpServletRequest对象和HttpServletResponse对象,作为参数调用JspServlet的doGet或doPost方法 。

    10. Context把执行完了之后的HttpServletResponse对象返回给Host 。

    11. Host把HttpServletResponse对象返回给Engine 。

    12. Engine把HttpServletResponse对象返回给Connector 。

    13. Connector把HttpServletResponse对象返回给客户browser 。

      流程图:有些模糊。

    「为了未来好一点 ,现在苦一点算什么」

    推荐阅读

    掌握Mybatis动态映射,我可是下了功夫的

    2020所有原创

    写给大忙人看的JAVA核心技术.pdf下载

    图解多线程

    京东面试:说说MySQL的架构体系

    Mybatis 中xml和注解映射,so easy啦


    展开全文
  • Tomcat处理HTTP请求源码分析(下)

    千次阅读 2012-11-15 21:25:23
    这样,这些应用服务器的性能基本上就取决于Tomcat处理HTTP请求的connector模块的性能。本文首先从应用层次分析了tomcat所有的connector种类及用法,接着从架构上分析了connector模块在整个tomcat中所处的位置,最后...

    很多开源应用服务器都是集成tomcat作为web container的,而且对于tomcat的servlet container这部分代码很少改动。这样,这些应用服务器的性能基本上就取决于Tomcat处理HTTP请求的connector模块的性能。本文首先从应用层次分析了tomcat所有的connector种类及用法,接着从架构上分析了connector模块在整个tomcat中所处的位置,最后对connector做了详细的源代码分析。并且我们以Http11NioProtocol为例详细说明了tomcat是如何通过实现ProtocolHandler接口而构建connector的。


    4 如何实现Connector
    上篇地址为《Tomcat处理HTTP请求源码分析(上)》 ,本文是系列下篇。

    由上面的介绍我们可以知道,实现Connector就是实现ProtocolHander接口的过程。

    AjpAprProtocol、AjpProtocol、Http11AprProtocol、Http11Protocol、JkCoyoteHandler、MemoryProtocolHandler这些实现类的实现流程与Http11NioProtocol相同,下面我们以Http11NioProtocol为类重点说明tomcat中如何实现ProtocolHander接口的。

    Http11NioProtocol实现了ProtocolHander接口,它将所有的操作委托给NioEndpoint类去做,如下图:

    NioEndpoint类中的init方法中首先以普通阻塞方式启动了SocketServer:

    NioEndpoint类的start方法是关键,如下:

    可以看出,在start方法中启动了两个线程和一个线程池:

    • Acceptor线程,该线程以普通阻塞方式接收客户端请求(socket.accep()),将客户Socket交由线程池是处理,线程池要将该Socket配置成非阻塞模式(socket.configureBlocking(false)),并且向Selector注册READ事件。该线程数目可配置,默认为1个。
    • Poller线程,由于Acceptor委托线程为客户端Socket注册了READ事件,当READ准备好时,就会进入Poller线程的循环,Poller线程也是委托线程池去做,线程池将NioChannel加入到ConcurrentLinkedQueue<NioChannel>队列中。该线程数目可配置,默认为1个。
    • 线程池,就是上面说的做Acceptor与Poller线程委托要做的事情。

    4.1 Init接口实现方法中阻塞方式启动ServerSocketChannel

    在Init接口实现方法中阻塞方式启动ServerSocketChannel。

    4.2 Start接口实现方法中启动所有线程

    Start方法中启动了线程池,acceptor线程与Poller线程。其中acceptor与poller线程一般数目为1,当然,数目也可配置。

    可以看出,线程池有两种实现方式:

    • 普通queue + wait + notify方式,默认使用的方式,据说实际测试这种比下种效率高
    • JDK1.5自带的线程池方式

    4.3 Acceptor线程接收客户请求、注册READ事件

    在Acceptor线程中接收了客户请求,同时委托线程池注册READ事件。

    1. 在Acceptior线程中接收了客户请求(serverSock.accept())

    2. 委托线程池处理

    3. 在线程池的Worker线程的run方法中有这么几句:

    在setSocketOptions方法中,首先将socket配置成非阻塞模式:

    在setSocketOptions方法中,最后调用getPoller0().register(channel);一句为SocketChannel注册READ事件,register方法代码如下(注意:这是Poller线程的方法):

    其中attachment的结构如下,它可以看做是一个共享的数据结构:

    4.4 Poller线程读请求、生成响应数据、注册WRITE事件

    1. 在上面说的setSocketOptions方法中调用Poller线程的register方法注册读事件之后,当READ准备就绪之后,就开始读了。下面代码位于Poller线程的run方法之中:

    2. 可以看到,可读之后调用processSocket方法,该方法将读处理操作委拖给线程池处理(注意此时加入到线程池的是NioChannel,不是SocketChannel):

    3. 线程池的Worker线程中的run方法中的部分代码如下(请注意handler.process(socket)这一句):

      注意:

      • 调用了hanler.process(socket)来生成响应数据)
      • 数据生成完之后,注册WRITE事件的,代码如下:

    4.5 Handle接口实现类通过Adpater调用Servlet容器生成响应数据

    NioEndpoint类中的Handler接口定义如下:

    其中process方法通过Adapter来调用Servlet Container生成返回结果。Adapter接口定义如下:

    4.6 小结

    实现一个tomcat连接器Connector就是实现ProtocolHander接口的过程。Connector用来接收Socket Client端的请求,通过内置的线程池去调用Servlet Container生成响应结果,并将响应结果同步或异步的返回给Socket Client。在第三方应用集成tomcat作为Web容器时,一般不会动Servlet Container端的代码,那么connector的性能将是整个Web容器性能的关键。

    展开全文
  • 1.Tomcat原理以及处理http请求过程

    千次阅读 2018-04-29 22:22:53
    Tomcat作为Servlet容器,负责处理客户端请求,把请求传送给Servlet,并将Servlet的响应返回给客户端。二.Tomcat的体系结构Tomcat是一个基于组件的服务器,它的构成组件都是可配置的。其各个组件都在Tomcat安装目录下...
  • tomcat源码系列---HTTP请求处理过程

    千次阅读 2018-09-03 22:10:15
    tomcat源码系列—HTTP请求处理过程 分析tomcatHTTP请求处理过程得从Connector的架构说起,前面说过Connector是用于接收请求,并将请求封装成Request和Response,然后交给Container处理处理完之后再由...
  • Tomcat处理HTTP请求 详解Connector模块

    千次阅读 2011-12-21 09:41:07
    Tomcat处理HTTP请求 详解Connector模块 2011年12月20日10:44 来源:InfoQ 作者:张华 编辑:皮丽华 评论:0条  【IT168 技术】很多开源应用服务器都是集成tomcat作为web container的,而且对于tomcat的...
  • Tomcat处理HTTP请求源码分析

    千次阅读 2012-09-02 20:48:51
    这样,这些应用服务器的性能基本上就取决于Tomcat处理HTTP请求的connector模块的性能。本文首先从应用层次分析了tomcat所有的connector种类及用法,接着从架构上分析了connector模块在整个tomcat中所处的位置,最后...
  • 这样,这些应用服务器的性能基本上就取决于Tomcat处理HTTP请求的connector模块的性能。本文首先从应用层次分析了tomcat所有的connector种类及用法,接着从架构上分析了connector模块在整个tomcat中所处的位置,最后
  • Servlet之tomcat处理Http请求的流程

    千次阅读 2016-09-08 14:56:17
    1.问题描述:
  • Tomcat处理Http请求和Pipeline机制

    千次阅读 2016-07-05 11:54:59
    Tomcat处理HTTP请求源码分析 tomcat pipline设计模式 Pipeline的机制tomcat对Http处理:假设来自客户的请求为:http://localhost:8080/test/index.jsp请求被发送到本机端口8080,被在那里侦听的Coyote ...
  • Tomcat处理HTTP请求源码分析(上)

    千次阅读 2011-12-18 18:14:45
    Tomcat处理HTTP请求源码分析(上) 很多开源应用服务器都是集成tomcat作为web container的,而且对于tomcat的servlet container这部分代码很少改动。这样,这些应用服务器的性能基本上就取决于Tomcat处理HTTP请求...
  • 2. HTTP 请求在 Web 容器中的处理流程 Web 容器以进程的方式在计算机上运行,我们知道进程是系统资源分配的最小单元,线程是系统任务执行的最小单元。从这个角度看,Web 容器就像是邮包收件人所居住的楼宇或小区,...
  • Tomcat处理HTTP请求:Connector源码

    千次阅读 2014-10-13 21:00:44
    第1页: ...这样,这些应用服务器的性能基本上就取决于Tomcat处理HTTP请求的connector模块的性能。本文首先从应用层次分析了tomcat所有的connector种类及用法,接着从架构上分析了connector模块在
  • Tomcat源码分析--一次HTTP请求过程

    千次阅读 2016-05-08 20:37:45
     上文我们说到endpoint是底层处理I/O具体实现类,那么一次HTTP首先也要从这个类中开始。还是以NIOEndPoint实现类为例子。在NIOEndPoint类中有一个名为Acceptor内部类。该内部类负责接收即将到来的TCP/IP连接,并将...
  • Tomcat系统架构与请求处理流程

    千次阅读 2019-10-22 09:28:50
    文章目录Tomcat顶层架构Tomcat顶层架构小结Connector和Container的微妙关系Container架构分析Container如何处理请求的总结 面试时问到Tomcat相关问题的几率并不高,正式因为如此,很多人忽略了对Tomcat相关技能的...
  • service中增加了对PATCH类型请求处理。 doGet doPut doDelete 都是自己处理处理方法内统一交给(调用)processRequest方法处理, processRequest核心语句是 doService(request, response),在...
  • Tomcat处理请求过程和重要参数详解

    千次阅读 2018-04-21 16:22:59
    Tomcat处理用户连接请求模式 BIO:阻塞模型 NIO:非阻塞模型 APR:高性能,可扩展的模式,Tomcat8版本默认模式 在使用tomcat时,经常会遇到连接数、线程数之类的配置问题,要真正理解这些概念,必须先了解Tomcat的...
  • Tomcat结构以及处理一个请求的过程

    千次阅读 2016-03-18 10:30:32
    1. Tomcat结构 Tomcat是一个基于组件的服务器,它的构成组件都是可配置的,其中最外层的组件是Catalina Servlet容器,其他的组件按照一定的格式要求配置在这个顶层容器中。Tomcat的各个组件是在\conf\server.xml...
  • springboot默认内置了tomcat容器,启动时可以直接启动内置tomcat来启动应用,本文详细介绍tomcat启动全流程及接受http请求全流程 源码分析 直接从源码开始分析,先从run方式开始分析,我们只关注主要流程,即只关心...
  • Tomcat请求处理一个请求的过程

    千次阅读 2018-04-24 15:09:02
    Connector组件是Tomcat两个核心组件之一(另一个是Container),主要任务是负责接收客户端发过来的TCP连接请求,创建一个Request和Response对象用于和请求端交换数据。 Tomcat使用Apache Coyote库来处理网络I/O的。...
  • Tomcat请求处理响应过程

    千次阅读 2019-06-15 19:27:09
    经过上篇Tomcat架构简述,我们了解到Tomcat的结构和模块化,模块之间的关系。因此,到这里,就像我们已经盖好一座大楼,并将其装饰成了酒店。分配了前台(Connector),其他工作服务人员(Container),已经对每层...
  • tomcat处理一个请求的过程

    千次阅读 2017-07-16 22:32:50
    首先,tomcat是一个基于组件的服务器,它的构成组件都是可配置的,可以在tomcat目录下conf/server.xml中进行配置。其配置文件结构如下:顶层类元素:一个配置文件中只能有一个元素,可包含多个Service。 顶层类元素...
  • Tomcat请求处理整体过程

    千次阅读 2018-10-04 15:21:23
    一:Tomcat的各个组件和功能介绍  1. 核心组件是Connector(连接器)组件和Container(容器)组件组成.一个Container对应多个Connector组件构成Service.  2. Connector组件负责在服务端处理客户端连接,包括了接收...
  • Tomcat处理请求过程

    千次阅读 2014-03-06 11:21:20
    Tomcat运行流程 ...请求被发送到本机端口8080,被在那里侦听的Coyote HTTP/1.1 Connector获得 Connector把该请求交给它所在的Service的Engine来处理,并等待Engine的回应 Engine获得请求localhost:8

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 176,892
精华内容 70,756
关键字:

tomcat处理http请求