Java Tomcat

基础

资源分配

静态资源

直接被游览器解析

动态资源

不能被游览器解析

通信三要素

协议,主机(IP),端口号

Tomcat下载安装

官网

Apache Tomcat® - Welcome!

安装

解压即可

目录结构
bin

可执行文件(bat为Windows的处理脚本,sh为Linux的处理脚本) startup.bat (开启Tomcat的脚本) shutdown.bat(关闭Tomcat的脚本)

conf 配置文件

配置文件

说明

logging-properties

日志的配置文件

server.xml

当前Tomcat的配置信息,如端口号等

tomcat-users.xml

tomcat的访问用户以及每个用户的信息

web.xml

tomcat部署的所有应用的配置文件

lib

tomcat依赖的jar包

logs

日志信息

temp

临时文件

webapps

tomcat默认应用部署的目录

work

java源码和class字节码存放的目录

Tomcat的启动与停止

配置环境

因为Tomcat中的运行环境需要在java环境下,所以先要有JAVA_HOME

在进行Tomcat的配置

配置CATALINA_HOME 值为Tomcat的安装路径

再将安装路径中的bin与lib目录配置到Path中

启动

双击startup.bat

在游览器搜索:http://localhost:8080/ 出现Tomcat的界面即可

关闭

直接关闭命令行,或者执行shutdown.bat

Tomcat源码

下载

官网中下载即可

运行
  1. 解压
  2. 进入解压目录,并创建一个目录,命名为home,将conf、webapps目录移动至home中
  3. 在当前目录下创建一个pom.xml文件,引入tomcat的依赖包
  4. ·
  5. ·
  6. ·

Tomcat架构

HTTP工作原理

规定服务器和客户端的通信格式

  1. 用户通过游览器向服务器发起请求
  2. 游览器发起TCP连接请求
  3. 服务器接收请求并建立连接
  4. 客户端生成HTML格式的数据包
  5. 客户端将生成的数据包发送至服务端
  6. 服务端解析HTTP格式的数据包
  7. 服务端执行请求
  8. 服务器生成HTTP格式的数据包
  9. 服务器发送响应的数据包给客户端
  10. 客户端游览器解析HTTP格式的数据包
  11. 游览器呈现HTML响应给客户

Tomcat整体架构

HTTP服务器请求处理(业务类实现Servlet接口)

连接器(coyote)

概念

供客户端访问的接外部口

负责

协议和IO操作

IO模型与协议

IO模型

描述

NIO

非阻塞I/O,采用Java NIO类实现

NIO2

异步I/O,采用jdk 7最新的NIO2类库的实现

APR

采用Apache可移植运行库实现,是C/C++编写的本地库,如果选择该方案,需要单独安装APR库

Tomcat支持的应用层协议

应用层协议

描述

HTTP/1.1

这是大部分Web应用采用的访问协议

AJP

用于和Web服务器集成(如Apache),以实现对静态资源的优化以及集群部署

HTTP/2

HTTP 2.0大幅度地提升了Web性能,下一代HTTP协议,自8.5以及9.0版本后支持

连接器的组件

容器(catalina)

概念

通过松耦合的方式集成coyote,以完成按照请求协议进行数据的读写等

地位

结构

Catalina 负责解析Tomcat的配置文件 , 以此来创建服务器Server组件,并根据命令来对其进行管理

Server 服务器表示整个Catalina Servlet容器以及其它组件,负责组装并启动Servlet引擎,Tomcat连接器,Server通过实现Lifecycle接口,提供了一种优雅的启动和关闭整个系统的方式

Service 服务是Server内部的组件,一个Server包含多个Service。它将若干个Connector组件绑定到一个Container(Engine)上

Connector 连接器,处理与客户端的通信,它负责接收客户请求,然后转给相关的容器处理,最后向客户返回响应结果

Container 容器,负责处理用户的servlet请求,并返回对象给web用户的模块

container结构(Tomcat设计了4种容器,分别是Engine、Host、Context和Wrapper。这4种容器不是平行关系,而是父子关系。, Tomcat通过一种分层的架构,使得Servlet容器具有很好的灵活性)

