Tomcat是java的一个不完整实现,但是已经广泛应用于生产环境,java 2 ee中的一个特殊类叫servlet可以让java虚拟机运行在服务端。jsp也是java 2 ee的一个特殊类,可以让java代码嵌入到html文档中,最终转换为java代码,然后才能够在JVM虚拟机中运行。tomcat运行需要JDK的支持,JDK是java的开发工具包,包括Java核心和JVM虚拟机等运行环境。

安装

下载tomcat和JDK:

        下载地址:http://tomcat.apache.org 下载Core版本的tar.gz即可。http://mirrors.tuna.tsinghua.edu.cn/apache/tomcat/tomcat-8/v8.5.27/bin/apache-tomcat-8.5.27.tar.gz

        tomcat需要和JDK才能工作,所以要下载JDK。

        到官网下载:http://www.oracle.com/technetwork/java/javase/downloads/index.html

        找到JDK进入下载页面,这里选择Linux的rpm版本,下载前要先接受协议才可下载:

http://download.oracle.com/otn-pub/java/jdk/9.0.4+11/c2514751926b4512b076cc82f959763f/jdk-9.0.4_linux-x64_bin.rpm

安装JDK:

        安装JDK:rpm -Uvh jdk-9.0.4_linux-x64_bin.rpm 使用命令rpm -ql jdk-9.0.4 可以看到,jdk被安装到了/usr/java/目录下了。由于会经常用到java命令,但是命令使用的路径很长,所以在/etc/profile.d/java.sh中将PATH路径包含Java的路径即可, PATH=/usr/java/latest/bin:$PATH。这样就可以直接运行java命令了,在命令行下输入java即可看到java命令的帮助信息。使用java --version命令可以查看Java的版本信息,看到版本信息说明java已近安装成功了。

        注意:PATH目录不要定义错了,如果位置写错了的话会出现 no such directory的提示,因为这个目录/usr/java/latest/bin是tomcat所要引用的目录。写错了可能导致无法启动。

安装tomcat:

        首先将下载的tar包解压到/usr/local中,使用命令tar xf apache-tomcat-8.5.27.tar.gz -C /usr/local,解压后为文件夹创建一个软连接 ln -sv apache-tomcat-8.5.27/ tomcat,同样的由于经常使用到/usr/local/tomcat/bin中的命令,所以在/etc/profile.d/中创建tomcat.sh文件,创建完成后重读 .  tomcat.sh文件,这样tomcat就安装好了。使用catalina.sh --help命令查看帮助信息。使用catalina.sh start命令可以启动tomcat。启动后使用ss -tnlp命令查看是否有8080端口的java进程。

        然后打开浏览器访问:192.168.96.132:8080 查看是否可以访问页面。注意关闭selinux和防火墙规则。


配置和使用

Tomcat的目录结构:

        bin       脚本及启动时用到的类

        lib        类库

        conf     配置文件

        logs     日志文件

        webapps 应用程序默认部署目录

        work    工作目录

        temp   临时文件目录

配置文件:

        主配置文件位置:/usr/local/tomcat/conf/server.xml

        context.xml:各个webapp提供的默认配置,默认继承此文件。

        web.xml:每个webapp部署之后才能被访问,此文件提供部署相关配置,默认继承此文件。

        tomcat-users.xml:用户访问认证的账号和密码配置文件。

        catalina.policy:当使用-security选项启动tomcat实例时会读取此配置文件来实现其安全运行策略。

        catalina.properties:Java属性定义文件,用于设定类加载器路径等,以及一些JVM性能相关调优参数

        logging.properties:日志相关的配置信息。

配置文件格式:

        service的作用是将connector和engine关联起来,一个service内部只能有一个engine但是可以有多个connector,一个engine可以有多个host,用来提供虚拟主机,一个host可以有多个context,用来部署多个webapp程序,一个server对应一个tomcat实例。

        <server>

                <service>

                        <connector />

                        <connector />

                        <engine>

                                <host>

                                        <context />

                                </host>

                        </engine>

                </service>

        </server>

创建测试应用:

        首先在/usr/local/tomcat/webapps/中创建目录 mkdir myapp/{lib,classes,WEB-INF,META-INF} -pv,然后创建myapp/index.jsp文件,在index.jsp文件中写上如下代码:

<%@ page language="java" %>

<%@ page import="java.util.*" %>

<html>

        <h1>This is test page</h1>

        <% out.println("hello world"); %>

</html>

        在浏览器中打开 http://192.168.96.132:8080/myapp/index.jsp 查看是否可以显示。java是编译后运行,编译结果都在/usr/local/tomcat/work中了。

几个目录的作用:

        WEB-INF/      当前webapp的私有资源目录,通常存放当前webapp自用的web.xml

        META-INF/    当前webapp的私有资源目录,通常存放当前webapp自用的context.xml

        classes/          此webapp的私有类

        lib/                 此webapp的私有类,被打包为jar格式类

        index.jsp        webapp的主页


host-manager:

