内容


扩展 Tomcat Web 服务器的功能

把服务器提升到新的高度

Comments

开始之前

本节讨论本教程的内容以及如何从中获得最大的收益。

关于本教程

如果您正在阅读本教程,很可能已经安装了单独的基本 Apache Tomcat Web 服务器。如果还没有,请先阅读前一个教程 “在 UNIX 中安装和配置开发 Web 服务器”。然后再阅读本教程,进一步学习可以用来配置服务器的高级特性和选项,以及实现它们的详细步骤。

但是,如果您只想了解某些对于各种 Web 服务器环境通用的 Web 服务器管理技术,只想了解 Tomcat 产品本身的更多知识,或者打算学习几种管理技巧,那么继续阅读本教程。

目标

在本教程中包含以下内容:

  • 介绍为什么需要为现有的 Web 服务器配置一些高级设置,本教程的目标读者,本教程提供的详细信息的总结,包括开始学习本教程的前提条件。
  • 对比基本 Tomcat Web 服务器与具备更高安全性、健壮性和可扩展性的 Tomcat 服务器之间的差异。
  • 概述如何在 Tomcat 中部署高级应用程序。
  • 安全考虑因素,包括 Java™ Security Manager 和 Secure Sockets Layer(SSL)等特性的设置、安装和配置过程。
  • Tomcat 服务器到数据库和数据源的连接。
  • 高级 Tomcat 管理技巧。
  • 更多参考资料。

前提条件

本教程假设您已经安装了基本的 UNIX® 操作系统。要想运行本教程中的示例,还必须安装和运行 Tomcat 6。

系统需求

服务器应该有至少 10GB 的可用硬盘空间和至少 512MB 的 RAM。需要在 UNIX 服务器上安装以下工具:

需要了解的情况

本节讨论需要了解哪些情况才能为 Tomcat 环境做出适当的配置和定制决策。

基本设置与高级设置

显然,安装并运行 Tomcat 和示例应用程序只是一个开始。这构建了一个基础:现在,必须真正发挥这种简单、免费且高效的服务器软件的威力。除此之外,还必须学习保护服务器、设置数据库以及排除故障的方法。

如果您阅读了 前一个教程,您的服务器应该已经安装好并运行起来了。但是,即使在测试环境中,也有许多限制。必须把测试服务器设置得与生产服务器相同。在原来的设置中,只做了最基本的工作 — 安装和设置服务器软件环境,实现部署 Tomcat 示例应用程序所需的 Tomcat Web Application Manager 控制台。在本教程中,了解更多部署和安全信息以及管理技巧。

生产环境中的 Tomcat

在本教程中,将讨论高级的中间件管理技术,确保最高水平的正常运行时间和稳定性,从而让您的公司具备竞争优势!在生产环境中,在同一台服务器上可能有多个应用程序并可以通过不同的 URL 访问它们(虚拟主机),可能在一个服务器集群中包含多台服务器,可能有许多额外的部署需求,至少需要设置基本的身份验证和 SSL 来保护应用程序。但是,不必担心:本教程会帮助您通过设置服务器提高效率、安全性和可扩展性。

五个核心问题

首先,计划应用程序的需求。如果应用程序是高级的 “Hello World” 应用程序或刚开发的作品,那么必须了解开发级的需求,了解这些需求应该如何转换为服务器级的设置。如果您只是管理员,不关心代码,只需要设置服务器,这也很好。无论您的角色是什么,都需要回答以下问题:

  • 为了适应应用程序对外或对内的依赖性,应该如何设置数据库访问、资源引用等等?
  • 如何实现标准的身份验证和其他安全措施来保护 Tomcat 服务器?
  • 如何成功地部署应用程序?
  • 应该采用哪些管理和故障排除技巧来确保以后的成功?
  • 应该使用哪些技巧和资源来设置运行生产应用程序的服务器?

本教程就围绕这些问题展开。本教程将详细讲解如何实现这些问题的实用解决方案,帮助您把服务器和技能提升到新的高度。

应用程序部署

如果没有应用程序,应用服务器还有什么价值呢?

高级应用程序部署

前一个教程 中,学习了如何使用 Tomcat Web Application Manager 控制台安装简单的示例应用程序。但是,这个应用程序并不代表在日常工作中通常遇到的程序。在本教程中,了解 Tomcat 如何使用应用程序部署描述符,及其与上下文的依赖关系。本文主要关注通过自动部署方法让 Tomcat 替您完成大多数工作,而不需要打开控制台并执行应用程序的手工部署过程。

根据 Servlet 2.2 规范(参见 参考资料),Web 应用程序 由 servlet、Hypertext Markup Language(HTML)页面、类和其他资源组成,它们可以打包在一起并在不同厂商的不同容器中运行。当然,我们要用基于 Java 的服务器技术部署 Java 应用程序:Tomcat 不适用于基于 Microsoft® .NET 的代码和部署。

WAR 文件

必须了解代码的打包方式,才能知道如何部署它。我说的打包 是指存档和压缩 — 把一个目录结构的内容压缩成一个文件。在这里,将使用 Web Archive(WAR)文件,文件扩展名是 .war

图 1 给出 Java 应用程序的基本打包格式。

图 1. Web 模块的内容
Web 模块
Web 模块

目录

Web 模块具有一种固定的特殊结构。组装根/文档根(称为 AppBase)包含 JavaServer Pages™(JSP)页、客户端类和存档以及静态图像。这个目录包含一个子目录 /WEB-INF/,这个子目录包含以下文件和目录:

  • web.xml:这是 Web 应用程序的部署描述符,对于部署非常重要。其中还包含与应用程序相关的安全设置和基于角色的定义。
  • lib:这是库存档文件夹。它包含服务器端类调用的 Java Archive(JAR)库文件。
  • classes:这个目录包含服务器端类 — servlet、JavaBean 组件等等。
  • tags:这个目录包含 Web 模块的标记文件,是标记库的实现。

上下文

理解 Tomcat 中的上下文是实际安装应用程序的重要先决条件。在创建 Web 应用程序目录结构之后,必须添加一个上下文,让 Tomcat 知道应用程序的运行环境。

上下文 定义 servlet 容器用来与 Web 应用程序通信的方法集。Java 2 Platform, Enterprise Edition(J2EE)标准在 /WEB-INF/web.xml 文件中提供一组标准的元素,用来引用必须在应用服务器特有配置中定义的资源。对于 Tomcat 6,InitialContext 的这些 Web 应用程序特有设置在 <Context> 元素中配置,可以在 $CATALINA_HOME/conf/server.xml 或 Web 应用程序特有上下文 Extensible Markup Language(XML)文件(META-INF/context.xml)中指定。最好不要像过去那样在 server.xml 文件中定义这些上下文。而是创建并编辑 context.xml 文件,把它们分开。

上下文描述符 仅仅是一个 XML 文件,其中包含与 Tomcat 相关的上下文配置。InitialContext 配置最初部署的 Web 应用程序,可供 Web 应用程序组件使用(用于只读访问)。

上下文描述符的位置通常是:

  • $CATALINA_HOME/conf/enginename/hostname/context.xml(例如,$CATALINA_HOME/conf/Catalina/localhost/myApp.xml)
  • $CATALINA_HOME/webapps/myApp/META-INF/context.xml