Engine 表示整个Catalina的Servlet引擎,用来管理多个虚拟站点,一个Service最多只能有一个Engine,但是一个引擎可包含多个Host

Host 代表一个虚拟主机,或者说一个站点,可以给Tomcat配置多个虚拟主机地址,而一个虚拟主机下可包含多个Context

Context 表示一个Web应用程序, 一个Web应用可包含多个Wrapper

Wrapper 表示一个Servlet,Wrapper 作为容器中的最底层,不能包含子容器

Tomcat的配置文件server.xml

Tomcat 采用了组件化的设计,它的构成组件都是可配置的,其中最外层的是Server,其他组件 按照一定的格式要求配置在这个顶层容器中

<?xml version="1.0" encoding="UTF-8"?>

<Server port="8005" shutdown="SHUTDOWN">

<Service name="Catalina">

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

<Engine name="Catalina" defaultHost="localhost">

<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true">

<Context></Context>

</Host>

</Engine>

</Service>

</Server>

Tomcat是怎么管理这些容器的呢?你会发现这些容器具有父子关系,形成一个树形结构,你可能马上就想到了设计模式中的组合模式。没错,Tomcat就是用组合模式来管理这些容器的。

具体实现方法是,所有容器组件都实现了Container接口,因此组合模 式可以使得用户对单容器对象和组合容器对象的使用具有一致性。这里单容器对象指的是最底层的Wrapper,组合容器对象指的是上面的Context、Host或者Engine。

**下图尤其重要,Tomcat中Engine,Context,Wrapper,Host接口有很多实现,默认执行标准实现逻辑,即下图中实现类 **

Container接口扩展了LifeCycle接口,LifeCycle接口用来统一管理各组件的生命周期。

LifeCycle接口管理生命周期的主要方法

Tomcat启动流程

步骤(反射、模板等)

1、启动tomcat,需要调用 bin/startup.bat,在startup.bat 脚本中,调用了catalina.bat

2、在catalina.bat 脚本文件中,调用了BootStrap 中的main方法

3、在BootStrap 的main 方法中调用了init方法 , 来创建Catalina 及初始化类加载器

4、在BootStrap 的main 方法中调用了load 方法 , 在其中又调用了Catalina的load方法

5、在Catalina 的load方法中,需要进行一些初始化的工作,并需要构造Digester 对象,用于解析 XML

6、然后在调用后续组件的初始化操作

主要事物:加载Tomcat的配置文件,初始化容器组件,监听对应的端口号,准备接受客户端请求

源码解析

Lifecycle

由于所有的组件均存在初始化、启动、停止等生命周期方法,拥有生命周期管理的特性, 所以Tomcat在设计的时候, 基于生命周期管理抽象成了一个接口 Lifecycle ,而组件 Server、Service、Container、Executor、Connector 组件 , 都实现了一个生命周期的接口,从而具有了以下生命周期中的核心方法:

  1. init() :初始化组件
  2. start() :启动组件
  3. stop() :停止组件
  4. destroy() :销毁组件

各组件的默认实现

上面我们提到的Server、Service、Engine、Host、Context都是接口, 下图中罗列了这些接口的默认实现类。当前对于 Endpoint组件来说,在Tomcat中没有对应的Endpoint接口, 但是有一个抽象类 AbstractEndpoint ,其下有三个实现类: NioEndpoint、Nio2Endpoint、AprEndpoint , 这三个实现类,分别对应于前面讲解链接器 Coyote时, 提到的链接器支持的三种IO模型:NIO、NIO2、APR,Tomcat8.5版本中,默认采用的是 NioEndpoint

ProtocolHandler:Coyote协议接口,通过封装Endpoint和Processor , 实现针对具体协议的处理功能。Tomcat按照协议和IO提供了6个实现类

AJP协议
  1. AjpNioProtocol:采用NIO的IO模型
  2. AjpNio2Protocol:采用NIO2的IO模型
  3. AjpAprProtocol:采用APR的IO模型,需要依赖于APR库
