Tomcat

前言

  • Tomcat 是常见的免费的 web 服务器。

  • Tomcat 是一种野外的猫科动物,不依赖人类,独立生活。

  • Tomcat 的作者取这个名字的初衷是希望,这一款服务器可以自力更生,自给自足,像 Tomcat 这样一种野生动物一般,不依赖其他插件,而可以独立达到提供 web 服务的效果。

  • Tomcat 官网

  • Tomcat 教程

  • Tomcat 快速入门

1、Tomcat

  • Tomcat 是由 Apache 软件基金会下属的 Jakarta 项目开发的一个 Servlet 容器,按照 Sun Microsystems 提供的技术规范开发出来。

  • Tomcat 8 实现了对 Servlet 3.1 和 JavaServer Page 2.3(JSP)的支持,并提供了作为 Web 服务器的一些特有功能,如 Tomcat 管理和控制平台、安全域管理和 Tomcat 附加组件等。

  • Tomcat 文件

    • bin:可执行文件 (打开/关闭服务器的文件)
    • conf:服务器的配置信息
    • lib:服务器使用的 jar 包
    • logs:服务器日志
    • temp:产生的临时文件
    • work:服务器自己的工作空间
    • webapps:默认的存放工程 (应用程序) 文件夹
    • wtpwebapps:跟 Eclipse 关联后产生的存放工程的文件夹

2、配置

3、项目部署

  • Tomcat 项目部署方式有以下三种方式。

  • 第一种方式

    • 直接把项目复制到 Tomcat 安装目录的 webapps\ROOT 目录中。
    • 这是最简单的一种 Tomcat 项目部署的方法,也是初学者最常用的方法。
  • 第二种方式

    • 在 Tomcat 安装目录中有一个 conf 文件夹,打开此文件夹,其中包含配置文件 server.xml。
    • 打开配置文件,并在 <host></host> 之间插入如下语句。
    • 其中,path 为访问 url 路径,如下为 http://localhost:8080/hello。
    • 其中,docBase 为设置项目的路径。

      1
      <Context path="/hello" docBase="F:\eclipse3.2\workspace\hello\WebRoot" debug="0" privileged="true"></Context>
  • 第三种方式

    • 在 conf 目录中,在 Catalina\localhost(此处需要注意目录的大小写)目录下新建一个 XML 文件。
    • 任意命名,只要和当前文件中的文件名不重复即可,代码如下。
    • 这种方法相对来说比较灵活,并且可以设置别名。

      1
      <Context path="/hello" docBase="D:\eclipse3.2\workspace\hello\WebRoot" debug="0" privileged="true"></Context>

4、修改端口

  • Tomcat 默认的端口号是 8080,可以通过配置把端口号修改成 80。

  • 修改端口后必须重启 Tomcat。

  • Tomcat 的端口配置相关信息在 server.xml 文件中。

    1
    2
    3
    <Connector port="8080" protocol="HTTP/1.1"
    connectionTimeout="20000"
    redirectPort="8443" />
  • 修改后就可以直接通过 http://localhost/test.html 访问网页了。

  • 80 端口是 web 服务默认的端口号,所以就不需要显式写这个端口号了。

5、常见问题

5.1 持久化异常

  • 现象:Tomcat 启动的时候会报一个 Exception loading sessions from persistent storage 异常,但是又不影响正常的业务。

  • 分析:该问题的原因是 Tomcat 的 session 持久化机制引起的,Tomcat 这个功能本身的用意在于重启 Tomcat 后保存之前的 session,Tomcat 会把 session 持久化在 %TOMCAT%/work/Catalina/localhost/session.ser 这个文件里。但是因为 Tomcat 非正常关闭,所以这个文件没有正确地结束 (无 EOF 标记)。

  • 解决:

    • 解决办法 治标:只需要删除 session.ser 文件即可。
    • 解决办法 治本:关闭 Tomcat 的持久化功能,就能一劳永逸的解决这个问题。具体为修改 conf 下的 server.xml 文件。在项目的 context 间加入一句代码 <Manager className="org.apache.catalina.session.PersistentManager" saveOnRestart="false"/>,重启 Tomcat 以后再也不会报这个错误了。

