**前言**(转载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原理
①处表示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所示
在XML文件的代码中,这些组件之间关系如下所示:
<Server>
<Service>
<Connector/>
<Engine>
<Host>
<Context>
</Context>
</Host>
</Engine>
</Service>
</Server>
上述各组件将Tomcat分成若干层(Server层、Service层、Engine层、Host层、Context层),各层通过数据管道PipeLine交互,如图1-3所示。
上述各层对应组件及其在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 "%r" %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 / #代理至后端的服务器 ProxyPassReverse / 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的默认虚拟主机
基于域名访问为后端tomcat定义的虚拟主机
**使用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即可 ProxyPassReverse / 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; }