**前言**(转载http://yangleilt.iteye.com/blog/695854)



一:Tomcat


Tomcat是Sun的JSWDK(Java Server Web Development Kit)中的Servlet容器,属于Apache软件基金会(Apache Software Foundation)的Jakarta项目中的一个核心项目,由Apache、Sun和其他一些公司和个人共同开发而成。Tomcat既是一个开放源码、免费支持JSP和Servlet技术的容器,同时又是一个Web服务器软件,受到了Sun公司的大力推荐和支持.

二、Tomcat优点


Tomcat是一个小型的轻量级应用服务器,运行时占用系统资源小、扩展性好、支持负载平衡与邮件服务等开发应用系统中的常用功能,并且不断改进和完善。Tomcat适用于中小型系统和并发访问用户不太多的场合,是开发和调试JSP程序的首选。先进的技术、稳定的性能、源码开放和免费获取的机制,使得Tomcat深受Java爱好者的喜爱并得到了许多软件开发商的认可,成为目前相当流行的处理动态Web应用服务器。

三、toncat原理


wKiom1bhiorznYLOAAALNX2bOVU734.gif


①处表示Web服务器接收到客户端发出的HTTP请求后,转发给Servlet容器,同时把控制返回Servlet容器;②处表示Servlet容器把响应对象ServletResponse中的处理结果转发给Web服务器,通知Web服务器以HTTP响应的方式把结果发送到客户端,同时把控制返回Web服务器。 

当初在Apache开发时还未出现Servlet的概念,所以Apache不能内置支持Servlet。实际上,除了Apache,其他许多Web服务器软件都不能直接支持Servlet。为了支持Servlet,通常要单独开发程序,这种程序一般称为服务器小程序容器(Servlet Container),有时也叫做服务器小程序引擎(Servlet Engine)。它是Web服务器或应用程序服务器的一部分,用于在发送的请求和响应之上提供网络服务,解码基于MIME的请求,格式化基于MIME的响应,它在Servlet的生命周期内包容和管理Servlet,是一个实时运行的外壳程序。运行时由Web服务器软件处理一般请求,并把Servlet调用传递给“容器”来处理。Tomcat就是满足这种需要的JSP/Servlet引擎,是Sun公司的JSP/Servlet的官方实现。 
按照工作模式的不同,Servlet容器可以分为以下3类: 
1.独立运行的Servlet容器 
在这种模式下,Servlet容器作为构成Web服务器的一部分而存在。当使用基于Java的Web服务器时,就属于这种情况。这种方式是Tomcat的默认模式,然而大多数Web服务器并不是基于Java的,所以就产生了下面的两种其他类型。 
2.内置的Servlet容器 
Servlet容器由Web服务器插件和Java容器两部分组成。采用这种方式时,Web服务器插件需要在某个Web服务器内部地址空间中打开一个JVM(Java虚拟机),在此JVM上加载Java容器并运行Servlet。如果客户端调用Servlet,Web服务器插件首先获得此请求的控制并将它传递(使用JNI技术)给Java容器,然后Java容器把此请求交给Servlet来处理。这种方式运行速度较快,并且能够提供良好的性能,适用于单进程、多线程服务器,但是在伸缩性方面存在不足。 
3.外置的Servlet容器 
采用这种方式时,Servlet容器运行在Web服务器外部地址空间。先由Web服务器插件在某个Web服务器外部地址空间打开一个JVM(Java虚拟机),然后加载Java容器来运行Servlet。Web服务器插件和JVM之间使用IPC(进程间通信)机制(通常是TCP/IPSockets)。如果客户端调用Servlet,Web服务器插件首先获得此请求的控制并将它传递(使用IPCs技术)给Java容器,然后Java容器把此请求交给Servlet来处理。这种方式对客户端请求的处理速度不如内置Servlet那样快,但是在其他方面(如可伸缩性、稳定性等)具有优势。 
Tomcat属于Servlet容器,其工作模式也分为上述3种,所以Tomcat既可被用作独立运行的Servlet引擎(便于开发和调试),又可作为一个需要增强功能的Web服务器(如当前的Apache、IIS和Netscape服务器)插件。在配置Tomcat之前,就需要确定采用哪种工作模式,工作模式(1)比较简单,直接安装Tomcat即可,工作模式(2)和(3)有些复杂,除了安装Tomcat、Web服务器之外,还需要安装连接两者的中间连接件。


四、 Tomcat层次结构 


Tomcat服务器由一系列可配置组件构成,其中核心组件是Catalina Servlet容器,它是其他所有Tomcat组件的顶层容器。Tomcat各组件之间存在的层次关系如图1-2所示

wKioL1bhi5PgIwIRAAAk7rETOAM892.jpg


在XML文件的代码中,这些组件之间关系如下所示: 
<Server> 
<Service> 
<Connector/> 
<Engine> 
<Host> 
<Context> 
</Context> 
</Host> 
</Engine> 
</Service> 
</Server> 
上述各组件将Tomcat分成若干层(Server层、Service层、Engine层、Host层、Context层),各层通过数据管道PipeLine交互,如图1-3所示。 

32045604-9b3f-3b02-8ac5-a4858d870f1c.jpg


上述各层对应组件及其在Tomcat服务器中的作用如下: 

(1)Server层 
对应Server组件,逻辑上表示整个Tomcat,即整个Catalina Servlet容器。它处于Tomcat顶层,可以包含一个或多个Service层。Tomcat提供了该层接口的一个默认实现,所以通常不需要用户自己去实现。 
 
图1-3  Tomcat的层次结构 
(2)Service层 
对应Service组件,是包含在Server层中的一个逻辑功能层。它包含一个Engine层,以及一个或多个连接器(Connector)。Service组件将一个或多个Connector组件绑定到Engine层上,Connector组件侦听端口,获得用户请求,并将请求交给Engine层处理,同时把处理结果发给用户,从而实现一个特定的实际功能。Tomcat提供了Service接口的默认实现,所以通常也不需要用户定制。 
(3)Engine层 
对应Engine组件,该层是请求分发处理层,可以连接多个Connector。它从Connector接收请求后,解析出可以完成用户请求的URL,根据该URL可以把请求匹配到正确的Host上,当Host处理完用户请求后,Engine层把结果返回给适合的连接器,再由连接器传输给用户。该层的接口一般不需要用户来定制,特殊情况下,用户可以通过实现该接口来提供自定义的引擎。 
(4)Host层 
对应Host组件,该层表示一个虚拟主机,一个Engine层可以包含多个Host层,每个Host层可以包含一个或多个Context层,对应不同的Web应用。因为Tomcat给出的Host接口的实现(类StandardHost)提供了重要的附加功能,所以用户通常不需要定制Host。 
(5)Context层 
对应Context组件,该层代表某个虚拟主机上的实际目录或一个WAR,即单个Web应用程序,它运行在特定的虚拟主机中,使用最为频繁。一个Host层包含多个Context层,每一个Context都有唯一的路径,Host层接到请求后,根据用户请求的URL,将请求定位到Context层。 



 

**tomcat安装与配置**



实验环境:CaentOS 7


rpm包安装:java-1.7.0-openjdk(开源的java开放工具包)

   java-1.7.0-openjdk-devel

   tomcat

   tomcat-lib

   tomcat-webapps

   tomcat-admin-webapps

[root@node8 tomcat]# cat /etc/profile.d/java.sh      #安装完成后需要导出JAVA_HOME到环境变量
JAVA_HOME=/usr/bin
export JAVA_HOME
[root@node8 tomcat]# . /etc/profile.d/java.sh  #重读该脚本生效

[root@node8 tomcat]# grep "^[[:space:]]\+<Connect" server.xml   #rpm包安装后tomcat默认的connector
    <Connector port="8080" protocol="HTTP/1.1"      #http1.1的连接器,端口为8080
    <Connector executor="tomcatThreadPool"
    <Connector port="8443" protocol="org.apache.coyote.http11.Http11Protocol"   #http11的连接器,端口为8443
    <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />    #ajp协议的连接器,端口为8009
    

     <Host name="localhost"  appBase="webapps"     #tomcat默认的虚拟主机
            unpackWARs="true" autoDeploy="true">
        
        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
               prefix="localhost_access_log." suffix=".txt"
               pattern="%h %l %u %t &quot;%r&quot; %s %b" />

      </Host>
      <Host name="node8.tz.com"  appBase="/data/webapps"   #自定义的虚拟主机
            unpackWARs="true" autoDeploy="true">
           <Context path="/test" docBase="testapp" reloadable="true" />
      </Host>
            
    
[root@node8 tomcat]# sysytemctl start tomcat   #启动tomcat
[root@node8 tomcat]# ss -tanlp | awk '{print $4}'
Local
*:22
127.0.0.1:25
::ffff:127.0.0.1:8005
:::8009                 #8009端口被监听
:::80
:::8080                 #8080端口已经被监听
:::22
::1:25

 

(注:tomcat进程默认以普通用户身份运行,所以不能随便更改端口为1024以下,tomcat一般只面对前端的apache处理请求,所以我们也无需更改端口)


**配置apache做为反向代理**



[root@node8 conf.d]# httpd -M |  grep "proxy"     #httpd关于proxy的模块
 proxy_module (shared)                   
 proxy_ajp_module (shared)
 proxy_balancer_module (shared)
 proxy_connect_module (shared)
 proxy_express_module (shared)
 proxy_fcgi_module (shared)
 proxy_fdpass_module (shared)
 proxy_ftp_module (shared)
 proxy_http_module (shared)           
 proxy_scgi_module (shared)
 proxy_wstunnel_module (shared)

[root@node8 conf.d]# cat proxy.conf    #在conf.d目录下创建该配置文件
<VirtualHost *:80>
    ServerName tc1.tz.com                
    ProxyRequests Off                  #关闭apache正向代理
    ProxyVia On	                       #控制在http首部是否使用Via(用于多级代理中)
    ProxyPreserveHost On               #启用该功能httpd会将请求报文中的Host发送给后端(适用于基于不同虚拟主机的代理)

    <Proxy *>
	Require all granted           #代理访问控制
    </Proxy>
    ProxyPass /      #代理至后端的服务器 
    ProxyPa***everse / http://localhost:8080/
    <Location />                      #访问控制
	Require all granted
    </Location>
</VirtualHost>


**为tomcat虚拟主机提供所需目录及文件测试页面**



[root@node8 webapps]# tree
.
├── ROOT      #虚拟主机默认的根目录
│   ├── classes
│   ├── index.jsp    #测试的主页文件
│   ├── lib
│   ├── META-INF
│   └── WEB-INF

[root@node8 ROOT]# cat index.jsp    #提供测试文件代码
 <%@ page language="java" %>
<html>
  <head><title>Tomcat8</title></head>
  <body>
    <h1><font color="red">node8.tz.com</font></h1>
    <table align="centre" border="1">
      <tr>
        <td>Session ID</td>
    <% session.setAttribute("magedu.com","magedu.com"); %>
        <td><%= session.getId() %></td>
      </tr>
      <tr>
        <td>Created on</td>
        <td><%= session.getCreationTime() %></td>
     </tr>
    </table>
  </body>
</html>


**测试**




将windows本地hosts文件加入node8.tz.com虚拟主机的解析


地址访问默认为后端tomcat的默认虚拟主机

wKioL1bhk43iOg3jAAENKGAIJYc815.png


基于域名访问为后端tomcat定义的虚拟主机

wKiom1bhkzfwbjUtAABBdK_3E24528.png


**使用ajp协议进行反向代理**



[root@node8 ROOT]# cat /etc/httpd/conf.d/proxy.conf 
<VirtualHost *:80>
    ServerName tc1.tz.com
    ProxyRequests Off
    ProxyVia On	
    ProxyPreserveHost On

    <Proxy *>
	Require all granted
    </Proxy>
    ProxyPass / ajp://localhost:8009/    #只需将此处协议改为ajp端口改为8009即可
    ProxyPa***everse / ajp://localhost:8009/
    <Location />
	Require all granted
    </Location>
</VirtualHost>


**基于nginx做反向代理**



location  / {                 #在nginx配置文件的server中定义此location
                proxy_set_header Host $http_host;   #将请求报文中的host信息传递给后端(实现基于虚拟主机的代理)
                proxy_pass http://localhost:8080;
                index index.html index.htm;
        }