Tomcat部署深坑,差点引发的血案

2019 Java 开发者跳槽指南.pdf (吐血整理)….>>>


如果你和我一样,只会把war包放到webapps目录下,启动和关闭的话,请跟我一起来学习Tomcat底层原理,以及常见异常及解决办法。干货在最后面


Tomcat部署深坑,差点引发的血案 

Tomcat是什么

Tomcat部署深坑,差点引发的血案












































Tomcat 是一个开源的Web 应用服务器,是由 Apache 开发的一个 Servlet 容器,实现了对 Servlet 和 JSP 的支持,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP 程序的首选,Tomcat是服务器而不是容器。

Tomcat与Apache不是同一个东西,请不要混淆,(以前观念就是同一个东西,其实不是)

Tomcat部署深坑,差点引发的血案 

Tomcat 目录结构

Tomcat部署深坑,差点引发的血案

  • bin - 脚本存放目录,比如启动/关闭, *.sh 文件用于 Unix 系统; *.bat 文件用于 Windows 系统。

  • conf - Tomcat 配置文件目录。

  • logs - Tomcat 默认日志目录。

  • webapps - webapp 运行的目录。

  • lib - Tomcat服务器所需要jar包。

  • work - Tomcat工作目录。

  • temp - 临时文件。

  • conf/server.xml - Tomcat的主配置文件

  • conf/web.xml - 遵循Servlet规范标准的配置文件,用于配置servlet

  • conf/tomcat-user.xml - Realm认证时用到的相关角色、用户和密码等信息;

  • conf/catalina.policy - 安全策略配置文件,在系统资源级别上提供访问控制的能力;

  • conf/catalina.properties -Tomcat内部package的定义及访问相关的控制,

  • conf/logging.properties - 文件即为日志记录器相关的配置信息

Tomcat部署深坑,差点引发的血案 

Tomcat 配置详解

Tomcat部署深坑,差点引发的血案

通过架构图了解conf/service.xml配置

Tomcat部署深坑,差点引发的血案

Server元素表示整个 Catalina servlet 容器。支持以下属性;

属性 描述
className

要使用的实现的Java类名。该类必须实现该org.apache.catalina.Server接口。如果未指定类名,则将使用标准实现。

address

此服务器等待shutdown命令的TCP / IP地址。如果未指定地址,localhost则使用。

port

此服务器等待shutdown命令的TCP / IP端口号。设置为-1禁用关闭端口。

shutdown

必须通过TCP / IP连接接收到指定端口号的命令字符串,以便关闭Tomcat。


Service元素表示一个或多个连接器组件的组合,这些组件共享一个用于处理传入请求的引擎组件。Server 中可以有多个 Service。节点支持以下属性

属性 描述
className

要使用的实现的Java类名。该类必须实现该org.apache.catalina.Service接口。

name

将包含在日志消息中。与特定服务器关联的每个服务的名称必须是唯一的。


Connector代表连接组件。Tomcat 支持三种协议:HTTP/1.1、HTTP/2.0、AJP。 支持以下属性;

属性 描述
port

连接器 将在其上创建服务器套接字并等待传入连接的TCP端口号。

protocol

设置协议以处理传入流量。默认值是 HTTP/1.1使用自动切换机制来选择基于Java NIO的连接器或基于APR / native的连接器。

redirectPort

如果此连接器支持非SSL请求,并且收到匹配 <security-constraint>需要SSL传输的请求,则Catalina将自动将请求重定向到此处指定的端口号。

connectionTimeout

接受连接后,此连接器将等待呈现请求URI行的毫秒数。使用值-1表示没有(即无限)超时。默认值为60000(即60秒),但请注意Tomcat附带的标准server.xml将其设置为20000(即20秒)。

URIEncoding

这指定在%xx解码URL之后用于解码URI字节的字符编码。如果未指定,将使用UTF-8,除非org.apache.catalina.STRICT_SERVLET_COMPLIANCE 系统属性设置为true 将使用ISO-8859-1。(重要:必须手动配置该属性)

redirectPort

