一、原理

1. 浏览器拜访服务器流程

    1. 用户输出申请到浏览器
    2. 浏览器发送TCP连贯申请
    3. 服务器接管到(疏忽Nginx等状况)申请并三次握手建设连贯
    4. 浏览器生成HTTP的数据包并发送
    5. 服务器收到并解析
    6. 服务器执行申请并封装后果发送
    7. 浏览器收到HTTP格局数据包并解析渲染

2. Tomcat申请解决流程

首先,Tomcat是一个HTTP服务器

Tomcat中的HTTP服务器(Connectot组件)在接管到申请之后把申请交给Servlet容器(Conntainer组件)来解决(解耦),Servlet容器通过Servlet接口调用业务类,Servlet容器这一套内容叫做Servlet标准

3. Servlet容器解决流程

  1. HTTP服务器把申请信息应用ServletRequest对象封装
  2. 依据配置,找到url和Servlet的映射, 调用Servlet容器中的某个具体Servlet
  3. 如果Servlet还没有加载,就用反射机制创立这个Servlet,并调用Servlet的init办法来实现初始化
  4. 调用这个Servlet的service办法解决申请,处理结果用ServletResponse对象封装
  5. ServletResponse 对象返回给HTTP服务器,HTTP服务器把响应发给客户端

二、组件

1. 连接器组件Coyote

客户端通过Coyote与服务器建设连贯,发送并响应申请

  1. Coyote 封装底层网络通信(Socket申请及响应解决)
  2. Coyote 使 Catalina容器(容器组件)与具体的申请及I/O操作解耦
  3. Coyote 将Socket 输出封装Request对象,容器解决后,Catelina通过Response对象将后果写入输入流
  4. Coyote 去负责具体应用层协定和传输层io相干内容

    ### 2. Servlet 容器 Catalina

Tomcat由一系列可配置(server.xml)的组件形成的web容器,Catalina是它的Servlet容器。某种方面说,Tomcat就是一个Servlet容器,Catalina是它的外围组件。

三、外围配置

配置文件server.xml

<?xml version="1.0" encoding="UTF-8"?><!-- 根元素,定义一个Server实例,本人标签:Listener、GlobalNamingResources、Service--><!-- 监听8005,状态为敞开状态 这里不须要改--><Server port="8005" shutdown="SHUTDOWN">  <!-- 定义监听器 以下都无需更改-->  <!-- 打印JVM、操作系统相干日志 无需更改 -->  <Listener className="org.apache.catalina.startup.VersionLoggerListener" />  <!-- 加载销毁Apr 无需更改 -->  <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />  <!-- 防止JRE内存溢出 -->  <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />  <!-- 加载和进行全局命名服务 -->  <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />  <!-- 在Context进行时重建 Executor 池中的线程,防止 ThreadLocal 相干的内存透露 -->  <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />  <!-- 定义全局JNDI资源 个别无需批改-->  <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>  <!-- 定义service服务容器,一个server能够有很多service -->  <Service name="Catalina">    <!--The connectors can use a shared executor, you can define one or more named thread pools-->        <!-- 配置Service共享线程池 -->    <!-- 默认状况下,Service 并未增加共享线程池配置。 如果咱们想增加一个线程池, 能够在 <Service> 下增加如下配置:           name: 线程池名称,用于 Connector中指定          namePrefix: 所创立的每个线程的名称前缀,一个独自的线程名称为 namePrefix+threadNumber          maxThreads: 池中最大线程数           minSpareThreads: 沉闷线程数,也就是外围池线程数,这些线程不会被销毁,会始终存在           maxIdleTime: 线程闲暇工夫,超过该工夫后,闲暇线程会被销毁,默认值为6000(1分钟),单位毫秒          maxQueueSize: 在被执行前最大线程排队数目,默认为Int的最大值,也就是狭义的有限。除非非凡状况,这个值 不须要更改,否则会有申请不会被解决的状况产生 prestartminSpareThreads: 启动线程池时是否启动 minSpareThreads局部线程。默认值为false,即不启动           threadPriority: 线程池中线程优先级,默认值为5,值从1到10           className: 线程池实现类,未指定状况下,默认实现类为org.apache.catalina.core.StandardThreadExecutor。如果想应用自定义线程池首先须要实现 org.apache.catalina.Executor接口    -->    <Executor       name="commonThreadPool"      namePrefix="thread-exec-"      maxThreads="200"      minSpareThreads="100"      maxIdleTime="60000"      maxQueueSize="Integer.MAX_VALUE"       prestartminSpareThreads="false"      threadPriority="5"       className="org.apache.catalina.core.StandardThreadExecutor"      />     <!-- 一个Service容器能够有多个连接器,每个连贯启动一个线程 -->    <!--       port: 端口号,Connector 用于创立服务端Socket 并进行监听,以期待客户端申请链接。如果该属性设置为0,Tomcat将会随机抉择一个可用的端口号给以后Connector应用      protocol: 以后Connector 反对的拜访协定。默认为 HTTP/1.1,并采纳主动切换机制抉择一个基于 JAVA NIO的链接器或者基于本地APR的链接器依据本地是否含有Tomcat的本地库断定)       connectionTimeOut: Connector 接管链接后的期待超时工夫, 单位为毫秒。 -1 示意不超时。       redirectPort: 以后Connector不反对SSL申请,接管到了一个申请,并且也合乎security-constraint束缚,须要SSL传输,Catalina主动将申请重定向到指定的端口。      executor: 指定共享线程池的名称, 也能够通过maxThreads、minSpareThreads 等属性配置外部线程池。      URIEncoding: 用于指定编码URI的字符编码, Tomcat8.x版本默认的编码为 UTF-8 , Tomcat7.x版本默认为ISO-8859-1    -->    <!--org.apache.coyote.http11.Http11NioProtocol , 非阻塞式 Java NIO 链接器-->     <Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />    <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />    <!-- 应用共享线程池,不明确线程池就会有本人保护的线程池,造成资源节约 -->    <!--     <Connector port="8080"                protocol="HTTP/1.1"               executor="commonThreadPool"                maxThreads="1000"                minSpareThreads="100"                acceptCount="1000"                maxConnections="1000"                connectionTimeout="20000"                compression="on"                compressionMinSize="2048"                disableUploadTimeout="true"                redirectPort="8443"                URIEncoding="UTF-8" /> -->         <!-- A "Connector" using the shared thread pool-->    <!--    <Connector executor="tomcatThreadPool"               port="8080" protocol="HTTP/1.1"               connectionTimeout="20000"               redirectPort="8443" />    -->    <!-- Servlet引擎 -->    <!--      name: 用于指定Engine的名称, 默认为Catalina      defaultHost: 默认应用的虚拟主机名称,当客户端申请指向下边配置Host的主机有效时,将交由默认的虚拟主机解决,默认为localhost    -->    <Engine name="Catalina" defaultHost="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标签用于配置虚拟主机 -->      <!-- 默认解决 ,appbase是相对路径,unpackWARs解压war包,autoDeploy主动部署-->      <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" />      </Host>      <!-- 监听 www.abc.com:8080 -->      <Host name="www.abc.com"  appBase="webapps1"            unpackWARs="true" autoDeploy="true">        <!--        docBase:Web利用目录或者War包的部署门路。能够是绝对路径,也能够是绝对于 Host appBase的 相对路径。        path:Web利用的Context 门路。如果咱们Host名为localhost, 则该web利用拜访的根门路为: http://localhost:8080/web_demo。        -->        <Context docBase="/Users/yingdian/web_demo" path="/web3"></Context>        <!-- 拜访申请日志的 阀  ,寄存门路为相对路径-->        <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>