清单 1 提供一个应用程序特有上下文的基本示例。

清单 1. 应用程序特有上下文的示例
<Context docBase="myApp" debug="1" reloadable="true">
<Logger className=""
prefix="localhost_myApp" suffix=".log"
timestamp="false"/>
 <Resource name="jdbc/myApp" auth="Container" 
type="javax.sql.DataSource"/>
 <ResourceParams name="jdbc/myApp">
   <parameter>
       <name>driverClassName</name>
        <value>sun.jdbc.odbc.JDriver</value>
   </parameter>
   <paramete>
       <name>url<name>
        <value>jdbc:odbc:myApp</value>
   </parameter>
 </ResourceParams>
</Contex>

这个清单中的 docBase 和所有数据库驱动程序信息对于应用程序都是惟一的。记住,除非要在 server.xml 文件中编辑上下文(不建议这么做),否则上下文下面的 path="" 变量是不需要的。

这段代码使用 Java Naming and Directory Interface(JNDI)并引用数据源驱动程序和类名,这些在后面的 数据库 一节中详细讨论。关于 <Context> 标记中资源定义的更多选项,参见 参考资料

自动部署

在解释自动部署方法时,常常会提到主机服务器(在默认情况下,是localhost)和 appBase 属性(默认的 appBase 目录是 $CATALINA_HOME/webapps)。

在启动时部署

在启动时部署意味着,通过在 $CATALINA_HOME/appbase 目录中复制内容(WAR 文件格式或已经展开的内容)手工部署静态内容,然后停止并重新启动 Tomcat 服务器。要想利用 Deploy on Startup 特性,只需编辑主机,把 deployOnStartup 属性设置为 True,见 清单 2

清单 2. deployOnStartup.xml
<Engine name="Catalina" defaultHost="localhost" debug="0">
      <!-- This host is the default host. -->
      <Host name="localhost" debug="0" appBase="webapps"
	      unpackWARs="true" autoDeploy="true" deployOnStartup="true">
        <Context path="" docBase="ROOT" debug="0"/>
        </Context>
      </Host>

如果以下条件之一成立,就会在启动时执行部署:

  • 在 $CATALINA_HOME/conf/engine_name/host_name 目录中的 XML 文件中有新的或更新过的上下文描述符。
  • 在 appBase 目录中有新的展开的应用程序。在这种情况下,Tomcat 检查 appBase 目录中同名的相关联 WAR 文件是否比展开的 Web 应用程序新。如果是这样,就删除展开的目录,从 WAR 中重新部署 Web 应用程序(假设主机上下文中设置了 unpackWars=true)。
  • appBase 目录中有任何新的 WAR 文件。

除了能够在启动时部署之外,Tomcat 还可以要求在运行时自动部署新的 XML 配置文件、WAR 文件或拖放到 appBase 目录的子目录(对于使用 XML 配置文件的情况,是 $CATALINA_HOME/conf/engine_name/host_name)。这需要在上下文文件中设置 autoDeploy="true" 来配置这个行为。

在运行时部署

要想在 Tomcat 中启用这个有用的特性,需要把 autoDeploy 标记设置为 True,见 清单 3

清单 3. autoDeploy xml
<Engine name="Catalina" defaultHost="localhost" debug="0">
      <!-- This host is the default host. -->
      <Host name="localhost" debug="0" appBase="webapps"
	      unpackWARs="true" autoDeploy="true" deployOnStartup="true">
        <Context path="" docBase="ROOT" debug="0"/>
        </Context>
      </Host>

自动部署器还会跟踪 Web 应用程序中下面这些方面的变化:

  • 更新 WEB-INF/web.xml 文件,这会触发 Web 应用程序的重新装载。
  • 在 appBase 目录中放置一个比以前展开过的更新的 WAR 文件,这会触发 “卸载”操作(并删除展开的 Web 应用程序),然后执行重新部署。
  • 更新 XML 配置文件,这会触发 “卸载”操作(但是不删除展开的任何目录),然后部署相关联的 Web 应用程序。

在使用自动部署时,XML 上下文文件定义的 docBase 应该在 appBase 目录之外。如果不是这样,在部署 Web 应用程序时可能会遇到困难,或者会部署应用程序两次。

关于在 Tomcat 中部署应用程序的最后提示

如果显式地定义上下文,应该关闭自动应用程序部署特性。否则,上下文会部署两次,这可能会给应用程序造成问题。

另外,在复制和展开 WAR 之前,最好删除 Tomcat 中现有的所有目录。否则,会覆盖一部分代码,留下一些老代码,而不是删除所有老代码。上面的 server.xml 文件设置应该可以缓解这个问题,但是最好不要留下这个漏洞。如果应用程序的表现奇怪,应该考虑如何重新部署它。在每次安装新的应用程序时,还需要重新启动 Tomcat,这虽然麻烦,但这是必要的。

Tomcat Web Application Manager

