框架源码私享笔记(01)Tomcat核心架构功能 | 配置详解
读书笔记:对《活出意义来》这本书的序言特别有感触。其中:不要以成功为目标,你越是对它念念不忘,就越有可能错过它。因为成功犹如幸福,不是追求就能得到;它必须因缘际会...它实际是一个人经心全意投入并把自己置之度外时,不测获得的副产物。外界向你提供的目标,每每以某种奖励吸引着你追随。我们理应拒绝外在的奖励刺激-外驱力,必要自己创建’内奖‘-内驱力。即选定自己的目标,在追求目标的努力中,获得内心的秩序和成长的乐趣。
一、Tomcat概述
二、Tomcat核心功能
2.1 connector-网络毗连器
2.1.1 三种IO模型
2.2 container-servlet 容器
2.2.1 Container的主要功能
2.2.2 Container的容器布局
三、Tomcat架构解析
四、tomcat server.xml配置说明
【公众号搜索:拉丁解牛说技术】接待一起交换讨论。
一、Tomcat概述
Tomcat是Apache基金会基于Java开发开源的web容器。Tomcat应用服务器,又称“汤姆猫”,它开源、轻量、易于集成、社区背书支持的特性,深受Java开发者偏幸。尤其是Tomcat专注于处理servlet和jsp的出色能力深得研发者信赖(固然目前jsp用的企业已经很少,瓶颈在于互联网高并发期间配景下,jsp的响应和吞吐量很难满足需求)。
web服务器除了Tomcat,另有我们认识的Nginx、Apache。Nginx主要用于静态资源、反向署理、负载均衡服务器。而Apache服务器主要用于静态页面和http哀求,别的它有丰富的模块和插件,支持扩展实现负载均衡、虚拟主机等。
本日也是先从架构原理核心功能开头,有个大抵了解,背面在对具体某个核心组件进行详细分享。
二、Tomcat核心功能
Tomcat核心功能有2个:网络毗连器功能+servlet容器功能。
网络毗连器功能,负责是接收客户端的http哀求,并将http哀求转给对应servlet进行处理,以及将servlet处理结果返回给客户端。具体是专注处理来自外部的socket毗连哀求,并将对应IO字节流转成对应Request和Response对象。可以说,网络毗连器就是外交官,专注处理外部通讯事宜。
servlet容器功能,复杂加载和管理servlet,以及处理具体的Request哀求。servlet容器就是真正的内务管家,处理内部具体业务逻辑事宜,也就是我们的接口逻辑。
https://i-blog.csdnimg.cn/direct/055f6beed29e415c85ae98ea37aaccb5.png
这两个核心功能对应Tomcat两个核心源码组件,分别是毗连器connector类,容器container接口。
2.1 connector-网络毗连器
connector之所以可以负责接收和响应外部的哀求,是因为内里有个协议处理器ProtocolHandler,专门负责处理socket通讯。Tomcat 8.0 支持的网络协议有http/1.1另有AJP/1.3 两个协议,而Tomcat8.5之后版本则新增支持下一代http/2.0协议。
2.1.1 三种IO模型
两种协议底层应用的网络IO模型,主要实现都是NIO,NIO2两个模型,别的另有一个APR模型。
https://i-blog.csdnimg.cn/direct/6f34eed192ca405495ebdc25b7f47ca9.png
三个IO模型核心特点和实用场景具体如下:
NIO ,全称Non-blocking I/O,是jdk1.4开始引入,并基于Java NIO类库的channel、buffer、selector去实现多路复用的NIO。具体是允许一个线程同时管理多个channel通道,当一个channel有读写IO事件,selector选择器再关照线程去处理,也就是允许每个线程管理多个IO操作,不像BIO是1V1那样干等,得当高并发毗连数多的场景。
NIO2,全称Non-blocking I/O 2,别的也叫Asynchronous I/O,所以也称为AIO。在jdk7开始引入的异步非壅闭I/O,基于jdk 7的NIO2类库实现。具体是基于事件和回调机制,通过AsynchronousSocketChannel实现异步IO操作,办理数据复制阶段壅闭问题,允许应用程序直接返回不消壅闭。NIO2比NIO得当更高并发和复杂场景的应用,比如大数据处理、高性能网络服务器。
而APR模型(Apache Portable Runtime),是通过C/C++实现封装Unix的IO操作,可以跨平台使用,由于与操作系统底层直接交互,性能优于NIO和NIO2。得当性能要求极高的静态资源和大型web高并发哀求场景。
这里附带说一下BIO,虽然BIO性能不佳,但是日常平凡性能要求场景,我们照旧经常使用和见到BIO。BIO是使用java.io里的FileInputStream和FileOutputStream进行读写操作,由于每次读写必要线程等待完成,导致效率低下性能不佳。
2.1.2 connector的核心组件
毗连器内里有2个核心组件,一个是protocolHandler协议处理器,一个是Adapter适配器。源码filed视图:
https://i-blog.csdnimg.cn/direct/af05a04b5f3742f3ac20f502fa6b355d.png
ProtocolHandler接口,用来处理具体的tcp\http哀求。
Adapter适配器,则将ProtocolHandler处理处理的http哀求Request,转换成servlet容器能处理的servletRequest。
https://i-blog.csdnimg.cn/direct/41a91e31d1a04b90972f86c33693fdb9.png
protocolHandler内部的核心功能,是通过Endpoint和Processor两个核心组件实现具体的协议处理:
其中Endpoint负责监听端口,实现了TCP/IP协议,专门处理socket数据流信息。
而Processor实现http协议,接收Endpoint发过来的socket字节流数据,通过http协议格式解析相关数据,转换成Tomcat的Request对象,末了通过Adapter提交到servlet容器处理。
https://i-blog.csdnimg.cn/direct/f5c565b1ae8d4a4abad02881eac18efb.png
对于协议处理器,Tomcat提供了以下7个实现类,包罗我们常见的基于NIO、NIO2模型并实现http1.1协议、Ajp协议的几个处理器。
https://i-blog.csdnimg.cn/direct/75bc0969855046b1bf202dfc8b185461.png
protocolHandler处理了网络毗连并得到相关哀求对象,为何不直接转给Container容器处理?
为什么必要Adapter适配器去中转?
由于每个协议格式数据不一样,Tomcat通过协议处理器,得到Tomcat的Request对象(org.apache.coyote.Request)。然而servlet容器里定义了自己的ServletRequest对象(HttpServletRequest),为了解耦两者通过Adapter适配器进行转换。
Adapter适配器的存在,就是为了桥接tomcat的Request对象与标准的ServletRequest对象之间的差异,确保Tomcat毗连器可以或许顺利地与Servlet容器进行交互,同时保持系统的机动性和扩展性。
2.2 Servlet Container容器
container容器核心功能,主要负责处理网络毗连器connector发过来的ServletRequest哀求。
https://i-blog.csdnimg.cn/direct/c389b987ad8a412787ca6df0842ca5bb.png
2.2.1 Container的主要功能
它主要的功能有:
1、负责管理Servlet的生命周期,包罗Servlet的初始化、服务处理、销毁等。
2、负责http哀求的调度与执行。当connector毗连器接收到客户端http哀求后,会将哀求转给对应Container容器,Container根据哀求路径和配置信息,找到对应的Servlet并调用服务方法处理哀求。
3、负责响应天生HttpServletResponse对象,并返回给connector,通过connector返回给客户端。
2.2.2 Container的容器布局
Servlet web容器里,主要有四大组:engine、host、context、wrapper。彼此是父子层级关系,具体包含层级关系如下图:
https://i-blog.csdnimg.cn/direct/9014ec42735b4d2594adc3903ab11c1b.png
Engine:代表Servlet引擎,一个Service只能有一个engine引擎,用来管理多个虚拟站点host。
Host:代表一个虚拟主机、站点。一个tomcat可以配置多个虚拟主机地点,然后内里可以包含多个context。
Context:表示一个web服务程序。也就是我们最认识的一个个应用。
wrapper:表示一个Servlet,是Container容器中最底层,没有下一级子类。
如上图所见,自上而下,有点像二叉树分散开来,tomcat通过组合模式来管理这些父子关系容器。
这四种容器,都统一实现了Container接口。他们的几个在server.xml有相关配置标签配置参数。
https://i-blog.csdnimg.cn/direct/db905d89c7c74ec9b17f816329712c8a.png
三、Tomcat架构解析
刚才已经对核心功能的connector、Container进行了详细介绍,接下来从团体再看。团体外部组件就比较简单。
直接看tomcat的server.xml文件可见其构成,server.xml我们非常认识,看起来更加直观,一目了然。
<Server port="8005" shutdown="SHUTDOWN">
<Service name="Catalina">
<Connector port="8080" protocol="HTTP/1.1"/>
<Engine name="Catalina" defaultHost="localhost">
<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true">
<Context path="/ladingjieniu" docBase="ladingjieniu.war"/>
</Host>
</Engine>
</Service>
</Server>
server:是tomcat的最顶级容器,一个tomcat里只有一个server。server表示tomcatServlet容器以及其他组件,负责组装并启动关闭connector毗连器、Servlet容器引擎。
service:一个server有多个service。service的出现,关键在于办理了网络协议解析和Servlet容器解耦问题,具体是整合多个connector毗连器和Container(内里只有一个engine Servlet引擎)绑定到一起,便于两个核心功能的维护和扩展。
connector、Container就和上文说的一致。一个主要负责处理外部的tcp、http哀求。另一个是具体负责Servlet哀求逻辑。
https://i-blog.csdnimg.cn/direct/b8b6d2a8d2b147f88e3deabe3adc2f74.png
彼此之间的父子层级和关联数目关系如下,一个server有多个service,一个service只有一个engine引擎,一个engine可以配置多个host虚拟站点,而一个host可以有多个context web服务,一个context web服务里有多个Servlet wrapper。
https://i-blog.csdnimg.cn/direct/e897d53c32fa4928855b5dd31da70b62.png
四、tomcat server.xml 配置说明
<?xml version="1.0" encoding="UTF-8"?>
<!--
Server是tomcat的最顶级容器,是server.xml的最外层标签,代表整个tomcat容器
参数port,是tomcat用来监听shutdown命令的TCP/IP端口号,默认为
8005。设置为-1,表示禁止通过端口关闭Tomcat,此时shutdown.bat/sh命令不能使用。
如果在一台服务器启动多个tomcat服务实例,该端口需保持差异。
shutdown,用来指定shutdown 命令的别名,默认值SHUTDOWN
-->
<Server port="8005" shutdown="SHUTDOWN">
<!--监听器组件,不同组件功能不一样-->
<Listener className="org.apache.catalina.startup.VersionLoggerListener"/>
<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on"/>
<!--配置全局JNDI资源-->
<GlobalNamingResources>
<!-- 用户数据库Realm,配合tomcat-users.xml,管理tomcat host manager的用户身份验证 -->
<Resource name="ladingjieniu" 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>
<!--
一个server里有多个service,里面有一个engine和多个connector。相当于一个服务
可以配置多个connector去监听外部请求,并在engine Servlet处理。
-->
<Service name="Catalina">
<!-- 供Service内各个Connector组件共享使用的线程池执行器,我们可以定义多个命名线程池 -->
<!--
配置连接器使用连接池参数:
maxThreads:最大并发数
minSpareThreads:线程池的核心线程数
maxIdleTime:Executor中空闲线程超时关闭的毫秒数,默认1分钟
maxConnections 与tomcat建立的最大socket连接数,默认是10000
acceptCount;请求的队列最大长度,默认是100
-->
<Executor name="tomcatThreadPool" namePrefix="ladingjieniushuojishu-exec-"
maxThreads="100" minSpareThreads="50"/>
<!-- 连接器组件,负责接收和响应连接,然后创建Request和Response对象转发给engine
默认连接器,监听端口8080,并支持HTTP/1.1协议,支持指定命名共享线程池的连接器。
port:连接器监听的请求端口,必须唯一
protocol:连接器监听的请求协议类型,默认是http/1.1
redirectPort:如果当前连接器不支持SSL(HTTPS)请求,但是收到SSL(HTTPS)请求时,Catalina将重定向至指定端口的Connector。
URIEncoding:用于解码URL的字符编码,则默认使用 UTF-8。
connectionTimeout:此连接器在建立连接之后等待请求URI的超时时间(毫秒),默认值为60000(即 60秒)。
当client与tomcat建立连接之后,在"connectionTimeout"时间之内,仍然没有得到client的请求数据,此时连接将会被断开。
maxConnections:tomcat在任何给定时间能同时接收和处理的最大连接数,默认1w。
acceptCount:当同时连接数超过maxConnections时,系统会继续接收连接,并放入Accept等待队列的长度,默认是100.
同时连接数超过maxConnections,且等待队列也放满,后续收到的请求都将被直接拒绝。
-->
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000" executor="tomcatThreadPool"
redirectPort="8443"/>
<!--在端口8009上定义使用AJP/1.3协议访问的连接器-->
<!--
<Connector protocol="AJP/1.3"
address="::1"
port="8009"
redirectPort="8443" />
-->
<!--
请求处理组件,一个Service标签只能有一个Engine标签
Engine组件从一个或多个Connector中接收请求并处理,并将完成的响应返回给Connector,最终响应给客户端。
-->
<Engine name="Catalina" defaultHost="localhost">
<!--
一个虚拟主机,可以指定应用程序的基本目录,包含了一个或多个Web应用
默认的虚拟主机名为"localhost",
如果配置多个Host,可以让一个tomcat支持从不同的域名访问Web应用。
autoDeploy : Tomcat 在 运行时应定期检查新的或更新的 Web 应用程序。
appBase :虚拟主机的应用程序基础目录。
unpackWARs:是否将Web应用的WAR文件解压。如果为true,则先解压然后运行解压的Web应用,如果为false,直接使用WAR文件运行Web应用。
-->
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true">
<!--通过日志记录在该Host中处理的相关请求-->
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="localhost_access_log" suffix=".txt"
pattern="%h %l %u %t "%r" %s %b"/>
</Host>
<!--
支持配置多个web服务,域名映射, 需要修改本地hosts文件 。
-->
<Host name="www.ladingjieniu.com" appBase="lading" unpackWARs="true" autoDeploy="true">
<!--
Context的path,表示该 Web 应用程序的虚拟上下文路径。
docBase,表示web应用程序的物理根目录,若该路径是相对路径的话,则是相对于appBase而言,若是绝对路径,则与appBase无关。
reloadable是否支持重新加载web应用程序类,默认为false。
如果设为true,Tomcat服务器在运行时会监视在WEB-INF/classes和Web-INF/lib目录下的class文件变化,服务器自重新加载该Web应用。
-->
<Context docBase="/app/ladingjieniu/myweb-1.0-SNAPSHOT" path="/myweb" reloadable="true" />
</Host>
</Engine>
</Service>
</Server>
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页:
[1]