HTTP协议
  1. Http11NioProtocol:采用NIO的IO模型,默认使用的协议(如果服务器没有安装APR)
  2. Http11Nio2Protocol:采用NIO2的IO模型
  3. Http11AprProtocol:采用APR的IO模型,需要依赖于APR库

请求处理流程
  1. 浏览器在请求一个Servlet时,会按照HTTP协议构造一个HTTP请求,通过Socket连接发送给Tomcat
  2. Tomcat通过不同的IO模型都可以接收到Socket的字节流数据
  3. 接收到数据后,按HTTP协议解析字节流,得到HttpServletRequest对象
  4. 再通过HttpServletRequest对象,也就是请求信息,找到该请求对应的Host、Context、Wrapper
  5. 然后将请求交给Engine层处理
  6. Engine层处理完,就会将请求交给Host层处理
  7. Host层处理完,就会将请求交给Context层处理
  8. Context层处理完,就会将请求交给Wrapper层处理
  9. Wrapper层在拿到一个请求后,就会生成一个请求所要访问的Servlet实例对象
  10. 调用Servlet实例对象的service()方法,并把HttpServletRequest对象当做入参
  11. 从而就调用到Servlet所定义的逻辑

Jasper组件

Jasper简介

本质是Servlet

编译方式(核心jar :jatl.jar standard.jar)

运行时编译

预编译

编译过程

Tomcat服务器配置

server.xml

核心配置文件

1、Server

Server元素在最顶层,代表整个Tomcat容器,因此它必须是server.xml中***一个最外层的元素。一个Server元素中可以有一个或多个Service元素

在***部分的例子中,在最外层有一个元素,shutdown属性表示关闭Server的指令;port属性表示Server接收shutdown指令的端口号,设为-1可以禁掉该端口。

Server的主要任务,就是提供一个接口让客户端能够访问到这个Service集合,同时维护它所包含的所有的Service的声明周期,包括如何初始化、如何结束服务、如何找到客户端要访问的Service。

2、Service

Service的作用,是在Connector和Engine外面包了一层,把它们组装在一起,对外提供服务。一个Service可以包含多个Connector,但是只能包含一个Engine;其中Connector的作用是从客户端接收请求,Engine的作用是处理接收进来的请求。

在***部分的例子中,Server中包含一个名称为“Catalina”的Service。实际上,Tomcat可以提供多个Service,不同的Service监听不同的端口,后文会有介绍

Executor(线程池配置)

属性

含义

className

Executor实现的完全限定的Java类名、默认值:org.apache.catalina.core.StandardThread-Executor

daemon

决定这一Executor的线程是否应该为后台线程。如果JVM中的所有其他非后台线程都结束了,则后台线程结束,要获得有关后台线程的详细解释,参见java.lang.Thread的Java 1.5(及更高版本)Javadoc网页、默认值:false

name

共享线程池的名字。这是Connector为了共享线程池要引用的名字。该名字必须唯一、默认值:None;需要的参数

namePrefix

在JVM上,每个运行线程都可以有一个name 字符串。这一属性为线程池中每个线程的name字符串设置了一个前缀,Tomcat将把线程号追加到这一前缀的后面、默认值:tomcat-exec-

maxIdleTime

在Tomcat关闭一个空闲线程之前,允许空闲线程持续的时间(以毫秒为单位)。只有当前活跃的线程数大于minSpareThread的值,才会关闭空闲线程、默认值:60000(一分钟)

maxThreads

该线程池可以容纳的最大线程数、默认值:200

minSpareThreads

Tomcat应该始终打开的最小不活跃线程数、默认值:25

threadPriority

整数值,表示线程池中所有线程的线程优先权

3、Connector

Connector的主要功能,是接收连接请求,创建Request和Response对象用于和请求端交换数据;然后分配线程让Engine来处理这个请求,并把产生的Request和Response对象传给Engine。

通过配置Connector,可以控制请求Service的协议及端口号。在部分的例子中,Service包含两个Connector:

(1)通过配置第1个Connector,客户端可以通过8080端口号使用http协议访问Tomcat。其中,protocol属性规定了请求的协议,port规定了请求的端口号,redirectPort表示当强制要求https而请求是http时,重定向至端口号为8443的Connector,connectionTimeout表示连接的超时时间