5.2 端口冲突

  • 现象:屏幕一闪而过,或者不会关闭,但是提示大量错误,其中会看到 Address already in use: JVM_Bind :80,即表示端口被占用了。

  • 检验:如果是这个错误,在 Tomcat 目录下的 logs 目录里,会有一个日志文件:catalina.yyyy-mm-dd.log(当天时间),在这个日志文件里会记载一样的错误: Address already in use: JVM_Bind :80。即表明 80 端口被占用了。

  • 分析:端口是独占式的,一旦一个程序占用了这个端口,其他程序就不能够再去占用它了。而 80 端口,有可能是被已经存在的 Tomcat 占用了,也有可能是被其他不知名的软件占用了,比如 Apache,IIS,Oracle 等等。

  • 解决:找到端口被占用的程序是哪一个,然后再关闭对应的程序即可。

    • 查看 80 端口被哪些程序占用了

      1
      2
      3
      4
      5
      # Windows
      $ netstat -ano|findstr "80"

      # macOS
      $ lsof -i:80
    • 根据 pid(进程 id)查询对应的应用程序

      1
      2
      # Windows
      $ tasklist|findstr "1828"
    • 结束该程序

      1
      2
      3
      4
      5
      6
      7
      # Windows
      $ taskkill /f /pid 1828

      $ taskkill /f /t /im java.exe

      # macOS kill pid
      $ kill 1828

5.3 JAVA_HOME 环境变量没有设置

  • 现象:点击 startup.bat 之后,屏幕一闪而过。

  • 检验:首先通过 cmd 命令进入控制台,然后切换到对应的目录执行 startup 命令,得到 JRE_HOME environment …. 这么个提示,就表示 JAVA_HOME 环境变量没有设置。

  • 分析:Tomcat 本身是 JAVA 程序,必须要有 JDK 才可以执行,所以必须配 置JAVA_HOME。

  • 解决:进入 JDK 环境变量配置,跟着学习如何进行 JDK 环境变量配置。

5.4 CATALINA_HOME 环境变量设置错误

  • 现象:点击 startup.bat 之后,屏幕一闪而过。

  • 检验:首先通过 cmd 命令进入控制台,然后切换到对应的目录执行 startup 命令,得到 CATALINA_HOME environment …. 这么个提示,就表示 CATALINA_HOME 环境变量设置错误。

  • 分析:Tomcat 执行必须依赖 CATALINA_HOME 或者 CATALINA_BASE 这两个环境变量。如果没有在环境变量里配置过,那么会自动采用 bin 目录的父目录作为 CATALINA_HOME 和 CATALINA_BASE。如果配置了,而所配置的地方又不是正确的 Tomcat 目录,那么就会出现这个错误。

  • 解决:

    • 在环境变量中删除 CATALINA_HOME,CATALINA_BASE 的配置,记得不仅要检查环境变量,还要检查用户变量。
    • 或者把 CATALINA_HOME 设置为正确的 Tomcat 目录。

5.5 CATALINA_HOME 错误设置

  • 现象:Tomcat 可以成功启动,但是就是不能访问自己配置的 web 应用,老是提示 404 错误

  • 检验:如图所示, 在环境变量里,CATALINA_HOME 设置在了另一个合法的 Tomcat 目录上,所以无论运行哪个 startup.bat,都会导致这个 d:/tomcatxxxx 目录下的程序被启动,而不是你期望的那个。

  • 分析:默认的 Tomcat 会优先根据环境变量中的 CATALINA_HOME 来定位目录,并运行。

  • 解决:

    • 在环境变量中删除 CATALINA_HOME,CATALINA_BASE 的配置,记得不仅要检查环境变量,还要检查用户变量。
    • 或者使用纯净版 Tomcat,取消了对环境变量 CATALINA_HOME 和 CATALINA_BASE 的依赖。