Tomcat Web Application Manager 是 Tomcat 的一部分,已经在前一个教程中安装了。它提供一些有意思的特性。它允许用户通过安装在上下文路径 /manager(例如,http://localhost:8080/manager)中的一个应用程序部署和管理 Web 应用程序。它允许部署、启动和停止应用程序以及列出操作系统设置,支持以多种方式完成这些任务,比如在本地或远程使用基于 Hypertext Transfer Protocol(HTTP)的 URL 命令、应用程序图形用户界面(GUI)或 Ant 构建脚本中的 Apache Ant 命令。

要想使用自动部署功能,必须在 tomcat-users.xml 文件(Tomcat Web Application Manager 应用程序的默认 XML 文件)中设置 Tomcat Web Application Manager 用户。如果还没有设置这个应用程序,现在就应该设置了。然后,用角色管理器添加一个用户和密码,重新启动 Tomcat。

注意:如果希望研究 GUI 功能,那么访问 Tomcat Web Application Manager URL 或单击左上角导航栏中的 Tomcat Manager 链接。

所有基于 Uniform Resource Identifier(URI)的管理器命令都要在下面这样的请求 URI 中指定:

http://{host}:{port}/manager/{command}?{parameters}

有用的 URL 命令

可以使用 Tomcat Web Application Manager 提供的几个 URL 命令部署和重新部署应用程序:

  • 使用 URI 进行部署:为了使用 URI 部署应用程序,在 Web 浏览器的地址栏中输入以下 URL:
    http://localhost:8080/manager/deploy?path=/sample&
        war=file:$CATALINA_HOME/webapps/docs/appdev/sample/sample.war

    如果部署成功,应该会看到下面这样的消息:

    OK - Deployed application at context path /sample

    还可以通过访问 http://localhost:8080/sample/ 确认部署成功。

  • 重新装载当前的应用程序:为了重新装载当前的应用程序,在 Web 浏览器的地址栏中输入以下 URL:
    http://localhost:8080/manager/reload?path=/sample

    这个 URL 通知一个现有的应用程序关闭本身并重新装载。如果无法重新装载 Web 应用程序上下文,但是已经更新了 /WEB-INF/classes 目录中的类或属性文件,或者在 /WEB-INF/lib 目录中添加或更新了 JAR 文件,那么这个 URL 命令会很有用。但是,只要修改了 web.xml 文件,就需要重新启动应用程序。

    如果这个命令执行成功,应该会看到下面这样的消息:

    OK - Reloaded application at context path /sample
  • 列出操作系统和 Java Virtual Machine(JVM)属性:为了列出操作系统和 JVM 属性,在 Web 浏览器的地址栏中输入以下 URL:
    http://localhost:8080/manager/serverinfo

    如果这个命令执行成功,应该会看到下面这样的消息:

    OK - Server info
    Tomcat Version: Apache Tomcat/6.0.16
    OS Name: SunOS
    OS Version: 5.10
    OS Architecture: x86
    JVM Version: 1.5.0_12-b04
    JVM Vendor: Sun Microsystems Inc.
  • 启动、停止或反部署应用程序:只需在 URL 路径中输入以下值,就可以启动、停止或 “反部署” 应用程序:
    http://localhost:8080/manager/start?path=/sample
    http://localhost:8080/manager/stop?path=/sample
    http://localhost:8080/manager/undeploy?path=/sample
  • 列出当前部署的应用程序:为了列出当前部署的应用程序,在 Web 浏览器的地址栏中输入以下 URL:
    http://localhost:8080/manager/list

    如果这个命令执行成功,应该会看到下面这样的消息:

    OK - Listed applications for virtual host localhost
    /examples:running:0:examples
    /host-manager:running:0:host-manager
    /sample:running:0:sample
    /docs:running:0:docs
    /manager:running:0:manager
    /:running:0:ROOT

还有另外两种出色的部署工具。许多开发人员和管理员使用 Ant,而且因为 Ant 提供可定制的构建脚本和容易执行的命令,他们常常认为 Ant 比 Tomcat Web Application Manager URL 更方便。

其他部署工具

本节简要讨论 Ant 和 Tomcat Client Deployer(TCD)。这两种工具都值得进一步研究,更多信息参见 参考资料

Ant

在使用 Ant 之前,需要执行以下步骤:

  1. 下载并安装 Ant 二进制发行版 1.4 或更高版本。

    安装位置是在 $ANT_HOME 目录下面,这个目录放在您选择的安装位置(例如,在 /opt 或 /export/home 下面)。这个路径最好与安装 Tomcat 服务器的路径相似。

  2. 把 Tomcat 6 中的 server/lib/catalina-ant.jar 文件复制到 $ANT_HOME/lib 中。
  3. 在 PATH 环境变量中添加 $ANT_HOME/bin 目录,这样就不必每次都输入完整的路径名。命令如下所示:
    PATH=$ANT_HOME/bin; export PATH

Ant 与用来构建和编译 Java 应用程序的 make 实用程序相似。但是,Ant 更强大更流行。它可以编译 Java 源代码文件、复制类文件和打包 WAR 文件。

为了让 Ant 能够从命令行部署应用程序,必须有一个可以访问管理器角色的用户名和密码。可以使用与 Tomcat Web Application Manager 用户相同的用户名和密码(参见本教程前面的 Tomcat Web Application Manager),并在 build.xml 文件中以 XML 格式配置用户名和密码,见 清单 4。build.xml 文件是用来定制 Ant 的主要文件。

清单 4. build.xml 文件示例
<project name="My Application" default="compile" basedir=".">

  <!-- Configure the directory into which the Web application is built. -->
  <property name="build"    value="${basedir}/build"/>

  <!-- Configure the context path for this application. -->
  <property name="path"     value="/myapp"/>
 
<!-- Configure properties to access the Manager application. -->
  
  <property name="url"     value="http://localhost:8080/manager"/>
  <property name="username" value="myusername"/>
  <property name="password" value="mypassword"/>

  <!-- Configure the custom Ant tasks for the Manager application ->
  <taskdef name="deploy"    classname="org.apache.catalina.ant.DeployTask"/>
  <taskdef name="list"      classname="org.apache.catalina.ant.ListTask"/>
  <taskdef name="reload"    classname="org.apache.catalina.ant.ReloadTask"/>
  <taskdef name="resources" classname="org.apache.catalina.ant.ResourcesTask"/>
  <taskdef name="roles"     classname="org.apache.catalina.ant.RolesTask"/>
  <taskdef name="start"     classname="org.apache.catalina.ant.StartTask"/>
  <taskdef name="stop"      classname="org.apache.catalina.ant.StopTask"/>
  <taskdef name="undeploy"  classname="org.apache.catalina.ant.UndeployTask"/>

  <!-- Executable Targets -->
  <target name="compile" description="Compile web application">
    <!-- ... construct web application in ${build} subdirectory, and
            generated a ${path}.war ... -->
  </target>

  <target name="deploy" description="Install web application"
          depends="compile">
    <deploy url="${url}" username="${username}" password="${password}"
            path="${path}" war="file:${build}${path}.war"/>
  </target>

  <target name="reload" description="Reload web application"
          depends="compile">
   <reload  url="${url}" username="${username}" password="${password}"
            path="${path}"/>
  </target>

  <target name="undeploy" description="Remove web application">
    <undeploy url="${url}" username="${username}" password="${password}"
            path="${path}"/>
  </target>

</project>

这个清单中的 taskdef 命令是在执行 Ant 时使用的命令。只需输入 ant startant deployant undeploy 等等,就可以运行 Ant 命令。显然,需要在所有 $ 变量中硬编码与 Tomcat Web Application Manager 命令相似的值,但是这为常见的部署和管理任务提供了简便的执行方式。

注意:可以在 ANT_HOME 主路径中创建 build.xml 文件。如果在没有 build.xml 文件的情况下尝试执行 Ant 命令,或者 build.xml 文件位于 Ant 无法看到的位置,就会出现以下错误:

Buildfile: build.xml does not exist!Build failed

用这个 build.xml 文件运行 Ant 时,它会编译 /src 目录中的 Java 文件并把编译的类文件放在 build/src 目录中。

Tomcat Client Deployer

TCD 是一种第三方工具,用来对 Web 应用程序进行检验、编译并压缩为 WAR,然后将其部署到 Tomcat 服务器上。运行这个工具的前提条件是,按本节前面的描述正确地下载并安装 Ant。关于这个工具的更多信息参见 参考资料

数据库连接

数据库是任何动态 Web 应用程序的基本组成部分之一,用来存储、共享或访问各种通过会话、表单等接收到的数据。另外,越来越多的组织使用基本和高级数据仓库根据客户的 Web 特征、购物模式和浏览模式来定制 Web 应用程序。社交站点、社区站点和基于 wiki 的站点实现新的 Web 用户交互方式,因此即使小型的站点也可能需要一个或多个数据库。

面向服务体系架构(Service-Oriented Architecture,SOA)要求信息技术(IT)系统根据业务流程建模(BPM)以及客户和数据统计信息不断地发展。满足这个需求的惟一方法是要找到存储和获取数据的方法。本节讲解如何把 Tomcat 连接到数据库。

数据库

使用数据库的最基本方法是,在服务器上安装数据库软件(例如 Oracle、IBM® DB2® 或 MySQL)。还必须有一个用户和至少一个测试表,然后才能在 Tomcat 中把应用程序连接到这个数据库。

还需要安装一个 Java Database Connectivity(JDBC)驱动程序。这个驱动程序用来管理数据库调用和连接池,把数据库连接管理从您的代码中分离出来,从而提供最好的效率和灵活性。

安装驱动程序

与数据库一样,驱动程序是依赖于软件的。对于 DB2,还需要安装客户机。无论使用哪种驱动程序,必须把 JAR 文件复制到 CATALINA_HOME/lib。我发现,把驱动程序下载文件的扩展名由 .zip 改为 .jar 是有帮助的。除了重命名之外不需要做任何事,因为 .zip 和 .jar 文件是相同的。

JDBC

JDBC 应用程序编程接口(API)是在 Java 编程语言和各种数据库之间建立独立于数据库的连接的行业标准。

JDBC API 支持以下三种操作:

  • 建立数据库连接或访问任何表格式数据源。
  • 发送 Structured Query Language(SQL)语句。
  • 处理结果。

DBCP

Database Connection Pool(DBCP)仍然是标准的 Tomcat 连接池代理程序。commons-dbcp 包依靠 commons-pool 包中的代码提供它使用的底层对象池机制。这些库放在 $CATALINA_HOME/lib/tomcat-dbcp.jar 中。应用程序可以直接使用 commons-dbcp 组件,或者通过容器框架的现有接口使用它。

注意:在比较老的 Tomcat 版本中,必须把数据库驱动程序的 JDBC JAR 放在 $CATALINA_HOME/common/lib 目录中。否则,Tomcat 就无法装载 JDBC 驱动程序。如果由于某种问题 Tomcat 看不到驱动程序,那么把文件复制到 CATALINA_HOME/common/lib 中。

在创建数据库和安装驱动程序时,要执行以下步骤:

  1. 在 Tomcat 中的 server.xml 文件中创建或映射初始上下文。

    这样做会在 server.xml 文件中定义资源,从而确保 Tomcat 和 Web 应用程序可以看到驱动程序。这相当于在 Tomcat 中手工创建数据源来查找、连接和管理这些连接。

  2. 在应用程序的 web.xml 文件中创建资源引用,或者在 web.xml 文件中共享资源引用。
  3. 为了在代码中使用刚才定义的 JNDI 名称,需要使用 javax.naming.Context.lookup() 方法查找数据源并获得数据库连接。

完成这三个简单的步骤之后,就可以测试应用程序了。

创建初始上下文

初始上下文 就是在 server.xml 文件中定义的资源定义,它使用 JNDI 引用定义的资源。在进一步配置之前,需要了解一点儿 JNDI 知识,因为它是一种 J2EE 基本元素,是一种扩展 Java 平台的方式。

JNDI 是一种目录和命名服务,用来通过一种通用的 API 访问不同的目录和命名服务。无论是使用 GUI 还是手工创建资源引用,都需要 表 1 所描述的信息。

表 1. 创建数据源资源定义所需的信息
名称描述
JNDI 名称数据源的 JNDI 名称
数据源 URL数据源的 JDBC 引用 URL
JDBC 驱动程序类JDBC 驱动程序类(更多信息参见 参考资料
用户名数据库模式用户名
密码为数据库用户名设置的密码

创建资源定义/数据源

手工创建资源引用的作用基本上与通过 Tomcat Web Application Manager 控制台 GUI 创建数据源相同。如果您更喜欢使用控制台的话,应该执行以下步骤:

  1. 打开 Tomcat 主页 http://localhost:8080(如果已经对 Tomcat 服务器实施了保护措施,URL 就是 https://localhost:8443)。
  2. 单击页面左上角的 Tomcat Administration 链接。
  3. 输入管理员用户名和密码,然后单击 Login
  4. 单击左面板中 Resources 文件夹下面的 Data Source
  5. 单击 Create a New Data Source
  6. 输入 表 1 中列出的所有信息。
  7. 单击 Save,然后单击 Commit Changes
  8. 查看 server.xml 文件,寻找刚才提供的信息。

注意:可能还需要把全局数据源名称映射到 Web 应用程序中使用的本地名称。这需要在 server.xml 文件中的 <Context> XML 标记中添加下面的资源链接:

<ResourceLink global="jdbc/TestDS" name="ds/TestDS"
	           type="javax.sql.DataSource"/>

在使用 Tomcat Web Application Manager GUI 创建数据源时,会在供所有应用程序使用的全局名称空间中创建它。对于只供一个应用程序专用的数据源,应该在 <Context> 标记下面添加资源。

在 server.xml 文件中手工创建资源定义和资源引用是更好的方法,因为它的效果虽然相同,但是速度更快,允许直接控制服务器配置,您可以获得额外的知识和经验,这是使用控制台所不能提供的。

在 server.xml 文件中,<Context> 标记包含基本资源配置。只需在 vi 编辑器中删除这一行前面的注释标志(例如 <!-- 和对应的 --> 标记),恢复这一行的作用。然后,可以根据下一节中提供的值进一步编辑这个文件。

创建资源定义

清单 5 提供一个在 server.xml 文件中创建资源定义的基本示例。

清单 5. 在 server.xml 文件中创建资源定义
<Context path="/{your Web application's context path}" 
    docBase="{the Web application path where your
 WAR is installed}"
        debug="5" reloadable="true" crossContext="true">

  <Resource name="jdbc/{db name}" auth="Container" type="{database type}"
               maxActive="100" maxIdle="30" maxWait="10000"
               username="{your db user}" password="{your db pwd}" driverClassName=
"{your driver class}"
               url="{your jdbc URL}"/>

</Context>

ie. 
<Context path="/DBTest" docBase="DBTest"
        debug="5" reloadable="true" crossContext="true">

  <Resource name="jdbc/TestDB" auth="Container" type="javax.sql.DataSource"
               maxActive="100" maxIdle="30" maxWait="10000"
               username="dbuser" password="test1234" \
			   driverClassName="com.mysql.jdbc.Driver"
               url="jdbc:mysql://localhost/javatest?autoReconnect=true"/>
</Context>

可以在 <DefaultContext> 标记中定义可供所有 Web 应用程序使用的资源。还可以在 <Context> 元素中定义只供一个特定应用程序使用的资源。

创建资源引用

在命令行上输入 vi APP_HOME/WEB-INF/web.xml 创建一个新的 web.xml 文件。然后,输入 i 插入 清单 6 中的代码,这会创建一个名为 TestDB 的测试数据源。

清单 6. 为这个测试应用程序创建 WEB-INF/web.xml 文件
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
        http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
    version="2.4">
  <description>Test SQL for test App</description>
  <resource-ref>
      <description>DB Connection</description>
      <res-ref-name>jdbc/TestDB</res-ref-name>
      <res-type>javax.sql.DataSource</res-type>
      <res-auth>Container</res-auth>
  </resource-ref>
</web-app>

然后,输入 :wq! 保存文件并退出 vi。也可以不从头创建新的 web.xml 文件,而是更新现有的 web.xml 文件。差异并不大,见 清单 7。这两种方法是相似的,都是引用前面讨论的数据库资源。

在命令行上,在 vi 编辑器中打开现有的 web.xml 文件。然后,输入 i,在 <web-app> 标记之间插入清单 7 中的代码。

清单 7. 在现有的 web.xml 文件中定义资源引用
<description>DB Connection</description>
  <resource-ref>
      <description>DB Connection</description>
      <res-ref-name>jdbc/TestDB</res-ref-name>
      <res-type>javax.sql.DataSource</res-type>
      <res-auth>Container</res-auth>
  </resource-ref>
</web-app>

输入 :wq! 保存文件并退出 vi。

清单 6 和清单 7 中的代码之间的惟一差异是,<web-app> 标记包含模式 URL 的引用。

用 JNDI 引用修改代码

一定要注意,如果把硬编码的数据库访问引用分离出来,放在不影响代码其他部分的对象中,就会简化部署和版本管理。这是一种重要的最佳实践。这有助于业务逻辑与表示层的分离。

本教程并不讨论如何创建定制的资源工厂、使用数据访问对象或使用非 DBCP 连接。但是,在 参考资料 中提供了更多信息的链接。

安全性

如果要提供真正的 Web 应用程序,那么保护 Tomcat 服务器是非常重要的。即使只作为测试服务器运行 Tomcat 服务器,也一定要理解和实现下面的概念。

服务器安全性

我们从两个不同的角度讨论安全性:服务器安全性和应用程序安全性。服务器安全性 包括 Java Security Manager、在安全的端口上启动 Tomcat 以及为服务器设置 SSL 证书。应用程序安全性 主要涉及根据用户的安全角色和他们试图访问的资产进行身份验证和授权。

如果单独使用 Tomcat 服务器,那么强烈建议在服务器上设置 SSL。如果有前端 HTTP 服务器,那么这个服务器很可能会处理所有 SSL over HTTP(HTTPS)连接,它要求使用 SSL 并把这些请求路由到适当的 Tomcat 服务器。在其他情况下,Tomcat 服务器可能需要打开 SSL;即使它们都在同一个网络上同一个防火墙后面相互进行可信连接,也需要这么做。

使用 keytool 设置 SSL

从本质上说,SSL 连接是让两个服务器可以进行可信的通信。让它们相互信任的方法是使用自签名或由第三方检验的安全密钥。

自签名证书对于加密是合适的,但是对于真正的在线可信身份验证是无法接受的。如果访问一个只有自签名证书的站点,就会在浏览器中看到许多警告消息。

下面讨论存储、请求和导入签名的服务器证书的过程。了解这些信息是实现任何 Tomcat 安全措施(比如在安全的端口上启动服务器)的前提条件。

幸运的是,Java 提供了一个相当简单的命令行工具 keytool,可以使用这个工具轻松地创建自签名证书。自签名证书仅仅是用户生成的证书,这些证书没有向任何证书机构(CA)正式注册,因此实际上根本无法保证它们是可信的。但是,通过使用 keytool,可以生成证书请求,然后把它发送给第三方以请求可信检验,第三方发送回 “signed”;然后,就可以使用 keytool 导入这个签名的服务器证书。这样的话,当客户机或其他服务器访问您的服务器或应用程序时,它们就知道您的服务器的身份是真实的。

创建密钥存储

在获取安全证书之前,必须有一个放置证书的地方。这个地方称为密钥存储。同时,还可以使用 清单 8清单 9 所示的命令(取决于 Java 版本)创建自签名证书。

清单 8. 在 Java 1.6 或更高版本上创建密钥存储和自签名证书
keytool -genkeypair -alias tomcat -keyalg RSA -keystore /
$CATALINA_HOME/ssl/keystore
清单 9. 在 Java 1.6 之前的版本上创建密钥存储和自签名证书
<!-- For Java versions earlier than 1.6, you must run two separate commands. -->
keytool -genkey -alias tomcat -keyalg RSA -keystore /
$CATALINA_HOME/ssl/keystore

<!-- and -->
keytool -selfcert -alias tomcat -keystore /
$CATALINA_HOME/ssl/keystore

在创建密钥时,可以在命令行上指定密钥大小、有效性、电子邮件地址等等,也可以在出现提示时输入各个值。指定密码值 changeit,这是大多数文档推荐的默认密码。如果愿意,可以把密码设置为其他值。

注意:$CATALINA_HOME/ssl 是我创建的一个目录,建议创建这个目录来保存密钥存储和服务器证书。但是,您可以在这里使用任何目录路径,只要在以后引用它时保持一致即可。

编辑密钥存储

如果需要,以后可以编辑密钥存储。在提示您输入 <tomcat> 或别名的密钥密码时,按回车,这会设置与密钥存储密码相同的密码。此后,将使用别名来引用密钥存储。

清单 10 给出编辑密钥存储的代码。

清单 10. 编辑密钥存储
keytool -genkey -alias tomcat -keyalg RSA  -keystore /
$CATALINA_HOME/ssl/keystore

根据需要修改公司、位置、默认密码等信息。

从可信的机构获得证书

要想从 CA 获得证书,首先必须创建一个 Certificate Signing Request(CSR)。这个词与其他软件平台上使用的 Server Cert Request 意义相同。清单 11 给出创建 CSR 的代码。

清单 11. 创建 CSR
$keytool -certreq -keyalg RSA -alias tomcat -file certreq.csr /
    -keystore $CATALINA_HOME/ssl/keystore

现在会生成一个名为 certreq.csr 的文件,可以把它提交给 CA。当请求返回时,会得到一个证书。第三方数字 CA 的列表参见 参考资料

为了完成证书过程,还需要执行以下步骤:

  1. 访问第三方厂商的网站,获得 Root 证书或证书链。

    注意,一些安全服务器需要中间证书和 Root 证书。必须从第三方厂商获取这两种证书,它们形成一个证书链。也可以分别导入这些证书。

  2. 输入以下命令导入证书链:
    keytool -import -alias root -keystore $CATALINA_HOME/ssl/keystore 
        -trustcacerts -file

    其中的 file 是证书链的名称。

  3. 输入以下命令导入签名的服务器证书:
    keytool -import -alias tomcat -keystore $CATALINA_HOME/ssl/keystore -file

    其中的 file 是签名的证书的文件名。

现在有了让 Tomcat 作为可信服务器运行所需的 SSL 密钥。但是,还必须通过配置 Tomcat 来使用 SSL。Tomcat 通过连接器完成这个任务,下一小节 “在安全端口上启动 Tomcat” 将定义连接器的概念。

在安全端口上启动 Tomcat

在默认情况下,server.xml 文件包含 SSL 连接器信息,需要取消这些信息的注释标志。首先,要确保在 server.xml 文件中 SSLEngine 属性被设置为 On,例如:

<Listener className="org.apache.catalina.core.AprLifecycleListener" 
    SSLEngine="on" />

清单 12 给出 Tomcat 6 的 server.xml 文件中 Connector 元素的默认设置。

清单 12. Connector 元素的默认设置
<Connector 
           port="8443" minSpareThreads="5" maxSpareThreads="75"
           enableLookups="true" disableUploadTimeout="true" 
           acceptCount="100"  maxThreads="200"
           scheme="https" secure="true" SSLEnabled="true"
           keystoreFile="$CATALINA_HOME/ssl/keystore" keystorePass="changeit"
           clientAuth="false" sslProtocol="TLS"/>
...

取消 <Connector> 标记的注释标志,然后根据自己的密钥存储设置 keystoreFilekeystorePass 属性。这个示例中使用的 port 属性默认值是 8443。Tomcat 将监听这个 TCP/IP 端口上的安全连接。可以把这个值改为您需要的任何端口号。但是,最好坚持使用典型的 SSL 端口,比如 443。

注意,如果在这里修改了端口号,那么还应该修改非 SSL 连接器的 redirectPort 属性值。这样的话,当用户试图访问需要 SSL 的安全页面或资源时,Tomcat 就可以自动地进行重定向。

为了访问受保护的 Tomcat 服务器默认页面,在 Web 浏览器的地址栏中输入地址 https://localhost:8443。应该会看到与 图 2 相似的页面。

图 2. Security 控制台欢迎页面
Security 控制台欢迎页面
Security 控制台欢迎页面

需要记住的最后一点是,在运行安全的虚拟主机时,需要在每个服务器的密钥存储的 SSL 连接器中添加一个 SSL Factory 元素。

Security Manager

Tomcat 内置的 Java Security Manager 是另一种安全机制,它可以避免 Tomcat 服务器接收可能会有意或无意地损害服务器的代码包。JRE 的作用包括防止某些代码段参与 JVM 的管理,在服务器文件系统上设置某些权限,等等。在许多情况下,可以从 Web 访问的服务器应该添加这个额外的安全层,以便防止黑客控制服务器或查看服务器上的文件。但是注意,如果您的代码由于某种原因需要在服务器文件系统中写文件,这种安全机制可能会造成妨碍,所以在生产环境中实现它之前,要仔细考虑并充分测试应用程序的功能。

Security Manager 实现的安全策略是在 $CATALINA_HOME/conf/catalina.policy 文件中配置的,并为 Web 应用程序的不同部分设置适当的权限。查看这个文件,判断哪些地方需要修改。

要想在启用 Security Manager 策略的情况下启动服务器,应该输入以下命令:

$CATALINA_HOME/bin/catalina.sh start -security

身份验证和安全角色

用 SSL 密钥保护服务器,确保它是可信的,这当然很好。但是,应用程序(至少是应用程序的某些部分)现在需要提示用户在访问受保护资源时必须进行安全的身份验证。Tomcat 提供四种常用的身份验证机制,还允许定制的安全身份验证。下面讨论如何设置 Basic 身份验证,然后讨论如何把它扩展为 Form-based、Custom 和 Digest 身份验证。

如果配置了 Basic 身份验证,当用户试图访问受保护资源时,会向用户显示一个登录对话框。如果使用 Form-based 身份验证,当用户试图访问受保护资源时,用户会被重定向到一个 HTML 页面,他们可以在这个页面上登录。如果在允许用户登录之前需要用户提供更多的信息,就应该使用 Custom 身份验证。如果需要通过散列的密码提高安全水平,就应该使用 Digest 身份验证。

Basic 身份验证

首先,定义 apps-appname.xml 文件,这个文件指定将使用 Basic 身份验证的应用程序,以及它为这个应用程序的安全角色引用的用户文件。清单 13 给出这个 XML 文件的内容。

清单 13. conf/apps-appname.xml 文件的内容
<?xml version="1.0" encoding="ISO-8859-1"?>
<webapps>
    <Context path="/sample" docBase="webapps/sample" reloadable="true"> 
            <SimpleRealm filename="conf/users/appname-users.xml" />
    </Context>
</webapps>

接下来,必须在 appname-users.xml 文件中创建应用程序特有的安全角色。输入您选择的用户名和密码,确保给这些用户授予适当的身份验证角色。关于可用角色的更多信息,请参考 Tomcat 文档(参见 参考资料)。

清单 14 给出一个 appname-users.xml 文件示例。

清单 14. conf/users/appname-users.xml 示例
<tomcat-users>
  <user name="username" password="passwd" roles="rolename" />
</tomcat-users>

最后,在 WEB-INF/web.xml 文件中输入 清单 15 所示的详细信息。这些详细信息指定不同的受保护资源以及相关的 HTTP 方法。如果需要保护 JSP 或 HTML 文件之外的其他资源,可以在这里添加它们。另外,这里定义了 Basic 身份验证以及系统上任何用户的默认角色。

清单 15. webapps/appname/WEB-INF/web.xml 文件示例
  <security-constraint>
    <web-resource-collection>
      <web-resource-name>user-resource</web-resource-name>
      <description>pages which require login</description>
      <url-pattern>*.jsp</url-pattern>
      <url-pattern>*.html</url-pattern>
      <http-method>GET</http-method>
      <http-method>POST</http-method>
    </web-resource-collection>
    <auth-constraint>
      <description>Must authenticate before querying the system</description>
      <role-name>rolename</role-name>
    </auth-constraint>
    <user-data-constraint>
      <transport-guarantee>NONE</transport-guarantee>
    </user-data-constraint>
  </security-constraint>

  <login-config>
    <auth-method>BASIC</auth-method>
   <realm-name>default</realm-name>
  </login-config>

  <security-role>
    <description>Any user of the system</description>
    <role-name>rolename</role-name>
  </security-role>

注意,必须确保 <role-name> 标记与创建用户时指定的角色匹配。

Form-based 身份验证

Form-based 身份验证可能是受保护网页最常用的用户身份验证方法。这种方法已经出现很长时间了。它提供 Basic 身份验证的基本特性,同时允许开发人员创建与站点外观匹配的定制登录和错误页面。

在 HTTPS 和 HTTP 之间来回切换时,Form-based 身份验证比 Basic 身份验证更好,这是因为用户名和密码并不随每个请求发送。请记住,在使用 Form-based 或这里提到的其他身份验证机制时,仍然强烈建议使用 HTTPS 等安全传输机制。

为了在已经设置的 Basic 身份验证基础上构建 Form-based 身份验证,需要执行以下步骤:

  1. 创建一个定制的错误文件和 login.jsp 文件(本教程不讨论这些文件)。
  2. 把 Basic 身份验证代码的 login-config 部分替换为 清单 16 中的代码。
    清单 16. 修改 Basic 身份验证代码
    <login-config>
       <auth-method>FORM</auth-method>
      <realm-name>Web Demo</realm-name>
       <form-login-config>
          <form-login-page>/admin/login.jsp</form-login-page>
          <form-error-page>/admin/error.jsp</form-error-page>
       </form-login-config>
    </login-config>

    安全约束信息保持不变。

    注意:在创建 HTML 表单时,需要采用以下语法:

    <form method="POST" action="j_security_check">
       <input type="text" name="j_username">
       <input type="text" name="j_password">
       <input type="submit" value="Log in">
    </form>
  3. 重新启动 Tomcat,让这些修改生效。

Custom 身份验证

Form-based 和 Custom 身份验证概念超出了本教程的范围,需要额外的开发工作。Custom 身份验证可以保护资源(例如 JSP 文件),然后在 Web-INF 目录中引用这个资源。参见 清单 17

清单 17. 在 WEB-INF/web.xml 文件中引用资源
 <web-app> 
   <security-constraint>  
    <!-- web resources that are protected --> 
  <web-resource-collection> 
      <web-resource-name>A Protected Page</web-resource-name> 
     <url-pattern>/protected-page.jsp</url-pattern> 
    </web-resource-collection> 

    <auth-constraint> 
      <role-name>resin-user</role-name> 
    </auth-constraint> 
   </security-constraint>

   <login-config> 
    <auth-method>BASIC</auth-method> 
    <realm-name>Basic Authentication Example</realm-name> 
 		<!-- The authenticator tag is Resin-specific --> 
 		<authenticator id='beans.SimpleAuthenticator'/> 
   </login-config>
 </web-app>

Digest 身份验证

从本质上说,Digest 身份验证与 Basic 身份验证相同,惟一的差异是 Digest 身份验证传输密码的散列(Hash)值,而不是密码本身。清单 18 给出需要对 Basic 身份验证的 web.xml 文件所做的修改。

清单 18. 实现 Digest 身份验证所需的修改
    <auth-method>DIGEST</auth-method>  
    <realm-name>Digest Authentication Example</realm-name> 
   </login-config>  
</web-app>

如清单 18 所示,Basic 和 Digest 身份验证配置之间的惟一差异是指定的身份验证方法不同。既然如此,为什么人们更喜欢 Basic 而不是 Digest 身份验证呢?这是没道理的。Digest 是更安全的替代机制。

可扩展性

对于真正需要生产型体系结构和高可用性的系统,可扩展性是一个极其重要的概念。它支持在 Web 服务器环境中运行更多的网站或 Web 应用程序,并提供更好的可用性。当然,获得这些好处也是要付出代价的。应该由企业的管理层和 IT 架构师决定企业究竟需要什么样的体系结构解决方案。但是,如果您有额外的硬件和大量时间,我当然鼓励您在自己的服务器上尝试实现下面的概念。

虚拟主机

虚拟主机 是指允许在一个或多个物理服务器节点上配置的单一服务器实例同时驻留多个应用程序。这种做法在 Web 上非常常见,这主要是因为大多数个人和小公司无力承担专用服务器的开销。通过使用共享的空间和进程以及出色的虚拟服务器软件,Web 管理员可以非常轻松地设置虚拟主机。

虚拟主机有显著的局限性,比如一个应用程序或网站会受到其他应用程序的资源使用量的影响。如果一个应用程序导致整个服务器停机(这种情况实际上很常见),会发生什么情况?所有其他应用程序都会受到影响。消除(或者缓解)这种依赖性的惟一方法是尽可能消除服务器环境中的单一故障点。这正是集群技术的目的。

要想在 Tomcat 中设置虚拟主机,只需设置 Domain Name System(DNS)或保存主机的数据。(对于测试,为本地主机设置一个 IP 别名就够了)。

然后,必须在 server.xml 配置文件中添加 清单 19 中的代码。

清单 19. 为主机设置 DNS
    <Engine name="Catalina" defaultHost="localhost" debug="0">
      <!-- This host is the default host. -->
      <Host name="localhost" debug="0" appBase="webapps"
	      unpackWARs="true" autoDeploy="true">
        <Context path="" docBase="ROOT" debug="0"/>
        </Context>
      </Host>

     <!-- This host is the first virtual host: www.example.com. -->
      <Host name="www.example.com" appBase="/home/example/webapp">
        <Context path="" docBase="."/>
      </Host>

    </Engine>

Tomcat 附带的 server.xml 文件只包含一个虚拟主机,但是很容易添加对更多虚拟主机的支持。清单 19 中的 server.xml 文件简化版展示添加一个虚拟主机所需的总体结构。每个 Host 元素必须包含一个或多个 Context 元素;这些元素之一必须是这个主机的默认上下文,把相对路径设置为空字符串(例如 path="")即表示默认上下文。

注意:如果把 Tomcat 配置为支持多个虚拟主机(网站),就需要为每个虚拟主机配置一个管理器。

默认的 Tomcat 安装包含管理器。为了给新主机添加管理器 Web 应用程序上下文的实例,需要在 $CATALINA_HOME/conf/enginename/hostname 文件夹中安装 manager.xml 上下文配置文件,参见 清单 20

清单 20. 管理器上下文路径示例
<Context path="/manager" debug="0" privileged="true"
         docBase="/opt/tomcat/localhost/webapps/manager">
</Context>

集群

集群 是另一个对于 Web 服务器环境很重要的可扩展性概念。虚拟主机允许在一个服务器实例中驻留多个应用程序,而集群的作用与虚拟主机正好相反,它允许跨不同的物理服务器运行多个服务器实例,同时提供健壮的会话和负载管理。在任何真实的生产环境中,这都是必需的。集群有三方面的好处:

  • 在软件层或硬件层消除环境中的单一故障点。安装在一个物理节点上的两个服务器可以提供垂直伸缩,从而实现软件层上的故障转移。但是,如果发生硬件故障,这种措施就不够了。水平伸缩 提供物理和逻辑故障转移,这是真正的集群产生的效果。
  • 集群可能有助于提高性能。当然,如果应用程序独自占用自己的专用服务器的所有资源,那么集群对性能可能没有帮助。但是,大多数应用程序会与其他应用程序共享服务器。在集群中添加更多服务器和更多资源(内存、CPU 等等),就可以提高性能。
  • 集群对于用户是透明的。即使一个服务器在用户事务的中间停止运行了,持久化会话数据库会保存会话数据并马上把数据传输给另一个服务器,从而保证会话的持久性。

因为集群是一个非常大的主题,本教程不打算讨论它的实现。如果确实需要在 Tomcat 服务器上运行许多应用程序,参见 参考资料

其他管理技巧

本节概述一些管理任务,它们可能有助于服务器导航、停止和启动进程、排除故障等。可以在保护服务器或设置数据库的步骤之前、之后或期间应用这些技巧。

授予对 Tomcat Web Server Administration 工具的访问权

可以使用 Tomcat Web Server Administration 工具执行查看服务器信息、编辑连接、修改资源等操作。它还提供一个方便的界面,可以用来管理、创建和修改 Tomcat 管理用户的用户名和密码以及添加新角色和新用户。

这个工具在 $CATALINA_HOME/webapps/admin.xml 中定义。在设置 Tomcat Web Server Administration 工具角色和用户的 tomcat-users.xml 文件中,必须定义初始登录管理用户。首先,在两个 <tomcat-users> 标记之间添加以下两行代码:

cd $CATALINA_HOME/conf
vi tomcat-users.xml

然后,把 清单 21 中的代码添加到 tomcat-users.xml 文件中。这些代码通过添加用户和角色来授予对 Tomcat Web Server Administration 的访问权。

清单 21. 授予对 Tomcat Web Server Administration 工具的访问权
<tomcat-users>
<role rolename="admin"/>
<user username="admin" password="s3cur3" roles="admin"/></user>
</tomcat-users>

必须重新启动 Tomcat,然后才能使用 http://localhost:8080/admin URL 访问 Tomcat Web Application Administration 工具。使用 清单 22 中的代码重新启动服务器。

清单 22. 重新启动 Tomcat 服务器
cd $CATALINA_HOME/bin
./shutdown.sh 
./startup.sh ;tail -f ../logs/catalina.out

在 catalina.out 日志文件中,应该会看到下面这样的日志记录:

May 15, 2008 4:08:12 PM org.apache.jk.server.JkMain start
INFO: Jk running ID=0 time=0/74  config=null
May 15, 2008 4:08:12 PM org.apache.catalina.startup.Catalina start
INFO: Server startup in 6271 ms

在 Web 浏览器的地址栏中输入 URL http://localhost:8080/admin。如果修改成功,会看到 图 3 所示的页面。

图 3. Tomcat Web Server Administration 工具的登录页面
Tomcat Web Server Administration 工具的登录页面
Tomcat Web Server Administration 工具的登录页面

用非根用户 ID 运行服务器

如果您的系统是真正的多用户系统,有许多用户登录 Web 服务器,那么应该考虑用一个对目录和进程具有特定访问权的 Tomcat 用户来运行 Tomcat 服务器。另外,如果服务器上有多种软件安装,比如数据库安装或者 Web 服务器或应用服务器的简化版或替代版,那么需要找到一种区分它们的方法。管理它们的最好方法是为每个安装使用特定的 ID。在生产环境中这肯定是一种好做法;如果相互独立的管理团队和部署团队都管理同一服务器,通常会采用这种方法。管理员通常具有更大的控制权,他们只把一部分访问权授予部署团队。

首先,必须创建用户 ID 和组。如果读过前面的 Tomcat 教程,您应该已经完成这一步了。只需运行以下命令:

  • 使用以下代码创建一个用来运行 Tomcat 的组:
    /usr/sbin/groupadd -g {specific gid. Leave this blank, and the operating system will
        assign you a gid}
    {group name}
    ie.
    /usr/sbin/groupadd -g 10004 tomcatgroup
  • 使用以下代码创建一个用来运行 Tomcat 的惟一用户:
    /usr/sbin/useradd -d {user home directory} -g {user 
    primary group} -u 
    {specific UID. You can leave this blank, and the operating system will 
    assign you a UID.) 
    -s {default shell path for this user} -c "{Description of 
    the user}" {username}
    ie. 
    /usr/sbin/useradd -d /export/home/tomcat -g tomcatgroup -u 
    10010 -s /bin/ksh -c 
    "Main Tomcat Administrative User" tomcat

