Apache与Tomcat的整合
旣然巳架设好Apache,并让它在系统上运行了,则可以开始处理Tomcat整合。选择您喜 爱的选项,并以此方式处理。也可试验每个选项并进行下去,或每个都试试,看看最喜 欢哪一个选项并领会最喜欢的选项。
图5-1:Apache httpd 2.2 welcome页
使用不同的端口分担负载
每个等待来自客户端的输入连接(incoming connection)的服务器,都被称为监听在所运行的机器的特定TCP端口上。这些端口号类似于建筑物内的电话分机。Web服务器一般在端口80上监听,而此端口已正式被分配为WWW服务的默认端口号。浏览器都知道这件事,所以当浏览URL http://tomcatbook.darwinsys.com/的,浏览器都连接到Ian的服务器默认端口80上。另一方面,如果您在URL中放入端口号,如http:"foo.bar.xyx:1234/index.html,则浏览器会连接到(假想的)服务器的端口1234上。
正如不能在同一电话分机上间时与两个不同的人对话一样,您也不能让两台Web服务器 在同一端口号上监听。因此,如果想要在同一台机器上执行两个服务器程序,其方法之 一必须下线或搬移至不同的端口,而不能同时在端口80上运行。当然,设定的方式则一定是与服务器实现有关。在Apache httpd服务器中,应于httpd.conf文件内使用Listen指令。而在Tomcat中,则应于server.xml的配置文件内设定HTTP Connector元素的端口号属 性,幸运的是,从现货供应的Tomcat已将此值设为8080,而非默认的80。这可以让您在不需任何特殊权限的条件下就能进行测试(在小于1024的端口号上运行服务器,需要在非Windows的服务器操作系统上使用root的权限,以防止“一般用户”架设自己的服务 器,并伪装成经过授权的服务器)。把Tomcat的默认HTTP端口设为8080也可以让您运行Tomcat,而不会与在标准的端口80上运行的现成服务器(如冲突,在不修改 默认配置文件的情形下,您应该能在同“台机器t:同是运行Apache 与Tomcat,而 不会造成服务器socket端口的冲突。若想避免这些冲突,追踪共存于任何巳知计算机上 所有服务器程序使用的端口号,是个不错的想法。
第一种解决方案的实现方法是直截了当的。一旦让两台服务器都运行后,通过在第一台 服务器中使用可通向第二台服务器的URL,您可以“连接”它们。例如,在Ian的网域 darwinsys.com上。如果httpd是在80端口上,而Tomcat位于8080端口上,则可以使用以下的URL从/mpd的HTML网页重定向至Tomcat的JSP网页:
Please fill in <a href="http:www.darwinsys.com:8080/process.jsp"> this form </a> for more information.
这是十分简单而且可行的。
另一神解决方案是从Apache httpd服务的HTML贝中引用由Tomcat提供的静态内容。例 如,您已经在Tomcat Web应用程序中部署了图像文件,并在Apache httpd的文档根目录 下部署了包含该图像文件的HTML网页:
<p>Here is a picture of an 800 pound gorilla:</p> <img src="http://www.example.com:8080/static//upload/image/course/tomcat/george.jpg">
按这种方式,Tomcat可以为Apache httpd处理繁重的挣态文件服务。这里需要注意的一些重要的事情是,从用户的角度看,这样处理就像整个网页的内容来源于一台Web服务 器一样。事实是来源于不同端口的图像并没有被Web浏览器展示,图像只足被嵌人在网页中,而且没有显示它们的URL。
通过使用<iframe> HTML标签,您还可以在网页中包含另一台服务器的内容。下面的例 子演示了从一台服务器上提供的网页,该网页包含了由定位到另一台服务器的URL (潜在 地指服务器端口号,但是,即使是到另一个域的URL也会工作)产生的一些远程文本:
<html> <body> <p>This is text at the top of the page.</p> <iframe src="http://www.example.com:8080/index.jsp" frameborder="O" scrolling="no" style="width; 600px; height: 40px;"></iframe> <p>This is text at the bottom of the page.</p> </body> </html>
该网页包含了一个从内部frame元素,该元素从不同服务器端口的另一台服务器上加载内容,并将内容放在含有本地文本的网页上面和下面。如果远程网页的index.jsp文件刚好输出了Hello,那么在完全实施完毕以后,这一HTML网页将看起来如下所示:
This is text at the top of the page. Hello. This is text at the bottom of the page.
Apache httpd会忽略Tomcat的安全防护
如果看到的目录与Tomcat看到的实体目录一样,则用户将能在端口上查看JSP 或其他模板文件的原始程序代码。另外,如果在这种情况下于Tomcat中部署Web应用程 序,除非适当地设定不从那些目录中提供文件,否则它会从服务于Web应用程序的 从与录中响应请求并提供文件,而这些文件可能会含有机密数据。这不是一件好事,所以请以不同目录树存放的文档根目录和Web应用程序内容。
两次调校、维护Web服务器并确保Web服务器安全
您不得不运行并维护两台不同的Web服务器。如果需要调校网站的性能,则不得不调校 这两台Web服务器的性能,而非一台,而且每台的调校方式也必顼不同,因为它们是具 有不同性能特性和设置的不同软件包,您还不得不頋及到两台Web服务器实现的稳定性 与安全防护,而非一台。
较差的用户经验与分散的日志记录
通过检査URL,用户可以知道您正使用两台不同的Web服务器。依网站内容的不同,这也许会或不会产生问题。不过,实际上笔者看到过由此产生的许多叫题。例如,如果允 仵用户可以保存只由Tomcat提供的网页,则他们可能不会再请求来自服务器的网页 了。如果跟踪只分析日志的访问用户,考虑到用户一直录入httpd提供的主页网址, 则这会是一个问题,为了解决这个问题,您需要分析httpd以及Tomcat的访问日志然后 利用L具合并日志文件。幸运的是,httpd以及Tomcat的访问日志都具有相同的格式。
麻烦的双重验证
如果在访问某些网页内容前,网站首先要求所有的用户都要登录,则您要么需要登录两 次(如果/当他们请求来自网站的信息,则一次给然后再给Tomcat),要么不得 不实现Mfpd与Tomcat之间的某种通信验证(从而TonKat知道用户已经登录了)。这种做 法可能会很复杂,因此,也许并不值得这样做。
从Apache到Tomcat的代理服务器
前节所说的URL整合方法的缺点之一是在用户的网页浏览器中可以看到新的URL (尽管用户可能看不到)。我们可以用一台Web服务器代理请求到其他服务器的机制来解决此 叫题。也就是说,第一台接触的Web服务器(注1),也称为原始服务器,收到了访问第 二台服务器资源的请求,而第一台服务器新产生了对第台服务器的请求,并把第二台 服务器的响应结果返问到客户端。
Apache httpd在HTTP、AJP和其他(不常用的)协议中实现代理的模坱叫做mod_proxy。在httpd2.2文档网页http://httpd.apache.org/docs/2.2/mod/mod_proxy.html上了解有关mod_proxy的内容。这一网页上包含一些有关前向代理和反向代理的、文风很好的解释:
普通的前向代理是位于客户端与原点服务器之间的媒介服务器。为了从原点服务器上获取内容,客户端把请求发送到命名原点服务器的代理,以作为访问目标,然后 从原点服务器上请求内容,并将结果返回客户端a为了使用前向代理以访问其他网 站,必须对客户端进行特殊配置。
架设Apache httpd
假设想要让将所有对目录的引用都映射给Tomcat处理。首先,您必须确定 可以在httpd中使用mod_proxy。如果已经在使用mod_proxy,则可以跳过下一段或两段的 内容。如果将编译成共享对象(在httpd的二进制发布版本中,通常都已被编译过,并且可供使用),这意味着如果下列行不在httpd.conf文件中,则只耍把下列行放在httpd的合适位置就可以了 :
LoadModule proxy_module modules/mod_proxy.so LoadModule proxy_http_module modules/mod_proxy_http.so LoadModule proxy_ajp_module modules/mod_proxy_ajp.so
当然,必须确保配置文件中这一路径,能正确找到操作系统通常安装可加载的Apache模 块的具体位置。如果这使httpd产生了日志错误,则可能需要根据源文件进行重新编译, 配置该编译文件以包含mod_proxy、mod_proxy_ajp和mod_proxy_http。但是,mod_proxy 及其关联模块已被广泛的使用,以至于它们已被编译到Apache 中,且默认可用于大部分Linux发行版。
设置Tomcat
现在,需要在Tomcat端配置HTTP 1.1服务器,在相关的Host元素内,增加这一Connector元素:
<!--在端口 80BO上定义代理HTTP/1.1 的 Corrector --> <Connector port="8080" protocol="HTTP/1.1" maxThreads="150" connectionTimeout="20000" proxyName="www.example.com"proxyPort= "80" redirectPort= "443" disableUploadTimeout ="false" />
如果运行Tomcat的AccessLogValve以记录客户端请求的日志信息,且您乐意显示 webS户端的真实IP地址,而不是显示Apache 的IP地址,则您需为此配置AccessLogValve。Apache httpd指令 Proxy Via On 使 Apache httpd以x-forwarded-for报头给 Tomcat发送Web客户端的IP地址。能用%{header-name}i样式标记记录报头值的日志信息。因此如果按如下方式配置:
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" prefix="localhost_access_log." suffix="txt" pattern="%{x-forwarded-for}i %l %u %t %r %s %b" resolveHosts="false"/>
则会记录Web客户端IP地址的日志信息,就像Apache没有代理请求一样。
确定代理机制可以运行
一旦重启Tomcat,则代理功能就应能完全运行。例如,在设置之后,但在将/loch-ness Context增加到Tomcat之前,尝试在80端口上访问代理,应会看到Tomcat 404网页,而非 httpd 404网面,如图5-2所示。
不足之处
通过整合Tomcat与Apache httpd的方法之一是Tomcat通过httpd进行应答,而非直接对网页浏览器响应。网页浏览器(以及用户)只会在URL中看到一个Web服务器的地址,因此看起来所有的响应都是来自一个整合的网站。httpd的访问日志含有对及Tomcat的请求所有访问日志信息。不过,这还是有一些如下缺点。
图5-2:通过Apache httpd及mod_proxy看到的Tomcat404网页
此看起来所有的响应都是来自一个整合的网站。httpd的访问日志含有对httpd及Tomcat的请求所有&问F1志信息。不过,这还是有一些如下缺点。
Apache httpd减慢了Tomcat的响应时间
至少在基准调校中,Apache httpd响应HTTP请求的速度要比几乎所有使用场合 的Tomcat都要慢。而且,在Apache httpd不得不传递Tomcat的请求和响应的时候,独立 Tomcat相比于相同请求业务量下只通过Apache httpd和连接器模块与Tomcat进行交互,要快51%~257%。但是,如果网站业务负栽不高,且在网站服务于峰值负载时,在这一配置下,网页加载速度似乎还足够快,则这是要十分关注的(但要知遒性能下降问题)。
两次调试、维护及安全防护Web服务器
仍然要维护并调校两台Web服务器的性能a如果您愿保证到Tomcat的客户端陆求只通过Apache httpd,则应配置网络防火墙,从而只有一台运行Apache的计算机(而且或许是局域网上的其他机器)可以连接到Tomcat的Web服务器端口。这不是关心所有应用程序的安全防护策略,因此您应决定阻止客户端,决定哪些能到达Tomcat的服务器端口。
麻烦的双重认证
httpd与Tomcat之间无法分享验证与访问控制,不过,此问题适用干所有整合Tomcat与 httpd的方法。当用户经由httpd验证机制登录时,Tomcat并不会知道,并且当用户请求保护的Web应用程序资源时,还会要求再登录一次。此外,当用户登录httpd及Tomcat后,在各个服务器上可能会有不同的扠限及角色,并以不同的格式储存在不同的文件中。
还要注意
并相所有Web应用程序都可如此简单地代理,因为并非所有Web应用程序都使用相关链 接与应用程序中的其他资源相连。例如,如果Web应用程序运行在叫做tomcathost的内部主机的Tomcat中,而Apache httpd运行在叫做www.example.com的公用机器上,而且在Web应用程序的一个HTML页上加载了如下所示的图片:
<img src="http://tomcathost:8080//upload/image/course/tomcat/Tomcat.jpg">
然后,在Apache httpd代理这一响应并把结果发送到公共Web客户端时,<img>标签看起来还是那样。但是,为了加载图片,Web客户端不能经公共Internet到达tomcat-host:8080,导致Web客户端的网页上显示一个残缺的图像图标。被代理的HTML页仍然显示 tomcathost:8080的原因是mod_proxy并没有修改所代理的内容。mod_proxy没有提供自动在内容中寻找和修改URL的特性。它只递归地把Web应用程序的目录树映射为Apache httpd的URI空间上的目录路径。
当Web应用程序包含了一个<href>链接到相对于服务器根目录的绝对路径、并将它映射到Apache httpd的URI空间上的不同URI时,会发生相同的事情。例如,如果配置Apache httpd,使Web应用程序相对于Apache的/webapp-name/目录,而Web应用程序的一个 HTML网页中包含类似于下列的链接:
<a herf="//upload/image/course/tomcat/Tomcat.jpg">Click here</a>
它不会映射到Web应用程序的image目录,但仍然会映射到Apache httpd自身的//upload/image/course/tomcat目录,而在该目录下则无法找到Tomcat.jpg文件。
大概修补这一问题的最佳方式是使用第三方模块,如mod_proxy_html(不要混淆为 mod_proxy_http,只有两个字母之差)。mod_proxy_html的存在是为了通过过滤与修改httpd代理Tomcat的内容,以解决预先映射的问题,从而在将内容发给客户端之前,可以找到并修改任何原始的相对或绝对的URL。这是非常容易让人困惑的事情。一但设置好,并适当修改了恶意代理(proxy-unfriendly) Web应用程序发给Web客户端的URL,则Web应用程序将呈现为直接由Apache提供服务。
从Tomcat到Apache httpd的代理
通常情况下,Tomcat提供文件的逨度要比Apache httpd提供文件的速度耍快,如果您要让网站页能执行,那为什么不把Tomcat放在前端并让它在必要的时候才代理到Apache httpd的请求呢?如果可以从Tomcat提供大多数请求(静态文本和/或servlet和/或JSP), 最好是从比较快的Web服务器(Tomcat)服务大部分请求,并代理少量请求到Apache httpd。如果关注性能,则把Tomcat放在前端,相比于把较慢的Web放在前端,会工作更好,否则处理所有请求的速度只能与较慢的Web服务器一样快。因此,为什么不把Tomcat放在“前端”及Apache httpd放在“后端”呢?笔者相信大多数网站都应按这种方式配置,这一点与让Apache httpd作为首台交互服务器相反。
不幸的是,截至本书发稿,Tomcat并没有实现代理请求到其他Web服务器的功能。因为它不是Tomcat的嵌入式功能,所以另一选项是增加代理请求的一些代码,或者作为Web 应用程序的一部分,也可以作为Tomcat Valve (门限)。
使用mod_jk连接器
本节描述如何经由mod_jk连接器模块,将Tomcat4用作Apache httpd Web服务器的后端 Servlet container来使用。因为有太多连接器、配置与组件的组合,所以在本书中根本不可能一一举例说明。笔者只描述及示范如何在Apache httpd 2.2.x服务器中使用mod_jk。
使用二进制发行版
如果您已经安装并运行Apache2,请看看是否能找到可运行的二进制发布版本的Tomcat连接器源码(一个包含mod_jk源码的独立下载)。如果无法运行,则需要编译您自己的mod_jk二进制发布版本。另外,如果/当升级新版http时,您可能要编译符合新版httpd的mod_jk。
启动整合的服务器
在启动Apache httpd前,请先启动Tomcat。您始终应该先启动Tomcat,在继续之前,请确定等足够时间,让Tomcat能完全启动。请快速浏览日志文件,以确定TOMCAT已经正确无误地启动了。
现在,请执行apachectl start命令以启动Httpd(或者,在许多Linux发行版上,运行/etc/init.d/httpd start,可以调用httpd初始化脚本)。如果Httpd已在执行中,则在重新启动运行中的服务器前,先使用apachetcl configtest来测试对httpd.conf文件的改变,因为如果配置有错,服务器则可能无法再启动。当一切都正常后,可以使用apachectl restart。一旦重启httpd成功,则链接httpd与TOMCAT的mod_jk就应已加载成功并能顺利运行了。
在图5-3中,笔者连接到80端口的Apache httpd Web服务器,请求/docs,而且可以看到,获得一个Tomcat格式的目录列表,从而表明,已经实现了与Tomcat的整合。
图5-3:通过Apache httpd提供的文档内容
mod_jk的状态显示,它可用于疑难排除t状态显示通常是第一个可见的URL已预先设定 过。只需在浏览器中请求的URL,就应该会看到如图5-4所示的状态。这将确认已设置好并运行了并将给您提供有利于调校的帮助信息。
文件workers.properties
workers2.properties文件是mod_jk的配置文件,主要描述workers或者后端服务器,也就是Tomcat服务器。每个worker都有一个名字。在Tomcat官方文档中,该名字通常用于描述协议,因此有如ajp12和ajp13的名字。笔者喜欢使用真实的服务器名。事实上,不管您使用什么样的名字,只要有利于挑选描述的名称就可以了。除了名字之外,每个worker至少拥有一个主机名、端口号和协议(或者“类型”)。而且所有的worker都必 须列在workers.list属性中。因此,最小的workers.properties文件至少具有一个类似于下列 的 worker :
图5-4:通过apache httpd显示的jkstatus
worker.list=tomcat1 worker.tomcat1.host=localhost worker.tofflcat1.port=8009
上述脚本定义了一个使用AJP 1.3协议(默认)、叫做tomcat1的单个worker,实现与位于localhost机器(同时在该机器上运行着Apache httpd)上通过端口8009进行通信的Tomcat进行对话。