如果此连接器支持非SSL请求,并且收到匹配 <security-constraint>需要SSL传输的请求,则Catalina将自动将请求重定向到此处指定的端口号。

 Tomcat 默认端口是8080(http请求默认端口是80

<Connector port="8080" protocol="HTTP/1.1" 
    connectionTimeout="20000"  redirectPort="443"
    URIEncoding="UTF-8" useBodyEncodingForURI="true"/>

Tomcat配置SSL设置(仿https请求,默认端口443

<Connector port="443"
  protocol="org.apache.coyote.http11.Http11Protocol"
   maxThreads="150" SSLEnabled="true" scheme="https" secure="true" 
   clientAuth="false" sslProtocol="TLS"  
   keystoreFile="e:tomcat.keystore"  
   keystorePass="123123" />
 


Engine元素表示与特定的Catalina服务相关联的整个请求处理机器。它接收并处理来自一个或多个连接器的所有请求,并将完成的响应返回给连接器,以便最终传输回客户端

属性 描述
defaultHost

默认的主机名,它标识 主机将处理指向该服务器上主机名的请求,但在这个配置文件中没有配置。该名称必须匹配紧接在name 其中的一个Host元素的属性。

name

此Engine的逻辑名称,用于日志和错误消息。在同一服务器中使用多个Service元素时 ,必须为每个Engine分配一个唯一的名称。

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


Host元素表示一个虚拟主机,它是一个服务器的网络名称(如"www.jumpw.com")与运行Tomcat的特定服务器的关联。

属性 描述
appBase

此虚拟主机的Application Base目录。这是可能包含要在此虚拟主机上部署的Web应用程序的目录的路径名如果未指定,webapps将使用默认值 。

autoDeploy

是否在Tomcat运行时定期检查新的或更新的Web应用程序,标志的值默认为true。

className

要使用的实现的Java类名。该类必须实现该org.apache.catalina.Host接口。

name

通常是在您的域名服务服务器中注册的此虚拟主机的网络名称

示例

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


Context元素表示一个Web应用程序,它在特定的虚拟主机中运行。每个Web应用程序都基于Web应用程序存档(WAR)文件,或者包含相应的解包内容的相应目录,如Servlet规范中所述。

属性 描述
docBase

为应用程序的路径或WAR文件存放的路径 ,可以是绝对路径 ,也可是相对路径,相对路径是相对于<Host >

path

此Web应用程序的访问路径

privileged

设置为true允许此上下文使用容器servlet,如管理器servlet。

reloadable

设置为true如果您希望Catalina监视更改类 /WEB-INF/classes//WEB-INF/lib更改,并在检测到更改时自动重新加载Web应用程序。默认值false

示例

  <Context path="/jumpw" docBase="jumpw" privileged="true" 
          reloadable="false"/>


Tomcat部署深坑,差点引发的血案 

Tomcat请求原理

Tomcat部署深坑,差点引发的血案


Tomcat部署深坑,差点引发的血案

重点,看图说原理请求地址为:http://localhost:8080/passport/login.jsp

1) 浏览器请求被发送到本机端口8080,被Connector(连接器)HTTP/1.1拿到

(1-1)Connector的主要任务是负责接收浏览器的发过来的 tcp 连接请求,创建一个 Request 和 Response 对象分别用于和请求端交换数据,然后会产生一个线程来处理这个请求并把产生的 Request 和 Response 对象传给处理这个请求的线程
2) Connector把该请求交给它所在的Service的Engine来处理,并等待来自Engine的回应
3) Engine获得请求localhost/passport/login.jsp,匹配它所拥有的所有虚拟主机Host
4) Engine匹配到名为localhost的Host(即使匹配不到也把请求交给该Host处理,因为该Host被定义为该Engine的默认主机)
5) localhost Host获得请求/passport/login.jsp,匹配它所拥有的所有Context
6) Host匹配到路径为/wsota的Context(如果匹配不到就把该请求交给路径名为”"的Context去处理)
7) path=”/passport”的Context获得请求/login.jsp,在它的mapping table中寻找对应的servlet
8) Context匹配到URL PATTERN为*.jsp的servlet,对应于JspServlet类
9) 构造HttpServletRequest对象和HttpServletResponse对象,作为参数调用JspServlet的doGet或doPost方法
10)Context把执行完了之后的HttpServletResponse对象返回给Host
11)Host把HttpServletResponse对象返回给Engine
12)Engine把HttpServletResponse对象返回给Connector
13)Connector把HttpServletResponse对象返回给客户browser


Tomcat部署深坑,差点引发的血案 

Tomcat遇到过的坑,填坑


Tomcat部署深坑,差点引发的血案


1.乱码

程序已设置UTF-8编码,IDE也设置UTF-8,部署Tomcat服务器就乱码,其实罪魁祸首就是Connector未设置编码,添加 URIEncoding="UTF-8"即可

2.URL参数包含转义字符

由于Tomcat版本升级,Tomcat对转义有了限制,conf/catalina.properties最后一行有描述,把注释去掉,添加转义字符

tomcat.util.http.parser.HttpParser.requestTargetAllow=| < > 

以后建议对URL参数进行编码,当时未对URL进行编码导致这个问题

3.Spring Sheched定时任务跑两次

这个问题,真的是坑,本地测的完全没有问题,我测别的接口又没有请求两次,定时任务却跑了两次,最终发现在预发布机器上conf/server.xml配置多个Service,当时还不相信,我就访问两个不同端口的同一个项目,都能访问。血崩


周五当时查看了conf/server.xml配置,未发现问题,网上都说appBase和docBase配置有问题,仔细查看并没有,本来周五想要解决,结果部门临时决定喝酒撸串,喝到11点,太爽了,还被逼着吃了两个大腰子,周六一直找,终于一篇博客提醒了我,配置多个Host将会实例化多次,最终被找到,万万没想到项目配置了在两个Service中。


参考资料

http://tomcat.apache.org/tomcat-8.5-doc/config/server.html

http://docs.huihoo.com/apache/tomcat/heavyz/01-startup.html


请大家多多指教

Tomcat部署深坑,差点引发的血案






原文始发于微信公众号(木子道):Tomcat部署深坑,差点引发的血案