输入以下命令,把所有 $CATALINA_HOME 目录的所有权改为 Tomcat 用户和 Tomcat 组:

Chown -R tomcat:tomcat $CATALINA_HOME

注意:-R 选项指定以递归方式修改所有东西的所有权。

接下来,使用 jsvc 守护进程启动 Tomcat,但是要指定 -user 选项。可以直接编辑 $CATALINA_HOME/bin/jsvc/native/tomcat.sh 脚本并把以下参数改为自己的 ID:

TOMCAT_USER=tomcat

注意:可以在脚本的注释部分下面找到这个变量和其他变量,比如 $JAVA_HOME 和 $CATALINA_HOME。使用 vi 或您选择的编辑器修改这个变量。

通过手工运行 jsvc 服务并指定 -user 选项,也可以完成这一修改:

Cd $DAEMON_HOME (where this is the location of your jsvc-src dir)
Bash#./jsvc -user tomcat -cp ./bin/bootstrap.jar \
-outfile ./logs/catalina.out -errfile ./logs/catalina.err \
        org.apache.catalina.startup.Bootstrap

这里假设已经指定了 JAVA_HOME 和 CATALINA_HOME。如果还没有,可以在手工启动时添加这些目录:

Bash#./jsvc -user tomcat -home /usr/jdk/instances/jdk1.5.0 \
-Dcatalina.home=/opt/apache-tomcat-6.0.16 \
-cp ./bin/bootstrap.jar -outfile ./logs/catalina.out \
-errfile ./logs/catalina.err \
        org.apache.catalina.startup.Bootstrap