在这个例子中,Tomcat监听HTTP请求,使用的是8080端口,而不是正式的80端口;实际上,在正式的生产环境中,Tomcat也常常监听8080端口,而不是80端口。这是因为在生产环境中,很少将Tomcat直接对外开放接收请求,而是在Tomcat和客户端之间加一层代理服务器(如nginx),用于请求的转发、负载均衡、处理静态文件等;通过代理服务器访问Tomcat时,是在局域网中,因此一般仍使用8080端口

(2)通过配置第2个Connector,客户端可以通过8009端口号使用AJP协议访问Tomcat。AJP协议负责和其他的HTTP服务器(如Apache)建立连接;在把Tomcat与其他HTTP服务器集成时,就需要用到这个连接器。之所以使用Tomcat和其他服务器集成,是因为Tomcat可以用作Servlet/JSP容器,但是对静态资源的处理速度较慢,不如Apache和IIS等HTTP服务器;因此常常将Tomcat与Apache等集成,前者作Servlet容器,后者处理静态资源,而AJP协议便负责Tomcat和Apache的连接。Tomcat与Apache等集成的原理如下图(图片来源):

4、Engine

Engine组件在Service组件中有且只有一个;Engine是Service组件中的请求处理组件。Engine组件从一个或多个Connector中接收请求并处理,并将完成的响应返回给Connector,最终传递给客户端。

前面已经提到过,Engine、Host和Context都是容器,但它们不是平行的关系,而是父子关系:Engine包含Host,Host包含Context。

在***部分的例子中,Engine的配置语句如下:

其中,name属性用于日志和错误信息,在整个Server中应该***。defaultHost属性指定了默认的host名称,当发往本机的请求指定的host名称不存在时,一律使用defaultHost指定的host进行处理;因此,defaultHost的值,必须与Engine中的一个Host组件的name属性值匹配。

5、Host
(1)Engine与Host

Host是Engine的子容器。Engine组件中可以内嵌1个或多个Host组件,每个Host组件代表Engine中的一个虚拟主机。Host组件至少有一个,且其中一个的name必须与Engine组件的defaultHost属性相匹配

(2)Host的作用

Host虚拟主机的作用,是运行多个Web应用(一个Context代表一个Web应用),并负责安装、展开、启动和结束每个Web应用。

Host组件代表的虚拟主机,对应了服务器中一个网络名实体(如”www.test.com”,或IP地址”116.25.25.25”);为了使用户可以通过网络名连接Tomcat服务器,这个名字应该在DNS服务器上注册。

客户端通常使用主机名来标识它们希望连接的服务器;该主机名也会包含在HTTP请求头中。Tomcat从HTTP头中提取出主机名,寻找名称匹配的主机。如果没有匹配,请求将发送至默认主机。因此默认主机不需要是在DNS服务器中注册的网络名,因为任何与所有Host名称不匹配的请求,都会路由至默认主机。

(3)Host的配置

在***部分的例子中,Host的配置如下:

下面对其中配置的属性进行说明:

name属性指定虚拟主机的主机名,一个Engine中有且仅有一个Host组件的name属性与Engine组件的defaultHost属性相匹配;一般情况下,主机名需要是在DNS服务器中注册的网络名,但是Engine指定的defaultHost不需要,原因在前面已经说明。

unpackWARs指定了是否将代表Web应用的WAR文件解压;如果为true,通过解压后的文件结构运行该Web应用,如果为false,直接使用WAR文件运行Web应用。

Host的autoDeploy和appBase属性,与Host内Web应用的自动部署有关;此外,本例中没有出现的xmlBase和deployOnStartup属性,也与Web应用的自动部署有关;将在下一节(Context)中介绍。

6、Context
(1)Context的作用

Context元素代表在特定虚拟主机上运行的一个Web应用。在后文中,提到Context、应用或Web应用,它们指代的都是Web应用。每个Web应用基于WAR文件,或WAR文件解压后对应的目录(这里称为应用目录)。