5.6 localhost.yyyy-mm-dd.log

  • 现象:404 错误

  • 检验:打开 tomcat/logs 目录里的 localhost.yyyy-mm-dd.log 文件,发现大量的报错信息。

  • 分析:当 server.xml,web.xml 配置错误的时候,当前 web 应用就会部署失败,并且会将错误信息输出到 localhost.yyyy-mm-dd.log 文件中。

  • 解决:要在 localhost.yyyy-mm-dd.log 文件中看提示什么错误,有可能是配置的 context 目录不存在,有可能是多了一个 > 符号,具体问题,具体分析了。

5.7 Error FilterStart

  • 现象:404 错误,明明有文件,但是就是不能访问

  • 检验:这个严格地说,也是配置失败,但是 tomcat 不会大量报错,只会偷偷地来这么一句:startup failed due to previous errors。

  • 分析:过滤器启动失败就会报这个错。

  • 解决:同样的,过滤器启动失败原因也是多种多样,好在它都会把具体错误信息输出到 localhost.yyyy-mm-dd.log,这样打开 localhost.yyyy-mm-dd.log 根据实际情况分析,就可以较快定位问题所在了。

5.8 JDK 版本

  • 现象:404 错误,明明有文件,但是就是不能访问

  • 检验:在命令行中运行 java -version 检查一下当前 java 的版本

  • 分析:当部署的 web 应用中的类是由高版本 JDK 编译生成,而当前 Tomcat 运行所使用的 JDK 又是低版本的话,就会报出如图所示的错误:UnsupportedClassVersionError,进而导致 web 应用启动失败。

  • 解决:请使用 JDK8 或者更高版本。

6、404 问题排查

  • 404 表示 File Not Found,文件不存在错误

6.1 正确的端口号

  • 出现 404 错误证明,Tomcat 是启动成功了的。但是在一台计算机上,可以启动多个端口号不一样的 Tomcat, 所以请确保自己访问的是正确的那个端口号,别自己启动的是 8080 端口号的 Tomcat,但是访问的地址却用的是 80 端口(默认),这样肯定会出现 404 错误的。

6.2 环境变量

  • 假设有两个 Tomcat A 和 B,自己分明运行的是 B 下的 startup.bat, 但是启动的却是 A,为什么会这样呢?这就是环境变量在作祟了。

  • 在环境变量中有两个属性:分别是 CATALINA_HOME 和 CATALNIA_BASE,如果这个值指向的是 A,那么即便运行的是 B 下的 startup.bat, 真正启动的还会是 A。

  • 解决办法:删除掉这个环境变量,或者使用移除了环境变量影响的纯净版 Tomcat。

6.3 确定 Web 应用是否成功启动

  • 虽然 Tomcat 启动成功了,但是对应的 Web 应用启动失败,依然会导致 404 错误。

  • 怎么判断 Web 应用成功与失败呢?倘若 Web 引用启动失败,那么就一定会在 Tomcat 的 logs 目录下的 localhost.当前日期.log 里留下错误信息。

  • 打开这个文件,检查对应的 Web 应用是否启动过程中报错了。也许是 web.xml 多写了一个标签结束,也许是对应的 servlet 类找不到。

6.4 webapps 下的 ROOT 目录

  • 有的时候,在 server.xml 中配置的 <context 是以 “/“ 为开始路径的,与此同时,在 webapps 目录下还存在一个 ROOT 目录,这个 ROOT 目录其实也是告诉 Tomcat,以 “/” 为开始路径,那么这样就发生冲突了,Tomcat 只能二选一,通常情况下都会选择 ROOT 目录,那么在 server.xml 中配置的 <context 就无法启动了,导致访问对应的资源提示 404 错误。

  • 解决办法就是删除掉 ROOT 目录,或者把 ROOT 目录重命名。

