Linux系统之Tomcat服务
目录
一、Tomcat概述
1、Tomcat介绍
2、Tomcat历史
二、Tomcat原理分析
1、Http工作原理
2、Tomcat整体架构
3、Coyote连接器架构
4、Catalina容器架构
5、Jasper处理流程
6、JSP编译过程
7、Tomcat启动流程
8、Tomcat请求处理流程
三、Tomcat安装与配置
1、单实例安装
环境准备
防火墙与SELinux
JAVA环境
Tomcat下载
Tomcat解压
Tomcat安装
Tomcat启动与关闭
Tomcat启动验证
Tomcat访问
2、多实例环境配置
四、Tomcat配置文件详解
1、配置文件目录
2、server.xml 详解
Server
Listener
GlobalNamingResources
Service
Executor
Connector
Engine
Host
Context
3、tomcat-users.xml 详解
host-manager应用配置
manager应用配置
4、web.xml 详解
ServletContext初始化参数
会话配置
Servlet配置
Listener配置
Filter配置
欢迎页面配置
错误页面配置
五、Tomcat高可用项目
1、项目概述
2、设计构架图
3、实施流程
配置Tomcat
配置Nginx反向代理
访问测试
如何解决session共享问题
一、Tomcat概述
1、Tomcat介绍
Tomcat是Apache 软件基金会(Apache Software Foundation)的Jakarta 项目中的一个核心项目,由Apache、Sun 和其他一些公司及个人共同开发而成。由于有了Sun 的参与和支持,最新的Servlet 和JSP 规范总是能在Tomcat 中得到体现,Tomcat 5支持最新的Servlet 2.4 和JSP 2.0 规范。因为Tomcat 技术先进、性能稳定,而且免费,因而深受Java 爱好者的喜爱并得到了部分软件开发商的认可,成为目前比较流行的Web 应用服务器。
Tomcat 服务器是一个免费的开放源代码的Web 应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP 程序的首选。对于一个初学者来说,可以这样认为,当在一台机器上配置好Apache 服务器,可利用它响应HTML(标准通用标记语言下的一个应用)页面的访问请求。实际上Tomcat是Apache 服务器的扩展,但运行时它是独立运行的,所以当你运行tomcat 时,它实际上作为一个与Apache 独立的进程单独运行的。
2、Tomcat历史
-
Tomcat 最初由Sun公司的软件架构师 James Duncan Davidson 开发,名称为“JavaWebServer”。
-
1999年,在 Davidson 的帮助下,该项目于1999年于apache软件基金会旗下的JServ项目合并,并发布第一个版本(3.x),即是现在的Tomcat,该版本实现了Servlet2.2和JSP 1.1规范 。
-
2001年,Tomcat 发布了4.0版本, 作为里程碑式的版本,Tomcat 完全重新设计了其架构,并实现了Servlet 2.3和JSP 1.2规范。
-
目前 Tomcat 已经更新到 10.0.x版本,但是目前企业中的Tomcat服务器,主流版本还是7.x 和 8.x,所以本课程是基于 8.5 版本进行讲解。
二、Tomcat原理分析
1、Http工作原理
HTTP协议(超文本传输协议)是浏览器与服务器之间的数据传送协议。作为应用层协议,HTTP是基于TCP/IP协议来传递数据的(HTML文件、图片、查询结果等),HTTP协议不涉及数据包(Packet)传输,主要规定了客户端和服务器之间的通信格式。它的整个过程如下图所示:
-
用户通过浏览器进行了一个操作,比如输入网址并回车,或者是点击链接,接着浏览器获取了这个事件。
-
浏览器向服务端发出TCP连接请求。
-
服务程序接受浏览器的连接请求并经过TCP三次握手建立连接。
-
浏览器将请求数据打包成一个HTTP协议格式的数据包。
-
浏览器将该数据包推入网络,数据包经过网络传输,最终达到端服务程序。
-
服务端程序拿到这个数据包后,同样以HTTP协议格式解包,获取到客户端的意图。
-
得知客户端意图后进行处理,比如提供静态文件或者调用服务端程序获得动态结果。
-
服务器将响应结果(可能是HTML或者图片等)按照HTTP协议格式打包。
-
服务器将响应数据包推入网络,数据包经过网络传输最终达到到浏览器。
-
浏览器拿到数据包后,以HTTP协议的格式解包,然后解析数据,假设这里的数据是 HTML。
-
浏览器将HTML文件展示在页面上。
2、Tomcat整体架构
(了解)
Tomcat要实现两个核心功能:
-
处理Socket连接,负责网络字节流与Request和Response对象的转化。
-
加载和管理Servlet,以及具体处理Request请求。
因此Tomcat设计了两个核心组件连接器(Connector)和容器(Container)来分别做这 两件事情。连接器负责对外交流,容器负责内部处理。
3、Coyote连接器架构
Coyote是Tomcat的连接器框架的名称 , 是Tomcat服务器提供的供客户端访问的外部接口。客户端通过Coyote与服务器建立连接、发送请求并接受响应 。
Coyote封装了底层的网络通信(Socket请求及响应处理),为Catalina容器提供了统一的接口,使Catalina容器与具体的请求协议及IO操作方式完全解耦。Coyote 将Socket输入转换封装为Request对象,交由Catalina容器进行处理,处理请求完成后,Catalina通过Coyote提供的Response对象将结果写入输出流 。
Coyote作为独立的模块,只负责具体协议和IO的相关操作,与Servlet规范实现没有直接关系,因此即便是Request和Response对象也并未实现Servlet规范对应的接口, 而是在Catalina中将他们进一步封装为ServletRequest和ServletResponse。
在Coyote中,Tomcat支持的IO模型
IO模型 | 描述 |
---|---|
NIO | 非阻塞I/O,采用Java NIO类库实现。 |
NIO2 | 异步I/O,采用JDK 7最新的NIO2类库实现。 |
APR | 采用Apache可移植运行库实现,是C/C++编写的本地库。如果选择该方案,需要单独安装APR库。 |
在Coyote中,Tomcat支持的应用层协议
应用层协议 | 描述 |
---|---|
HTTP/1.1 | 这是大部分Web应用采用的访问协议。 |
AJP/1.3 | 用于和Web服务器集成(如Apache),以实现对静态资源的优化以及集群部署。 |
HTTP/2 | HTTP 2.0大幅度的提升了Web性能。下一代HTTP协议 , 自8.5以及9.0版本之后支持。 |
协议分层
在8.0之前,Tomcat 默认采用的I/O方式为 BIO,之后改为 NIO。 无论 NIO、NIO2还是 APR,在性能方面均优于以往的BIO。 如果采用APR,甚至可以达到 Apache HTTP Server的影响性能。
Tomcat为了实现支持多种I/O模型和应用层协议,一个容器可能对接多个连接器,就好比一个房间有多个门。但是单独的连接器或者容器都不能对外提供服务,需要把它们组装起来才能工作,组装后这个整体叫作Service组件。这里请你注意,Service本身没有做什么重要的事情,只是在连接器和容器外面多包了一层,把它们组装在一起。Tomcat内可能有多个Service,这样的设计也是出于灵活性的考虑。通过在Tomcat中配置多个Service,可以实现通过不同的端口号来访问同一台机器上部署的不同应用。
Coyote的主要组件结构:
Coyote的各个组件的作用:
-
EndPoint:Coyote 通信端点,即通信监听的接口,是具体Socket接收和发送处理器,是对传输层的抽象,因此EndPoint用来实现TCP/IP协议的。Tomcat 并没有EndPoint接口,而是提供了一个抽象类AbstractEndpoint,里面定义了两个内部类:Acceptor和SocketProcessor。Acceptor用于监听Socket连接请求。SocketProcessor用于处理接收到的Socket请求,它实现Runnable接口,在Run方法里调用协议处理组件Processor进行处理。为了提高处理力,SocketProcessor被提交到线程池来执行,而这个线程池叫作执行器(Executor)。
-
Processor:Coyote 协议处理接口,如果说EndPoint是用来实现TCP/IP协议的,那么Processor用来实现HTTP协议,Processor接收来自EndPoint的Socket,读取字节流解析成Tomcat Request和Response对象,并通过Adapter将其提交到容器处理,Processor是对应用层协议的抽象。
-
ProtocolHandler:Coyote 协议接口,通过Endpoint和Processor,实现针对具体协议的处理能力。Tomcat按照协议和I/O 提供了6个实现类 : AjpNioProtocol、AjpNio2Protocol、AjpAprProtocol、Http11NioProtocol、Http11Nio2Protocol、Http11AprProtocol。我们在配置tomcat / conf / server.xml时,至少要指定具体的ProtocolHandler , 当然也可以指定协议名称,如:HTTP/1.1,如果安装了APR,那么将使用Http11AprProtocol,否则使用 Http11NioProtocol 。
-
Adapter:由于协议不同,客户端发过来的请求信息也不尽相同,Tomcat定义了自己的Request类 来“存放”这些请求信息。ProtocolHandler接口负责解析请求并生成Tomcat Request类。 但是这个Request对象不是标准的ServletRequest,也就意味着,不能用Tomcat Request作为参数来调用容器。Tomcat设计者的解决方案是引入CoyoteAdapter,这是 适配器模式的经典运用,连接器调用CoyoteAdapter的Sevice方法,传入的是Tomcat Request对象,CoyoteAdapter负责将Tomcat Request转成ServletRequest,再调用容器的Service方法。
4、Catalina容器架构
Tomcat的模块分层结构
Tomcat本质上就是一款 Servlet 容器,因此Catalina 才是 Tomcat 的核心,其他模块都是为Catalina提供支撑的。比如:通过Coyote模块提供连接通信,Jasper 模块提供JSP引擎,Naming 提供JNDI 服务,Juli提供日志服务。
Catalina的主要组件结构(背会)
Catalina的各个组件的作用
-
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容器具有很好的灵活性。
Container的各个组件的作用:
-
Engine
表示整个Catalina的Servlet引擎,用来管理多个虚拟站点,一个Service最多只能有一个Engine,但是一个引擎可包含多个Host。
-
Host
代表一个虚拟主机或者说一个站点,可以给Tomcat配置多个虚拟主机地址,而一个虚拟主机下可包含多个Context。
-
Context
表示一个Web应用程序, 一个Web应用可包含多个Wrapper。
-
Wrapper
表示一个Servlet,Wrapper 作为容器中的最底层,不能包含子容器。
我们也可以再通过Tomcat的server.xml配置文件来加深对Tomcat容器的理解。Tomcat采用了组件化的设计,它的构成组件都是可配置的,其中最外层的是Server,其他组件按照一定的格式要求配置在这个顶层容器中。
那么,Tomcat是怎么管理这些容器的呢?你会发现这些容器具有父子关系,形成一个树形结构,你可能马上就想到了设计模式中的组合模式。没错,Tomcat就是用组合模式来管理这些容器的。具体实现方法是,所有容器组件都实现了Container接口,因此组合模式可以使得用户对单容器对象和组合容器对象的使用具有一致性。这里单容器对象指的是最底层的Wrapper,组合容器对象指的是上面的Context、Host或者Engine。
5、Jasper处理流程
Tomcat在默认的web.xml中配置了一个org.apache.jasper.servlet.JspServlet,用于处理所有的.jsp或 .jspx结尾的请求,该Servlet 实现即是运行时编译的入口。
JspServlet 处理流程图
如果在 tomcat/conf/web.xml 中配置了参数scratchdir,则jsp编译后的结果,就会存储在该目录下 。 如果没有配置该选项,则会将编译后的结果,存储在Tomcat安装目录下的 work/Catalina(Engine名称)/localhost(Host名称)/Context名称 。
除了运行时编译,我们还可以直接在Web应用启动时, 一次性将Web应用中的所有的JSP页面一次性编译完成。在这种情况下,Web应用运行过程中,便可以不必再进行实时编译,而是直接调用JSP页面对应的Servlet完成请求处理, 从而提升系统性能。
Tomcat 提供了一个Shell程序JspC,用于支持JSP预编译,而且在Tomcat的安装目录下提供了一个 catalina-tasks.xml 文件声明了Tomcat 支持的Ant任务, 因此,我们很容易使用 Ant 来执行JSP 预编译。(要想使用这种方式,必须得确保在此之前已经下载并安装了Apache Ant)。
6、JSP编译过程
Compiler 编译工作主要包含代码生成和编译两部分:
-
代码生成
-
Compiler 通过一个 PageInfo 对象保存JSP 页面编译过程中的各种配置,这些配置可能来源于 Web 应用初始化参数, 也可能来源于JSP页面的指令配置(如 page , include)。
-
调用ParserController 解析指令节点, 验证其是否合法,同时将配置信息保存到 PageInfo 中, 用于控制代码生成。
-
调用ParserController 解析整个页面, 由于 JSP 是逐行解析, 所以对于每一行会创建一个具体的Node 对象。如静态文本(TemplateText)、Java代码(Scriptlet)、定制标签(CustomTag)、Include指令(IncludeDirective)。
-
验证除指令外其他所有节点的合法性, 如脚本、定制标签、EL表达式等。
-
收集除指令外其他节点的页面配置信息。
-
编译并加载当前 JSP 页面依赖的标签。
-
对于JSP页面的EL表达式,生成对应的映射函数。
-
生成JSP页面对应的Servlet类源代码 编译 代码生成完成后,Compiler还会生成 SMAP信息。 如果配置生成 SMAP信息,Compiler则会在编译阶段将SMAP信息写到class文件中 。
-
编译阶段
-
Compiler的两个实现 AntCompiler 和 JDTCompiler 分别调用先关框架的 API 进行源代码编译。
-
对于 AntCompiler 来说, 构造一个 Ant 的javac 的任务完成编译。
-
对于 JDTCompiler 来说, 调用 org.eclipse.jdt.internal.compiler.Compiler 完成编译。
7、Tomcat启动流程
8、Tomcat请求处理流程
三、Tomcat安装与配置
1、单实例安装
环境准备
防火墙与SELinux
[root@tomcat ~]# systemctl disable --now firewalld
[root@tomcat ~]# sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
JAVA环境
#tomcat8可以使用系统中默认的java环境
Tomcat下载
[root@tomcat ~]# tar xf apache-tomcat-8.5.40.tar.gz
Tomcat解压
https://tomcat.apache.org/download-80.cgi
Tomcat安装
[root@tomcat ~]# mv apache-tomcat-8.5.40 /usr/local/tomcat8
Tomcat启动与关闭
##优化启动命令
[root@tomcat ~]# ln -s /usr/local/tomcat8/bin/startup.sh /usr/local/bin/tomcat_start
##优化停止命令
[root@tomcat ~]# ln -s /usr/local/tomcat8/bin/shutdown.sh /usr/local/bin/tomcat_stop
Tomcat启动验证
[root@tomcat ~]# netstat -anptu | grep java
tcp6 0 0 127.0.0.1:8005 :::* LISTEN 58186/java
tcp6 0 0 :::8009 :::* LISTEN 58186/java
tcp6 0 0 :::8080 :::* LISTEN 58186/java
##8005:关闭端口
##8009:AJP协议端口
##8080:HTTP协议端口
Tomcat访问
#默认访问目录,APP存储目录
[root@tomcat webapps]# ls
docs examples host-manager manager ROOT
2、多实例环境配置
##复制多个tomcat应用程序
##修改对应的端口号
四、Tomcat配置文件详解
1、配置文件目录
[root@tomcat conf]# ls
Catalina catalina.properties jaspic-providers.xml logging.properties tomcat-users.xml web.xml
catalina.policy context.xml jaspic-providers.xsd server.xml tomcat-users.xsd
2、server.xml 详解
<?xml version="1.0" encoding="UTF-8"?>
<!--Licensed to the Apache Software Foundation (ASF) under one or morecontributor license agreements. See the NOTICE file distributed withthis work for additional information regarding copyright ownership.The ASF licenses this file to You under the Apache License, Version 2.0(the "License"); you may not use this file except in compliance withthe License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, softwaredistributed under the License is distributed on an "AS IS" BASIS,WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.See the License for the specific language governing permissions andlimitations under the License.
-->
<!-- Note: A "Server" is not itself a "Container", so you may notdefine subcomponents such as "Valves" at this level.Documentation at /docs/config/server.html-->
<Server port="8005" shutdown="SHUTDOWN"><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 --><Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" /><!-- Prevent memory leaks due to use of particular java/javax APIs--><Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" /><Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" /><Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
<!-- Global JNDI resourcesDocumentation at /docs/jndi-resources-howto.html--><GlobalNamingResources><!-- Editable user database that can also be used byUserDatabaseRealm 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 sharea 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">
<!--The connectors can use a shared executor, you can define one or more named thread pools--><!--<Executor name="tomcatThreadPool" namePrefix="catalina-exec-"maxThreads="150" minSpareThreads="4"/>-->
<!-- A "Connector" represents an endpoint by which requests are receivedand responses are returned. Documentation at :Java HTTP Connector: /docs/config/http.htmlJava AJP Connector: /docs/config/ajp.htmlAPR (HTTP/AJP) Connector: /docs/apr.htmlDefine a non-SSL/TLS HTTP/1.1 Connector on port 8080--><Connector port="8080" protocol="HTTP/1.1"connectionTimeout="20000"redirectPort="8443" /><!-- A "Connector" using the shared thread pool--><!--<Connector executor="tomcatThreadPool"port="8080" protocol="HTTP/1.1"connectionTimeout="20000"redirectPort="8443" />--><!-- Define a SSL/TLS HTTP/1.1 Connector on port 8443This connector uses the NIO implementation. The defaultSSLImplementation will depend on the presence of the APR/nativelibrary and the useOpenSSL attribute of theAprLifecycleListener.Either JSSE or OpenSSL style configuration may be used regardless ofthe SSLImplementation selected. JSSE style configuration is used below.--><!--<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"maxThreads="150" SSLEnabled="true"><SSLHostConfig><Certificate certificateKeystoreFile="conf/localhost-rsa.jks"type="RSA" /></SSLHostConfig></Connector>--><!-- Define a SSL/TLS HTTP/1.1 Connector on port 8443 with HTTP/2This connector uses the APR/native implementation which always usesOpenSSL for TLS.Either JSSE or OpenSSL style configuration may be used. OpenSSL styleconfiguration is used below.--><!--<Connector port="8443" protocol="org.apache.coyote.http11.Http11AprProtocol"maxThreads="150" SSLEnabled="true" ><UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol" /><SSLHostConfig><Certificate certificateKeyFile="conf/localhost-rsa-key.pem"certificateFile="conf/localhost-rsa-cert.pem"certificateChainFile="conf/localhost-rsa-chain.pem"type="RSA" /></SSLHostConfig></Connector>-->
<!-- Define an AJP 1.3 Connector on port 8009 --><Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
<!-- An Engine represents the entry point (within Catalina) that processesevery request. The Engine implementation for Tomcat stand aloneanalyzes the HTTP headers included with the request, and passes themon to the appropriate Host (virtual host).Documentation at /docs/config/engine.html -->
<!-- You should set jvmRoute to support load-balancing via AJP ie :<Engine name="Catalina" defaultHost="localhost" jvmRoute="jvm1">--><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 passwordsvia a brute-force attack --><Realm className="org.apache.catalina.realm.LockOutRealm"><!-- This Realm uses the UserDatabase configured in the global JNDIresources under the key "UserDatabase". Any editsthat are performed against this UserDatabase are immediatelyavailable for use by the Realm. --><Realm className="org.apache.catalina.realm.UserDatabaseRealm"resourceName="UserDatabase"/></Realm>
<Host name="www.jx1.com" appBase="webapps/jx1"unpackWARs="true" autoDeploy="true">
<!-- SingleSignOn valve, share authentication between web applicationsDocumentation at: /docs/config/valve.html --><!--<Valve className="org.apache.catalina.authenticator.SingleSignOn" />-->
<!-- Access log processes all example.Documentation at: /docs/config/valve.htmlNote: The pattern used is equivalent to using pattern="common" --><Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"prefix="jx1_access_log" suffix=".txt"pattern="%h %l %u %t "%r" %s %b" />
</Host>
<Host name="www.jx2.com" appBase="webapps/jx2"unpackWARs="true" autoDeploy="true">
<!-- SingleSignOn valve, share authentication between web applicationsDocumentation at: /docs/config/valve.html --><!--<Valve className="org.apache.catalina.authenticator.SingleSignOn" />-->
<!-- Access log processes all example.Documentation at: /docs/config/valve.htmlNote: The pattern used is equivalent to using pattern="common" --><Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"prefix="jx2_access_log" suffix=".txt"pattern="%h %l %u %t "%r" %s %b" />
</Host>
</Engine></Service><Service name="Catalina1">
<!--The connectors can use a shared executor, you can define one or more named thread pools--><!--<Executor name="tomcatThreadPool" namePrefix="catalina-exec-"maxThreads="150" minSpareThreads="4"/>-->
<!-- A "Connector" represents an endpoint by which requests are receivedand responses are returned. Documentation at :Java HTTP Connector: /docs/config/http.htmlJava AJP Connector: /docs/config/ajp.htmlAPR (HTTP/AJP) Connector: /docs/apr.htmlDefine a non-SSL/TLS HTTP/1.1 Connector on port 8080--><Connector port="8081" protocol="HTTP/1.1"connectionTimeout="20000"redirectPort="8444" /><!-- A "Connector" using the shared thread pool--><!--<Connector executor="tomcatThreadPool"port="8080" protocol="HTTP/1.1"connectionTimeout="20000"redirectPort="8443" />--><!-- Define a SSL/TLS HTTP/1.1 Connector on port 8443This connector uses the NIO implementation. The defaultSSLImplementation will depend on the presence of the APR/nativelibrary and the useOpenSSL attribute of theAprLifecycleListener.Either JSSE or OpenSSL style configuration may be used regardless ofthe SSLImplementation selected. JSSE style configuration is used below.--><!--<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"maxThreads="150" SSLEnabled="true"><SSLHostConfig><Certificate certificateKeystoreFile="conf/localhost-rsa.jks"type="RSA" /></SSLHostConfig></Connector>--><!-- Define a SSL/TLS HTTP/1.1 Connector on port 8443 with HTTP/2This connector uses the APR/native implementation which always usesOpenSSL for TLS.Either JSSE or OpenSSL style configuration may be used. OpenSSL styleconfiguration is used below.--><!--<Connector port="8443" protocol="org.apache.coyote.http11.Http11AprProtocol"maxThreads="150" SSLEnabled="true" ><UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol" /><SSLHostConfig><Certificate certificateKeyFile="conf/localhost-rsa-key.pem"certificateFile="conf/localhost-rsa-cert.pem"certificateChainFile="conf/localhost-rsa-chain.pem"type="RSA" /></SSLHostConfig></Connector>-->
<!-- Define an AJP 1.3 Connector on port 8009 --><Connector port="8010" protocol="AJP/1.3" redirectPort="8443" />
<!-- An Engine represents the entry point (within Catalina) that processesevery request. The Engine implementation for Tomcat stand aloneanalyzes the HTTP headers included with the request, and passes themon to the appropriate Host (virtual host).Documentation at /docs/config/engine.html -->
<!-- You should set jvmRoute to support load-balancing via AJP ie :<Engine name="Catalina" defaultHost="localhost" jvmRoute="jvm1">--><Engine name="Catalina1" 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 passwordsvia a brute-force attack --><Realm className="org.apache.catalina.realm.LockOutRealm"><!-- This Realm uses the UserDatabase configured in the global JNDIresources under the key "UserDatabase". Any editsthat are performed against this UserDatabase are immediatelyavailable for use by the Realm. --><Realm className="org.apache.catalina.realm.UserDatabaseRealm"resourceName="UserDatabase"/></Realm>
<Host name="www.jx3.com" appBase="webapps/jx3"unpackWARs="true" autoDeploy="true">
<!-- SingleSignOn valve, share authentication between web applicationsDocumentation at: /docs/config/valve.html --><!--<Valve className="org.apache.catalina.authenticator.SingleSignOn" />-->
<!-- Access log processes all example.Documentation at: /docs/config/valve.htmlNote: The pattern used is equivalent to using pattern="common" --><Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"prefix="jx3_access_log" suffix=".txt"pattern="%h %l %u %t "%r" %s %b" />
</Host>
<Host name="www.jx4.com" appBase="webapps/jx4"unpackWARs="true" autoDeploy="true">
<!-- SingleSignOn valve, share authentication between web applicationsDocumentation at: /docs/config/valve.html --><!--<Valve className="org.apache.catalina.authenticator.SingleSignOn" />-->
<!-- Access log processes all example.Documentation at: /docs/config/valve.htmlNote: The pattern used is equivalent to using pattern="common" --><Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"prefix="jx4_access_log" suffix=".txt"pattern="%h %l %u %t "%r" %s %b" />
</Host>
</Engine></Service>
</Server>
Server
Server是server.xml的根元素,用于创建一个Server实例,默认使用的实现类是 org.apache.catalina.core.StandardServer。
<Server port="8005" shutdown="SHUTDOWN">
...
</Server>
标签属性和子元素:
-
port:Tomcat 监听的关闭服务器的端口。
-
shutdown:关闭服务器的指令字符串。
-
Server内嵌的子元素为 Listener、GlobalNamingResources、Service。
Listener
默认配置的5个Listener的含义:
<!‐‐ 用于以日志形式输出服务器 、操作系统、JVM的版本信息 ‐‐>
<Listener className="org.apache.catalina.startup.VersionLoggerListener" />
<!‐‐ 用于加载(服务器启动) 和 销毁 (服务器停止) APR。 如果找不到APR库, 则会输出日志, 并不影响Tomcat启动 ‐‐>
<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" />
GlobalNamingResources
GlobalNamingResources中定义了全局命名服务:
<GlobalNamingResources><!‐‐ 可编辑的用户数据库,UserDatabaseRealm也可以使用该数据库对用户进行身份验证 ‐‐><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
该元素用于创建 Service 实例,默认使用 org.apache.catalina.core.StandardService。默认情况下,Tomcat 仅指定了Service 的名称, 值为 “Catalina”。Service 可以内嵌的元素为 : Listener、Executor、Connector、Engine,其中 : Listener 用于为Service添加生命周期监听器, Executor 用于配置Service 共享线程池,Connector 用于配置Service 包含的链接器, Engine 用于配置Service中链接器对应的Servlet 容器引擎。一个Server服务器,可以包含多个Service服务。
<Service name="Catalina">
...
</Service>
Executor
默认情况下,Service 并未添加共享线程池配置。 如果我们想添加一个线程池, 可以在 下添加如下配置:
<Executor name="tomcatThreadPool" namePrefix="catalina‐exec‐" maxThreads="200" minSpareThreads="100" maxIdleTime="60000" maxQueueSize="Integer.MAX_VALUE" prestartminSpareThreads="false" threadPriority="5"className="org.apache.catalina.core.StandardThreadExecutor" />
标签属性和子元素:
-
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接口。
Connector
Connector 用于创建链接器实例。默认情况下,server.xml 配置了两个链接器,一个支持HTTP协议,一个支持AJP协议。因此大多数情况下,我们并不需要新增链接器配置, 只是根据需要对已有链接器进行优化。
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
标签属性和子元素:
-
port:端口号,Connector 用于创建服务端Socket 并进行监听, 以等待客户端请求链接。如果该属性设置为0,Tomcat将会随机选择一个可用的端口号给当前Connector使用。
-
protocol:当前Connector 支持的访问协议。 默认为 HTTP/1.1,并采用自动切换机制选择一个基于 JAVA NIO 的链接器或者基于本地APR的链接器(根据本地是否含有Tomcat的本地库判定)。如果不希望采用上述自动切换的机制, 而是明确指定协议, 可以使用以下值。
Http协议:
org.apache.coyote.http11.Http11NioProtocol ,非阻塞式 Java NIO 链接器
org.apache.coyote.http11.Http11Nio2Protocol ,非阻塞式 JAVA NIO2 链接器
org.apache.coyote.http11.Http11AprProtocol ,APR 链接器
AJP协议:
org.apache.coyote.ajp.AjpNioProtocol ,非阻塞式 Java NIO 链接器
org.apache.coyote.ajp.AjpNio2Protocol ,非阻塞式 JAVA NIO2 链接器
org.apache.coyote.ajp.AjpAprProtocol ,APR 链接器
-
connectionTimeout:Connector接收连接后的等待超时时间, 单位为毫秒。 -1 表示不超时。
-
redirectPort:当前Connector 不支持SSL请求, 接收到了一个请求, 并且也符合 security-constraint 约束, 需要SSL传输,Catalina自动将请求重定向到指定的端口。
-
executor:指定共享线程池的名称, 也可以通过maxThreads、minSpareThreads 等属性配置内部线程池。
-
URIEncoding:用于指定编码URI的字符编码, Tomcat8.x版本默认的编码为UTF-8 , Tomcat7.x版本默认为ISO-8859-1。
-
maxThreads:池中最大线程数。
-
minSpareThreads:活跃线程数,也就是核心池线程数,这些线程不会被销毁,会一直存在。
-
acceptCount:接收的连接数。
-
maxConnections:接收的最大连接数。
-
compression:是否压缩。
-
compressionMinSize:压缩的大小。
-
disableUploadTimeout:禁用上传超时。
完整的配置如下:
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" executor="tomcatThreadPool" URIEncoding="UTF‐8"maxThreads="1000" minSpareThreads="100" acceptCount="1000" maxConnections="1000" compression="on" compressionMinSize="2048"disableUploadTimeout="true" />
Engine
Engine 作为Servlet 引擎的顶级元素,内部可以嵌入: Cluster、Listener、Realm、 Valve和Host。
<Engine name="Catalina" defaultHost="localhost">
...
</Engine>
标签属性和子元素:
-
name: 用于指定Engine的名称, 默认为Catalina 。该名称会影响一部分Tomcat的存储路径(如临时文件)。
-
defaultHost : 默认使用的虚拟主机名称, 当客户端请求指向的主机无效时, 将交由默认的虚拟主机处理, 默认为localhost。
Host
Host 元素用于配置一个虚拟主机, 它支持以下嵌入元素:Alias、Cluster、Listener、Valve、Realm、Context。
如果在Engine下配置Realm, 那么此配置将在当前Engine下的所有Host中共享。 同样,如果在Host中配置Realm , 则在当前Host下的所有Context中共享。
Context中的Realm优先级 > Host 的Realm优先级 > Engine中的Realm优先级。
<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true">...
</Host>
标签属性和子元素:
-
name:当前Host通用的网络名称,必须与DNS服务器上的注册信息一致。 Engine中包含的Host必须存在一个名称与Engine的defaultHost设置一致。
-
appBase:当前Host的应用基础目录,当前Host上部署的Web应用均在该目录下(可以是绝对目录,相对路径),默认为webapps。
-
unpackWARs:设置为true,Host在启动时会将appBase目录下war包解压为目录。设置为false, Host将直接从war文件启动。
-
autoDeploy:控制tomcat是否在运行时定期检测并自动部署新增或变更的web应用。
通过给Host添加别名,我们可以实现同一个Host拥有多个网络名称,配置如下:
<Host name="www.web1.com" appBase="webapps" unpackWARs="true" autoDeploy="true"><Alias>www.web2.com</Alias>
</Host>
这个时候,我们就可以通过两个域名访问当前Host下的应用(需要确保DNS或hosts中添加了域名的映射配置)。
Context
Context 用于配置一个Web应用,默认的配置如下:
<Context docBase="myApp" path="/myApp">....
</Context>
标签属性和子元素:
-
docBase:Web应用目录或者War包的部署路径。可以是绝对路径,也可以是相对于Host appBase的相对路径。
-
path:Web应用的Context 路径。如果我们Host名为localhost, 则该web应用访问的根路径为: http://localhost:8080/myApp。
-
它支持的内嵌元素为:CookieProcessor, Loader, Manager,Realm,Resources,WatchedResource,JarScanner,Valve。
简单的举例:
<Host name="www.tomcat.com" appBase="webapps" unpackWARs="true" autoDeploy="true"><Context docBase="myApp" path="/myApp"></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>
3、tomcat-users.xml 详解
host-manager应用配置
Tomcat启动之后,可以通过 http://localhost:8080/host-manager/html 访问该Web应用。 host-manager 默认添加了访问权限控制,当打开网址时,需要输入用户名和密码(conf/tomcat-users.xml中配置) 。所以要想访问该页面,需要在conf/tomcat-users.xml 中配置,并分配对应的角色:
<role rolename="admin-gui"/>
<role rolename="admin-script"/>
<user username="admin" password="123456" roles="admin-gui,admin-script"/>
标签属性和子元素:
-
admin-gui:用于控制页面访问权限。
-
admin-script:用于控制以简单文本的形式进行访问。
启动Tomcat,然后点击host-manager。
manager应用配置
manager的访问地址为 http://localhost:8080/manager,同样,manager也添加了页面访问控制,所以要想访问该页面,需要在conf/tomcat-users.xml 中配置,并分配对应的角色:
<role rolename="admin‐gui" />
<role rolename="admin‐script" />
<role rolename="manager‐gui" />
<role rolename="manager‐script" />
<user username="admin" password="123456" roles="admin-script,admin-gui,manager-gui,manager-script" />
启动Tomcat,然后点击manager。
4、web.xml 详解
(了解)
web.xml 是web应用的描述文件, 它支持的元素及属性来自于Servlet 规范定义 。 在Tomcat 中, Web 应用的描述信息包括 tomcat/conf/web.xml 中默认配置以及 Web应用 WEB-INF/web.xml 下的定制配置。
ServletContext初始化参数
我们可以通过 添加ServletContext 初始化参数,它配置了一个键值对,这样我们可以在应用程序中使用 javax.servlet.ServletContext.getInitParameter()方法获取参数。举例如下:
<context‐param><param‐name>contextConfigLocation</param‐name><param‐value>classpath:applicationContext‐*.xml</param‐value><description>Spring Config File Location</description>
</context‐param>
标签属性和子元素:
-
param‐name:初始化参数名称。
-
param‐value:初始化参数的值。
-
description:这个参数的描述信息。
会话配置
(了解)
用于配置Web应用会话,包括超时时间、Cookie配置以及会话追踪模式。它将覆盖server.xml 和 context.xml 中的配置。举例如下:
<session-config><session-timeout>30</session‐timeout><cookie-config><name>JESSIONID</name><domain>www.baidu.cn</domain><path>/</path><comment>Session Cookie</comment><http-only>true</http‐only><secure>false</secure><max-age>3600</max‐age></cookie‐config><tracking-mode>COOKIE</tracking‐mode>
</session‐config>
标签属性和子元素:
-
session-timeout: 会话超时时间,单位:分钟。
-
cookie-config:用于配置会话追踪Cookie。
-
name:Cookie的名称。
-
domain:Cookie的域名。
-
path:Cookie的路径。
-
comment:Cookie的注释。
-
http-only:Cookie只能通过HTTP方式进行访问,JS无法读取或修改,此项可以增 加网站访问的安全性。
-
secure:此Cookie只能通过HTTPS连接传递到服务器,而HTTP连接则不会传递该信息。注意是从浏览器传递到服务器,服务器端的Cookie对象不受此项影响。
-
max-age:以秒为单位表示cookie的生存期,默认为‐1表示是会话Cookie,浏览器 关闭时就会消失。
-
-
tracking-mode:用于配置会话追踪模式,Servlet3.0版本中支持的追踪模式: COOKIE、URL、SSL。
Servlet配置
(了解)
Servlet 的配置主要是两部分, servlet 和 servlet-mapping :
<servlet><servlet-name>myServlet</servlet‐name><servlet-class>com.caochenlei.MyServlet</servlet‐class><init-param><param-name>fileName</param‐name><param-value>init.conf</param‐value></init‐param><load-on-startup>1</load‐on‐startup><enabled>true</enabled>
</servlet>
<servlet-mapping><servlet-name>myServlet</servlet‐name><url-pattern>*.do</url‐pattern><url-pattern>/myservet/*</url‐pattern>
</servlet‐mapping>
标签属性和子元素:
servlet:
-
servlet-name:指定servlet的名称, 该属性在web.xml中唯一。
-
servlet-class:用于指定servlet类名。
-
init-param:用于指定servlet的初始化参数, 在应用中可以通过 HttpServlet.getInitParameter 获取。
-
param-name:初始化参数名称。
-
param-value:初始化参数的值。
-
-
load-on-startup:用于控制在Web应用启动时,Servlet的加载顺序, 值小于0,web应用启动时,不加载该servlet,第一次访问时加载。
-
enabled:若为false,表示Servlet不处理任何请求。
servlet-mapping:
-
servlet-name:你想要让哪个servlet处理,这里就写哪个servlet名称。
-
url-pattern:用于指定URL表达式,一个 servlet‐mapping可以同时配置多个 url‐ pattern。
servlet 中文件上传配置:
<servlet><servlet-name>uploadServlet</servlet‐name><servlet-class>com.caochenlei.UploadServlet</servlet‐class><multipart-config><location>C://path</location><max-file-size>10485760</max‐file‐size><max-request-size>10485760</max‐request‐size><file-size-threshold>0</file‐size‐threshold></multipart‐config>
</servlet>
标签属性和子元素:
-
multipart-config:上传的配置
-
location:存放生成的文件地址。
-
max-file-size:允许上传的文件最大值。 默认值为‐1, 表示没有限制。
-
max-request-size:针对该 multi/form‐data 请求的最大数量,默认值为‐1, 表示无限制。
-
file-size-threshold:当数量量大于该值时, 内容会被写入文件。
-
Listener配置
Listener用于监听servlet中的事件,例如context、request、session对象的创建、修改、删除,并触发响应事件。Listener是观察者模式的实现,在servlet中主要用于对context、request、session对象的生命周期进行监控。在servlet2.5规范中共定义了8中Listener。在启动时,ServletContextListener 的执行顺序与web.xml 中的配置顺序一致, 停止时执行顺序相反。
<listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener‐class>
</listener>
标签属性和子元素:
-
listener-class:用于指定监听的类,该类必须实现Listener接口
Filter配置
filter 用于配置web应用过滤器, 用来过滤资源请求及响应。 经常用于认证、日志、加密、数据转换等操作, 配置如下:
<filter><filter-name>myFilter</filter‐name><filter-class>com.caochenlei.MyFilter</filter‐class><async-supported>true</async‐supported><init-param><param-name>language</param‐name><param-value>CN</param‐value></init‐param>
</filter>
<filter-mapping><filter-name>myFilter</filter‐name><url-pattern>/*</url‐pattern>
</filter‐mapping>
标签属性和子元素:
filter:
-
filter-name:用于指定过滤器名称,在web.xml中,过滤器名称必须唯一。
-
filter-class:过滤器的全限定类名,该类必须实现Filter接口。
-
async-supported:该过滤器是否支持异步。
-
init-param:用于配置Filter的初始化参数, 可以配置多个, 可以通过FilterConfig.getInitParameter获取。
-
param-name:初始化参数名称。
-
param-value:初始化参数的值。
-
filter-mapping:
-
filter-name:这里指的是你想使用哪个过滤器进行过滤就写哪个过滤器的名称。
-
url-pattern:指定该过滤器需要拦截的URL。
欢迎页面配置
welcome-file-list 用于指定web应用的欢迎文件列表。尝试请求的顺序,从上到下。
<welcome-file-list><welcome-file>index.html</welcome-file><welcome-file>index.htm</welcome-file><welcome-file>index.jsp</welcome-file><welcome-file>default.html</welcome-file><welcome-file>default.htm</welcome-file><welcome-file>default.jsp</welcome-file>
</welcome-file-list>
错误页面配置
error-page 用于配置Web应用访问异常时定向到的页面,支持HTTP响应码和异常类两种形式。
<error-page><error-code>404</error‐code><location>/404.html</location>
</error‐page>
<error-page><error-code>500</error‐code><location>/500.html</location>
</error‐page>
<error-page><exception-type>java.lang.Exception</exception‐type><location>/error.jsp</location>
</error‐page>
五、Tomcat高可用项目
1、项目概述
由于单台Tomcat的承载能力是有限的,当我们的业务系统用户量比较大,请求压力比较大时,单台Tomcat是扛不住的,这个时候,就需要搭建Tomcat的集群,而目前比较流程的做法就是通过Nginx来实现Tomcat集群的负载均衡。
2、设计构架图
3、实施流程
配置Tomcat
##参照多实例配置
配置Nginx反向代理
http {log_format main '$remote_addr - $remote_user [$time_local] "$request" ''$status $body_bytes_sent "$http_referer" ''"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;tcp_nopush on;tcp_nodelay on;keepalive_timeout 65;types_hash_max_size 4096;
include /etc/nginx/mime.types;default_type application/octet-stream;
# Load modular configuration files from the /etc/nginx/conf.d directory.# See http://nginx.org/en/docs/ngx_core_module.html#include# for more information.include /etc/nginx/conf.d/*.conf;upstream tomcats {server 192.168.115.111:8080;server 192.168.115.111:8081;}
server {listen 80;listen [::]:80;server_name _;#root /usr/share/nginx/html;location / {proxy_pass http://tomcats;proxy_set_header Host $host;}# Load configuration files for the default server block.include /etc/nginx/default.d/*.conf;
error_page 404 /404.html;location = /404.html {}
error_page 500 502 503 504 /50x.html;location = /50x.html {}}
访问测试
###
如何解决session共享问题
方案一:ip_hash 策略
通过修改Nginx配置文件,让每个请求按访问 ip 的 hash 结果分配,这样每个访客固定访问一个后端服务器,可以解决 session 的问题。 例如:
方案二:session 复制
在每台Tomcat的 conf/server.xml 配置如下:
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>
在每台Tomcat部署的应用程序中,例如:servlet_demo 的 web.xml 中加入如下配置 :
<distributable/>
注意:上述方案,适用于较小的集群环境(节点数不超过4个),如果集群的节点数比较多的话,通过这种广播的形式来完成Session的复制,会消耗大量的网络带宽,影响服务的性能。