Context是Host的子容器,每个Host中可以定义任意多的Context元素。

在***部分的例子中,可以看到server.xml配置文件中并没有出现Context元素的配置。这是因为,Tomcat开启了自动部署,Web应用没有在server.xml中配置静态部署,而是由Tomcat通过特定的规则自动部署。下面介绍一下Tomcat自动部署Web应用的机制。

(2)Web应用自动部署
Host的配置

要开启Web应用的自动部署,需要配置所在的虚拟主机;配置的方式就是前面提到的Host元素的deployOnStartup和autoDeploy属性。如果deployOnStartup和autoDeploy设置为true,则tomcat启动自动部署:当检测到新的Web应用或Web应用的更新时,会触发应用的部署(或重新部署)。二者的主要区别在于,deployOnStartup为true时,Tomcat在启动时检查Web应用,且检测到的所有Web应用视作新应用;autoDeploy为true时,Tomcat在运行时定期检查新的Web应用或Web应用的更新。除此之外,二者的处理相似

通过配置deployOnStartup和autoDeploy可以开启虚拟主机自动部署Web应用;实际上,自动部署依赖于检查是否有新的或更改过的Web应用,而Host元素的appBase和xmlBase设置了检查Web应用更新的目录

其中,appBase属性指定Web应用所在的目录,默认值是webapps,这是一个相对路径,代表Tomcat根目录下webapps文件夹

xmlBase属性指定Web应用的XML配置文件所在的目录,默认值为conf//,例如部分的例子中,主机localhost的xmlBase的默认值是$TOMCAT_HOME/conf/Catalina/localhost

tomcat-users.xml

Web应用配置

在web.xml中配置

工程目录下配置web.xml

Tomcat管理配置

在安装目录下的webapps中的host-manager 和 manager目录下配置

Tomcat中JVM的配置

JVM内存

-Xmx512m

最大总堆内存,一般设置为物理内存的1/4

-Xms512m

初始总堆内存,一般将它设置的和最大堆内存一样大,这样就不需要根据当前堆使用情况而调整堆的大小了

-Xmn192m

年轻带堆内存,sun官方推荐为整个堆的3/8

堆内存的组成

总堆内存 = 年轻带堆内存 + 年老带堆内存 + 持久带堆内存

年轻带堆内存

对象刚创建出来时放在这里

年老带堆内存

对象在被真正会回收之前会先放在这里

持久带堆内存

class文件,元数据等放在这里

-XX:PermSize=128m

持久带堆的初始大小

-XX:MaxPermSize=128m

持久带堆的最大大小,eclipse默认为256m。如果要编译jdk这种,一定要把这个设的很大,因为它的类太多了。

操作脚本(catalina.bat)来配置选项(Linux为catalina.sh)

属性

含义

-Xms

JVM初始化内存大小,默认是物理内存的1/64

-Xmx

JVM最大内存大小,默认是物理内存的1/4。(一般都把这2个值设置成一样的,防止每次GC后改变堆的大小)

-Xmn

新生代的内存大小,建议为整个堆内存的3/8

-XX:MetaspaceSize

元空间内存初始大小

-XX:MaxMetaspaceSize

元空间最大内存大小

-XX:permSize

非堆内存大小(方法区),默认是物理内存的1/64

-XX:MaxPermSize

非堆内存最大大小(方法区),默认是物理内存的1/4

-XX:NewSize

新生代大小

-XX:MaxNewSize

新生代最大大小

-XX:NewRatio

新生代和老生带的内存配比

-XX:SurvivorRatio

Eden与From和To的内存配比

Tomcat集群

原因

一台Tomcat不能满足需求

使用原理

步骤

  1. 复制两个Tomcat,并改端口号
  2. 下载Nginx
  3. 安装配置Nginx
upstream serverpool {
        server localhost:8888;
        server localhost:9999;
    }


    server {
        listen 99;
        server_name localhost;
        location / {
            proxy_pass http://serverpool/;
        }
    }

负载均衡策略

轮询(可以通过weight权重改动访问概率)

ip-hash:可以通过客户端ip计算hash值,通过hash值决定服务端

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值