从技术上说,这两种方法都作为根用户启动,然后把运行这个进程的用户改为指定的用户。

判断 Tomcat 是否正在运行

Tomcat 没有状态。因此,要想判断 Tomcat 是否正在运行,必须输入:

ps -ef |grep java |grep server

如果作为根用户用默认的 startup.sh 脚本启动了 Tomcat,应该会看到与 清单 23 相似的输出。

清单 23. 作为根用户启动 Tomcat 的输出
bash-3.00# ps -ef | grep java|grep server
noaccess   720     1   0 16:35:05 ?           5:06 /usr/java/bin/java -server 
-Xmx128m -XX:+BackgroundCompilation -XX:PermSize=32m

如果使用 jsvc 守护进程手工启动服务器,或者通过 $CATALINA_HOME/bin/jsvc/native/tomcat.sh 下面的 tomcat.sh 脚本在服务器启动时启动 Tomcat,那么可以通过检查 Tomcat .pid 文件是否存在来判断服务器是否正在运行:

ls -l var/run/tomcat.pid

或者查看 pid 文件或对它使用 Cat

cat /var/run/tomcat.pid

检查 .pid 文件,然后对 pid 进程使用 grep 来检查它是否正在运行:

ps -ef | grep {pid}

修改 JVM 设置

这里说的 JVM 设置是指 JVM 可用内存。需要修改这个值的主要场景包括需要运行一个大型应用程序,打算在生产环境中使用 Tomcat 服务器,或者打算以不同的 JVM 内存量对应用程序运行受控的负载测试,以此了解在什么地方会发生内存堆耗尽。在运行受控的测试时,常常会把最小和最大堆大小设置为相同的值,直到到达顶峰负载并获得所需的数据。然后,可以把设置恢复为正常值。