6.5 访问地址的时候是否加了 web 应用的名称

  • 这个也是常犯的错误,加入部署的时候,指定了路径,比如:<Context path="/j2ee" docBase="e:\\project\\j2ee\\web" debug="0" reloadable="false" />

  • 那么访问的时候,要记得加上 j2ee,像这样:http://127.0.0.1:8080/j2ee/hello

6.6 是否访问对资源了

  • 这种错误也常见,你写的文件是 hello.html, 但是访问的是 holle.html,自然会提示 404 啦。

6.7 不能访问 WEB-INF 目录下的资源

  • 从安全角度出发,Tomcat 不允许访问 WEB-INF 目录下的 HTML,JSP 文件。所以如果你的资源文件放在 WEB-INF 下,也会提示 404 错误。

6.8 访问地址后面多加了一个斜杠

  • 访问地址后面多加了一个斜杠。如本来应该访问 http://127.0.0.1:8080/j2ee/login.html,但是却访问了地址:http://127.0.0.1:8080/j2ee/login.html/

7、Tomcat 调优

7.1 测试 Tomcat 的吞吐量等信息

  • 修改 tomcat-users.xml 配置 Tomcat 管理用户。

  • 修改 webapps/manager/META-INF/context.xml 配置可以访问 Server Status。

  • Apache Jmeter 是开源的压力测试工具,我们借助于此工具进行测试,将测试出 Tomcat 的吞吐量等信息。

7.2 调整 Tomcat 参数进行优化

  • Tomcat 在 server.xml 中配置了两种连接器。

    • 一种监听 8080,负责和其他的 HTTP 服务器建立连接。
    • 一种监听 8009,负责和其他的 HTTP 服务器建立连接。
    • 第二种如要要用可以配置 nginx 实现负载均衡,所以可以直接注释掉。
  • 禁用 AJP 服务,AJP 是定向包协议。

  • 设置执行器 (线程池),频繁地创建线程会造成性能浪费,所以使用线程池来优化,通过修改 server.xml 文件。

  • 设置最大等待队列,默认情况下,请求发送到 Tomcat,如果 Tomcat 正忙,那么该请求会一直等待,可以设置超过就不等待,请求失败,降低服务器负载。

  • 设置 nio2 的运行模式,Tomcat 8 以前默认是 bio,同步并阻塞,性能低下无优化,8 之后是 nio,同步非阻塞,还有个性能更高的 nio2,异步非阻塞,可以更改设置。

文章目录
  1. 1. 前言
  2. 2. 1、Tomcat
  3. 3. 2、配置
  4. 4. 3、项目部署
  5. 5. 4、修改端口
  6. 6. 5、常见问题
    1. 6.1. 5.1 持久化异常
    2. 6.2. 5.2 端口冲突
    3. 6.3. 5.3 JAVA_HOME 环境变量没有设置
    4. 6.4. 5.4 CATALINA_HOME 环境变量设置错误
    5. 6.5. 5.5 CATALINA_HOME 错误设置
    6. 6.6. 5.6 localhost.yyyy-mm-dd.log
    7. 6.7. 5.7 Error FilterStart
    8. 6.8. 5.8 JDK 版本
  7. 7. 6、404 问题排查
    1. 7.1. 6.1 正确的端口号
    2. 7.2. 6.2 环境变量
    3. 7.3. 6.3 确定 Web 应用是否成功启动
    4. 7.4. 6.4 webapps 下的 ROOT 目录
    5. 7.5. 6.5 访问地址的时候是否加了 web 应用的名称
    6. 7.6. 6.6 是否访问对资源了
    7. 7.7. 6.7 不能访问 WEB-INF 目录下的资源
    8. 7.8. 6.8 访问地址后面多加了一个斜杠
  8. 8. 7、Tomcat 调优
    1. 8.1. 7.1 测试 Tomcat 的吞吐量等信息
    2. 8.2. 7.2 调整 Tomcat 参数进行优化
隐藏目录