打开:conf/tomcat-users.xml,并添加如下内容:

<role rolename="manager-gui"/>

<user username="tomcat" password="tomcat" roles="manager-gui"/>


AJP连接器:

        server.xml中定义的HTTP连接器:定义HTTP连接器的时必须属性只有port,定义HTTPS属性只有protocol

        <connector port="8080" protocol="HTTP/1.1" maxThreads="150" connectionTimeout="2000" redirectPort="8442" >

address           指定连接器监听地址

maxThreads    支持最大的并发连接数,默认200

port                 监听的端口,默认为0

protocol          连接器使用的协议,默认为HTTP/1.1,AJP协议通常为AJP/1.3

redirectPort    当客户端发送HTTPS协议时,连接器只支持HTTP协议,则跳转到HTTP端口

connectionTimeout    连接超时时间

enableLookups           通过DNS反向查询主机名,非常耗时间,建议为false,默认为true

acceptCount               等待列队最大长度


SSL连接器:

        <Connector port="8443" maxThreads="150" minSpareThreads="25" maxSpareThreads="75" enableLookups="false" acceptCount="100" debug="0" scheme="https" secure="true" clientAuth="false" sslProtocol="TLS" />

maxThreads    最大并发线程

minSpareThreads     最小空闲线程

maxSpareThreads    最大空闲线程

debug           关闭debug

scheme         接受请求的类型

secure           安全加密

clientAuth     验证客户端,建议false

sslProtocol    SSL协议


Engine组件:

        Engine是Servlet处理器的一个实例,即servlet引擎,默认为定义在server.xml中的Catalina。Engine需要defaultHost属性来为其定义一个接收所有发往非明确定义虚拟主机的请求的host组件。如前面示例中定义的:<Engine name="Catalina" defaultHost="localhost">

        常用的属性定义:defaultHost:Tomcat支持基于FQDN的虚拟主机,这些虚拟主机可以通过在Engine容器中定义多个不同的Host组件来实现;但如果此引擎的连接器收到一个发往非非明确定义虚拟主机的请求时则需要将此请求发往一个默认的虚拟主机进行处理,因此,在Engine中定义的多个虚拟主机的主机名称中至少要有一个跟defaultHost定义的主机名称同名。

name:Engine组件的名称,用于日志和错误信息记录时区别不同的引擎。

Engine容器中可以包含Realm、Host、Listener和Valve子容器。


Host组件:

        位于Engine容器中用于接收请求并进行相应处理的主机或虚拟主机,如前面示例中的定义:

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

</Host>

appBase          此Host的webapps目录,即存放非归档的web应用程序的目录或归档后的WAR文件的目录路径,可以使用基于$CATALINA_HOME的相对路径。

autoDeploy     在Tomcat处于运行状态时放置于appBase目录中的应用程序文件是否自动进行deploy;默认为true。

unpackWars    在启用此webapps时是否对WAR格式的归档文件先进行展开;默认为true。

reloadable       是否支持重新装载

虚拟主机定义示例:

        tomcat支持基于主机名、IP、端口的虚拟主机。每个Host代表一个虚拟主机,

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

      <Host name="localhost" appBase="webapps">

            <Context path="" docBase="ROOT"/>

            <Context path="/bbs" docBase="/web/bss" reloadable="true" crossContext="true"/>

      </Host>

      <Host name="mail.magedu.com" appBase="/web/mail">

            <Context path="/" docBase="ROOT"/>

      </Host>

</Engine>

例:

        如果标签内部没有多余要定义的选项,可以直接在结尾处用斜杠 / 结束,而不用写</xxx>的结束标签。定义虚拟机主要有Host和Context即可,其他可选。

<Host name="web1.456.com" appBase="/data/webapps" unpackWARs="true" autoDeploy="false">

        <Context path="" docBase="/data/webapps/" reloadable="true" />

        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="/data/logs" prefix="web1_access_log" suffix=".txt" pattern="%h %l %u %t &quot;%r&quot; %s %b" />

</Host>

path          访问的路径

docBase    系统中存放文档的路径,可以是相对路径,相对于Host中的appBase

注意:如果服务启动不了查看配置文件中定义的目录是否都创建了。

主机别名定义:

        如果一个主机有两个或两个以上的主机名,额外的名称均可以以别名的形式进行定义,如下:

<Host name="www.scriptjc.com" appBase="webapps" unpackWARs="true">

        <Alias>scriptjc.com</Alias> #定义主机的别名

</Host>