Tomcat 的默认设置是最大值 128MB。在使用状态检查命令时,会看到 server -Xmx128m。如果运行多个 JVM,那么一定不要把最大 JVM 堆大小的总和设置得比服务器上的可用内存大。

在这种情况下,可以编辑 tomcat.sh 脚本,或者手工运行 jsvc 守护进程并在启动行中包含以下选项:

server -Xms128m -Xmx512m

使用 清单 24 所示的命令配置 JVM 设置。

清单 24. 配置 JVM 设置
#./jsvc -user tomcat -home /usr/jdk/instances/jdk1.5.0 \
-Dcatalina.home=/opt/apache-tomcat-6.0.16 \
-cp ./bin/bootstrap.jar -outfile ./logs/catalina.out \
-errfile ./logs/catalina.err \
-server -Xms128m -Xmx512m \
        org.apache.catalina.startup.Bootstrap

典型的高级应用服务器最佳实践指出,最好把最小 JVM 堆大小设置为最大值的四分之一。要尽可能避免随意修改内存设置,尤其是在修复可能与 JVM 内存无关的问题时。提高最大堆大小有利也有弊,一定要权衡考虑。

如果正确地调整 JVM,99% 的垃圾收集(GC)只需要不到一秒时间。其余的 GC 也只需要几秒。GC 进程花费的时间应该很少超过 10 秒。

结束语

教程结束语

本教程结束了。您可能并不需要同时实现本教程中讨论的所有技术,但是已经掌握了配置健壮的 Web 服务器或应用服务器所需的知识。

现在,您应该能够顺利地部署新的应用程序,在测试或生产环境中设置稳定且安全的 Web 服务器。祝您好运!


相关主题


评论

添加或订阅评论,请先登录注册

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=AIX and UNIX, Open source, Java technology
ArticleID=354991
ArticleTitle=扩展 Tomcat Web 服务器的功能
publish-date=11272008