一起进阶学习JAVA:Tomcat
什么是Tomcat
Tomcat 是一个开源的轻量级Web应用服务器,可实现JavaWeb程序的装载,它也具有传统的Web服务器的功能,也可以说Tomcat是一个Servlet容器。
Tomcat系统架构
Tomcat主要服务区B/S架构:浏览器客户端与服务器端交互。
浏览器访问服务器流程
浏览器访问服务器使用的是Http协议,Http是应用层协议,用于定义数据通信格式。数据传输使用的是TCP/IP协议
Tomcat请求处理过程
- 用户通过浏览器向网站发送Http请求。
- Http服务器接收到用户请求。
- Http服务器将请求交予Servlet容器。
- Servlet容器通过Servlet接口调用业务类。
- 返回请求数据。
Tomcat Servlet容器处理流程
当用户请求某个URL资源时
- HTTP服务器会把请求信息使用ServletRequest对象封装
- Servlet容器根据URL喝Servlet的映射关系调用具体的Servlet
- 如果Servlet还没有被加载,就使用反射机制创建这个Servlet并且调用init方法来初始化
- 调用该Servlet中的service方法来处理请求
- 使用ServletResponse对象丰庄返回数据
- 把ServletResponse对象返回给HTTP服务器
- HTTP服务器将响应发送给客户端
Tomcat系统总体架构
Tomcat有两个非常重要的功能
- 和客户端浏览器进行交互,进行Socket通信,将字节流喝Request以及Response等对象进行转换
- Servlet容器处理业务逻辑
因此Tomcat设计了两个核心组件连接器(Connector)
和容器(Container)
来完成Tomcat的两大核心功能
- 连接器,负责对外交流,处理Socket连接,负责网络字节流与
Request
和Response
对象的转化; - 容器,负责内部处理,夹在和管理Servlet,以及具体的处理Request请求
Tomcat连接器组件Coyote
什么是Coyote
Coyote是Tomcat中连接器组件,是对外的接口。客户端通过Coyote与服务器建立连接、发送请求、接受请求。
- Coyote封装了底层的网络通信(Socket请求及响应处理);
- Coyote使Catalina容器(容器组件)与具体的请求协议以及IO操作方式完全解耦
- Coyote将Socket输入转换封装为Request对象,进一步封装后交由Catalina容器进行处理,处理请求完成后,Catalina通过Coyote提供的Response对象将结果写入输出流
- Coyote负责的是具体协议(应用层)和IO(传输层)相关内容
Tomcat Coyote支持多种应用层协议和I/O模型
应用层 | 应用层协议 | 描述 |
---|---|---|
HTTP/1.1 | 这是大部分Web应用采用的访问协议 | |
AJP | 用于和WX集成(如Apache),以实现对静态资源的优化以及集群部署,当前支持AJP/1.3 | |
HTTP/2 | HTTP2.0大幅度的提升了Web性能。下一代HTTP协议,自8.5以及9.0版本之后开始支持 | |
传输层 | IO模型 | 描述 |
NIO | 非阻塞I/O,采用Java NIO类库实现 | |
NIO2 | 异步I/O,采用JDK7最新的NIO2类库实现 | |
APR | 采用Apache可移植运行库实现,是C/C++编写的本地库。如果选择该方案,需要单独安装APR库 |
在8.0之前,Tomcat默认采用的I/O的方式为BIO,之后改为NIO。无论NIO、NIO2还是APR,在性能方面均优于以往的BIO。如果采用APR,伸直可hi达到Apache HTTP Server的影响性能
Coyote的流程
Coyote 组件及作用
组件 | 作用描述 |
---|---|
EndPoint | EndPoint是Coyote通信端点,即通信监听的接口,是具体Socket接收和发送处理器,是对象传输层的抽象,因此EndPoint是用来实现TCP/IP协议的 |
Processor | Processor是Coyote协议处理接口,如果说EndPoint是用来实现TCP/IP协议的,那么Processor用来实现HTTP协议,Processor接受来自EndPoint的Socket,读取字节流解析成Tomcat Request和Response对象,并通过Adapter将其提交到容器处理,Processor是对应用层协议的抽象 |
ProtocolHandler | Coyote协议几口,通过EndPoint和Processor实现针对具体协议的处理能力。Tomcat按照协议和I/O提供的实现类: AjpNioProtocol, AjpAprProtocol҅ ,AjpNio2Protocol ,Http11NioProtocol,Http11Nio2Protocol ,Http11AprProtocol |
Adapter | 由于协议不同,客户端发过来的请求信息也不尽相同,Tomcat定义了自己的Request类来封装这些请求信息。ProtocolHandler接口负责解析请求并生成Tomcat Request类。但是这个Request对象不是标准的ServletRequest,不能用Tomcat Request作为参数来调用容器。Tomcat设计者的解决方案是引入CoyoteAdapter,这是适配器模式的经典运用,连接器调用CoyoteAdapter的Service方法,传入的是Tomcat Request对象,CoyoteAdapter负责将Tomcat Request转换成ServletRequest对象,然后再调用容器 |
Tomcat Servlet容器Catalina
Tomcat是一个由一系列可配置(conf/server.xml
)的组件构成的Web容器,而Catalina是Tomcat的Servlet容器。
Catalina是Tomcat的核心,其他模块都是为Catalina提供支撑的
Servlet容器Catalina的结构
我们可以认为整个Tomcat就是一个Catalina实力,Tomcat启动的时候会初始化这个实力,Catalina实力通过加载server.xml来完成创建一个Server,Server创建并管理多个服务,每个服务又可以又多个Connector和一个Container
- Catalina:负责解析Tomcat的配置文件(
server.xml
)用于创建服务器Server组件并进行管理 - Server:服务器表示整个Catalina Servlet容器以及其他组件,负责组装并启动Servlet引擎,Tomcat连接器。Server通过实现Lifecycle接口,提供了一种优雅的启动和关闭整个系统的方式
- Service:Service是Server的内部组件,一个Server包含多个Service。它将多个Connerctor组件绑定到一个Container
- Container:Container容器负责处理用户Servlet请求,并返回对象给web用户的模块
Container 组件的具体结构
Cintainer组件下有集中具体的组件,分别是Engine、Host、Context和Wrapper。具体配置在conf/server.xml
中
- Engine:表示整个Catalina的Servlet引擎,用来管理多个虚拟站点,一个Service最懂只能有一个Engine,但是一个Engine可以包含多个Host
- Host:代表一个虚拟主机或者站点,可以给Tomcat配置多个虚拟主机地址,而一个虚拟主机下可以包含多个Context
- Context:表示一个Web应用成语,一个Web应用可以包含多个Wrapper
- Wrapper:表示一个Servlet,Wrapper作为容器中的最底层,不能包含子容器
Tomcat服务器核心配置
Tomcat作为服务器的配置,主要是server.xml
文件的配置,server.xml
中包含了Servlet容器的相关配置,即Catalina的配置
主要标签如下
<!-- Server 根元素,创建一个Server实例,子标签有Listener,GlobalNamingResources,Service -->
<Server>
<!-- 定义监听器 -->
<Listener />
<!-- 定义服务器的全局JNDI资源 -->
<GlobalNamingResources />
<!-- 定义Service服务,一个Server标签可以有多个Service服务实例 -->
<Service />
</Server>
Server标签
<!-- port:关闭服务器的监听端口
shutdown:关闭服务器的指令字符串-->
<Server port="8005" shutdown="SHUTDOWN">
<!-- 以日志形式输出服务器、操作系统、JVM的版本信息 -->
<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 -->
<!-- 加载(服务器启动)和销毁(服务器停止)APR。如果找不到APR类库,则会输出日志,并不影响 Tomcat启动 -->
<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
<!-- Prevent memory leaks due to use of particular java/javax APIs-->
<!-- 避免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" />
<!-- Global JNDI resources
Documentation at /docs/jndi-resources-howto.html
GlobalNamingResources 中定义了全局命名服务 -->
<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>
</Server>
Service标签
<!-- 该标签用于创建Service实例,默认使用 org.apache.catalina.core.StandardService
Tomcat默认仅指定了Service的名称,值为Catalina
Service有如下子标签
Listener:用于为Service添加生命周期监听器
Executor:用于配置Service共享线程池
Connector:用于配置Service包含的链接器
Engine:用于配置Service中链接器对应的Servlet容器引擎
-->
<Service name="Catalina">
...
</Service>
Executor标签
<!-- name配置线程池名称,用于Connector中指定
namePrefix配置线程的名称前缀,一般线程名为namePrefix + threadNumber
maxThreads配置线程池最大线程数
minSpareThreads配置活跃线程数,也可以说是核心线程数,核心线程不会被销毁
maxIdleTime配置线程空闲时间,超过该时间后空闲线程会被销毁,单位毫秒,默认6000(1分钟)
maxQueueSize配置先前最大线程排队数
prestartminSpareThreads配置启动线程池时是否启动minSpareThreads线程,false为不启动
threadPriority配置有限期,默认为5,值从1-10,数字越大优先级越高
className配置线程池实现类,如果想自定义需要实现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"/>
Connector标签
Connector标签用于创建链接器实例,默认有2个,一个支持HTTP协议,一个支持AJP协议
一般情况下我们不需要新增,只需要对已有的进行优化
<!--
port:监听端口号,如果设置为0则Tomcat会随机分配一个端口
protocol:支持的访问协议,默认为HTTP/1.1
connectionTimeout:接受连接后的等待超时时间,单位为毫秒,-1为不超时
redirectPort:重定向端口,当前Connector不支持SSL请求,当接收到了符合security-constraint 约束的需要SSL传输的请求会重定向该端口
-->
<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" />
Engine标签
Engine标签标识Servlet引擎
<!--
name:指定Engine名称,默认为Catalina
defaultHost:默认使用的虚拟主机名称,当客户请求指向的主机无效时交由默认的虚拟主机处理
-->
<Engine name="Catalina" defaultHost="localhost">
...
</Engine>
Host标签
Host标签用于配置一个虚拟主机
<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true">
...
</Host>
Context标签
Context用于配置一个Web应用
<Host name="www.xxx.com" appBase="webapps" unpackWARs="true" autoDeploy="true">
<!--
docBase:Web应用录或者War包的部署路径。可以是绝对路径,也可以是相对于 Host appBase的
相对路径。
path:Web应用的Context 路径。如果我们Host名为localhost, 则该web应用访问的根路径为:
http://localhost:8080/web_demo。
-->
<Context docBase="/xxx/xxx/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 "%r" %s %b" />
</Host>