Valve组件:

        Valve类似于过滤器,它可以工作于Engine和Host/Context之间、Host和Context之间以及Context和Web应用程序的某资源之间。一个容器内可以建立多个Valve,而且Valve定义的次序也决定了它们生效的次序。Tomcat6中实现了多种不同的Valve:

        AccessLogValve             访问日志Valve

        ExtendedAccessValve    扩展功能的访问日志Valve

        JDBCAccessLogValve     通过JDBC将访问日志信息发送到数据库中

        RequestDumperValve    请求转储Valve

        RemoteAddrValve         基于远程地址的访问控制

        RemoteHostValve          基于远程主机名称的访问控制

        SemaphoreValve           用于控制Tomcat主机上任何容器上的并发访问数量

        JvmRouteBinderValve    在配置多个Tomcat为以Apache通过mod_proxy或mod_jk作为前端的集群架构中,当期望停止某节点时,可以通过此Valve将用记请求定向至备用节点;使用此Valve,必须使用JvmRouteSessionIDBinderListener。

        ReplicationValve          专用于Tomcat集群架构中,可以在某个请求的session信息发生更改时触发session数据在各节点间进行复制。

        SingleSignOn               将两个或多个需要对用户进行认证webapp在认证用户时连接在一起,即一次认证即可访问所有连接在一起的webapp。

        ClusterSingleSingOn    对SingleSignOn的扩展,专用于Tomcat集群当中,需要结合ClusterSingleSignOnListener进行工作。


访问控制:

        RemoteHostValve和RemoteAddrValve可以分别用来实现基于主机名称和基于IP地址的访问控制,控制本身可以通过allow或deny来进行定义,这有点类似于Apache的访问控制功能;如下面的Valve则实现了仅允许本机访问/probe:

<Context path="/probe" docBase="probe">

        <Valve className="org.apache.catalina.valves.RemoteAddrValve" deny="127\.0\.0\.1"/>

</Context>

deny后面跟要拒绝的IP地址,allow后面跟可以访问的地址。


LNMT:

        client --> http --> nginx --> reverse_proxy --> http --> tomcat(http connector)

        使用nginx反向代理,客户端请求nginx,nginx将请求发送到tomcat。首先在另一台主机上安装nginx,将nginx配置成反向代理,将请求发送到tomcat所在的主机上。


安装nginx:

        yum install nginx,使用的是epel yum源,安装好后打开配置文件 /etc/nginx/nginx.conf。

        location / {

                proxy_pass http://web1.456.com:8080; 将反向代理指向tomcat所在的服务。

        }

        注意设置hosts文件,客户端主机hosts文件将域名web1.456.com指向nginx所在的主机地址,nginx主机上的hosts文件将域名指向tomcat所在的主机地址。

        tomcat主机上也要配置响应的虚拟主机可以接受web1.456.com域名发送过来的请求。虚拟主机配置过程如上。这样客户端访问web1.456.com域名的时候实际上是nginx接受的请求通过反向代理到tomcat处理完成后发送给nginx再返回给客户端。


动静分离:

        将动态内容发送到tomcat,静态内容由nginx处理,在nginx配置文件的server中加上如下配置信息,index是用于设置主页文件,root是存放静态内容的位置,location中定义的是将以jsp结尾或do结尾的请求发送到tomcat。

        server {

                index        index.jsp index.html;

                root         /usr/share/nginx/html;

                location ~* \.(jsp|do)$ {

                        proxy_pass http://web1.456.com:8080;

                }

        }


LAMT:

        client --> http --> httpd --> reverse_proxy --> {http|ajp} --> tomcat { http connector | ajp connector}

        使用httpd服务作为反向代理。首先安装httpd服务yum install httpd,安装好后使用httpd -M查看加载的模块,可以看到支持反向代理的模块

        proxy_module            主模块,下面两个模块要使用必须要开启这个模块。

        proxy_ajp_module      ajp协议模块

        proxy_http_module    http协议模块


一、使用http协议实现反向代理:

        在httpd的配置中,在/etc/httpd/conf.d/中创建一个虚拟机文件vhosts.conf,在里面写入如下配置信息。

        <VirtualHost *:80>

            ServerName web1.456.com      主机名,必须

            ProxyVia On

            ProxyRequests Off

            ProxyPreserveHost On          必须,是否保留主机名,将主机名也发送到tomcat,这样tomcat就可以基于虚拟机

            <Proxy *>

                    Require all granted

            </Proxy>

            ProxyPass / http://192.168.96.132:8080/

            ProxyPassReverse / http://192.168.96.132:8080/

            <Location />

                    Require all granted

            </Location>

        </VirtualHost>

        配置好后使用httpd -t检查语法是否有错误,然后启动httpd服务,在客户端浏览器上输web1.456.com 就可以访问到页面内容,而且是tomcat虚拟机中的内容,如果直接使用httpd服务的IP地址看到的则是tomcat的默认页面,这个功能就是ProxyPreserveHost 提供的。


二、使用ajp协议实现反向代理:

        只要将上面的配置中的两条改成如下的即可,注意端口是8009,因为tomcat ajp协议的监听端口为8009,协议改成ajp。

        ProxyPass / ajp://192.168.96.132:8009/

        ProxyPassReverse / ajp://192.168.96.132:8009/

        修改好后重启服务即可,可以在浏览器端使用检查元素中看到请求的服务器类型。如果有些页面不想使用反代,可以在ProxyPass前面加上一个ProxyPass,再定义不想反代的页面,在后面加上叹号即可。具体配置如下:

        ProxyPass /status !