网上大量的文档教程中有很多重复和无用的配置文件数据,很容易误导初学者,这是我写这篇文档的根本原因,为了提供一个具有最简洁的配置文件的tomcat与apache集成的方法,去掉以前的重复的。
费大劲看了tomcat官方的一堆E文文档后,基本理解了他们之间的关系,让人恼火的事,官方文档中的例子也是新老兼有,从tomcat3到tomcat5,同样让人无所事从,幸好只为理解其本身模块的一些参数配置,不会有太大影响。
我对tomcat整合web server(apache)的的简单理解
我对tomcat 与apache 的理解,tomcat 为一个jsp的容器,apache 为一个web server 两者之间通信通过worker进行(由Tomcat使用Server.xml文件中Connector的标签来定义其端口和协议),通过mod_jk的模块(由web服务器 像apache iis等使用)和WebServer通信,通信协议使用下列三种worker协议之一进行通信 ajp12 或者ajp13 或者jni协议,ajp12很老了,ajp13是最常用的,可以通过标准的host+port方式,实现tomcat与apache分别在不同的服务器上的安装, JNI(进程内通信)方式应该能够提供更好的性能,但是一直没有被官方推荐使用在生产环境使用,估计还是不成熟吧,还有一个LB协议是用于load-balancing负载平衡,一般人很少用,按官方文档,lb不是worker协议,只不过是起到用来定义一组worker作为其load-balancing组件的作用。
让人困惑的Tomcat Connector
不同的work程序对应不同的connector模块来与web服务器通信,常见的connecter有webapps jk jk2 ,webapp,这点也很让人头大,以前tomcat早期是一个非官方的叫Jserv的模块来连接web server ,到后来apache基金会官方开发了jk模块 然后又开发了webapp模块,然后又开发了jk2模块。
到底该用哪个呢?如果你上网Google一下,会发现无论选用哪个worker作为connector的文章,网上都有,但是你注意一下里面提到的相关软件的版本时,会发现里面有很大的差异,从tomcat3-tomcat5 都有,基本上不同的时期,会选用不同的connector来整合tomcat与各WebServer。
基本上是这样:如果是3-4年前可能是只有Jserv可用,然后是Apache自己开发的JK模块,到了大概2年前,官方推荐使用webapp,我配置过webapp模块的整合,网上教程太复杂太麻烦到一头雾水的地步,最终失败了 :-(,再次配置时已经是去年的事情了,那时官方强烈推荐使用jk2的模块,说是jk 模块的完全重新改进版本,我配置整合很容易就成功了,没想到前几天偶然上了一下apache的网站,看到这样的消息 :
地址http://apache.freelamp.com/jakarta/tomcat-connectors/
Since November 2004 - JK2 is officially unsupported!
JK2 has been put in maintainer mode and no further development will take place.
JK will be fully supported for all relevant web servers.
看清楚没,把人当猴耍,不是说了一堆jk2的先进之处么,才用多久啊,jk2用不多久就被放弃掉了,Apache开始继续发展原来的jk了,上面的理由给了就一个,jk支持所有的web servers,当初让人用jk2的时候,给出的理由可是好几条啊,倒......
现阶段只有jk模块可选罗,所以快准备下载......
配置过程简单描述:
我配置整合的整个过程其实就是 让apache 的httpd.conf文件调用一个mod_jk.conf的文件,mod_jk.conf文件又调用了workers.properties文件;再就是各配置各的虚拟主机.
mod_jk.conf 主要定义mod_jk模块的位置以及mod_jk模块的连接日志设置 还有定义worker.properties文件的位置。
worker.properties文件定义worker的参数,主要是连接tomcat主机的地址和端口信息.如果Tomcat与apache不在同一台机器上 ,或者需要做多台机器上tomcat的负载均衡只需要更改workers.properties文件中的相应定义即可。
第一部分:安装配置tomcat apache mod_jk j2sdk
准备下载下列文件
Jdk1.4.2_08
下载地址: http://java.sun.com
tomcat 5.0.28
下载地址: http://jakarta.apache.org
apache 2.0.53
下载地址: http://httpd.apache.org
mod_jk-1.2.10-apache-2.0.53.so
下载地址:http://archive.apache.org/dist/jakarta/tomcat-connectors/
安装配置
在查找资料时发现网上一位兄弟的做法,感觉很好,就是把上面所有组件都安装到D:\Server目录下,这样也方便日常管理配置和将来移植到别的服务器上去.
1:安装j2sdk
安装到 D:\server\j2sdk\ 目录下,注意安装成系统服务,其余一路回车即可
2: 安装tomcat
安装到D:\server\tomcat\目录下,注意安装成系统服务,其余一路回车即可
提前说明我遇到的两个问题极其解决方法
问题1: 在解析JSP页面时,提示无法找到java compiler
请拷贝 j2sdk\lib\tools.jar 到 tomcat\common\lib 下面 ,使用tomcat 作为service启动后总是这样,当然用startup.bat脚本启动倒是完全正常。主要原因分析起来是以service方式启动的Tomcat无法读取JAVA_HOME 和CLASS_PATH等环境变量,前面一篇转载的Tomcat的文章提到了这个问题,但是他的解决方法我用来无效.
问题2:如何解决通过服务方式启动tomcat时log中提示:
ZoneInfo:d:\server\j2sdk\lib\zi\ZoneInfoMappings (系统找不到指定的路径。)
问题很奇怪, Google中很少有这方面的资料,苦思冥想加上左翻右找之后,找到了一个解决方法
从 d:\server\j2sdk\jre\lib目录拷贝所有文件放到 d:\server\j2sdk\lib\ ,起因是因为我发现可以在jre\lib\zi中找到zi\ZoneInfoMappings 等等一堆j2sdk\lib中没有的文件, 好,这个问题解决了!!
嘿嘿,最有意思的是 jre\lib 中的文件和j2sdk\lib\ 中的文件没有一个重复的,不用担心会覆盖掉j2sdk\lib 中原有的任何文件。
3:安装apache 到 d:\server\apache\
配置 index.jsp 为默认页 配置 GB2312为默认语言
提醒一下关于默认页的问题 不只Apache的httpd.conf中定义了默认页面文件,连Tomcat的web.xml配置文件的结尾处也定义了默认页面文件,而且Tomcat中定义的的优先级还高于原有的Apache中所定义的默认页。
4:加入mod_jk连接模块
拷贝 mod_jk-1.2.10-apache-2.0.53.so 到d:\apache\apache2\modules\ 改名为mod_jk.so
5: 修改apache的配置文件
为了保持httpd.conf文件的简洁,把jk模块的配置放到单独的文件中来,就在httpd.conf中增加一行调用
include D:\server\apache\Apache2\conf\mod_jk.conf
6:配置mod_jk.conf
我们把 mod_jk的配置放到 mod_jk.conf的配置文件中,请注意使用绝对路径
mod_jk.conf的配置内容如下,其实最关键的就是 第一条 第二条 和最后一条,如果要精简,就保留这三条内容就可以了。
# Load mod_jk module
LoadModule jk_module modules/mod_jk.so
# Where to find workers.properties
JkWorkersFile conf/workers.properties
# Where to put jk logs
JkLogFile logs/mod_jk.log
# Set the jk log level [debug/error/info]
JkLogLevel info
# Select the log format
JkLogStampFormat "[%a %b %d %H:%M:%S %Y] "
# JkOptions indicate to send SSL KEY SIZE,
JkOptions +ForwardKeySize +ForwardURICompat -ForwardDirectories
# JkRequestLogFormat set the request format
JkRequestLogFormat "%w %V %T"
# Send servlet for context /examples to worker named ajp13
#JkMount /servlet/* ajp13
# Send JSPs for context /examples to worker named ajp13
JkMount /*.jsp ajp13
说一个相关的问题, 上面这一行我们设置了了 /*.jsp ajp13 就是说把所有.jsp结尾的文件都由ajp13这个worker交给tomcat处理了,但是我们这边开发的很多应用被映射为一个.do的URL(比如你访问
http://software.nxedu.com.cn/的留言薄),这样就会出错.简单解决方法 把*.jsp 改为* 即可
但是这是不好的,因为apache会把所有请求交给tomcat处理,包括图片,静态html文件等等,这是违背了我们整合的初衷,我们只需要 再添加如下一行即可。
JkMount /*.do ajp13
7:配置 worker工人
好,我们的连接器worker配置文件名被定义为workers.properties
由上面mod_jk.conf的内容可以看出文件位置在 apache的conf目录下
内容如下
worker.list=ajp13
worker.ajp13.port=8009
worker.ajp13.host=localhost #本机,若上面Tomcat主机不为localhost,作相应修改
worker.ajp13.type=ajp13 #类型
worker.ajp13.lbfactor=1 #代理数,不用修改
你找找网上其它的整合文档,你会发现一些其它的不必要的配置内容 :)
第二部分:虚拟主机的配置
举例配置2个vhost网站 一个是 localhost ,另一个是 www.ok.com
当然www.ok.com是虚拟的,本地测试时,应该修改系统中的hosts文件,添加一行 127.0.0.1 www.ok.com
1:Apache 虚拟主机配置:
Httpd.conf文件最后添加如下两个vhost内容
NameVirtualHost *:80
<VirtualHost *:80>
ServerAdmin webmaster@localhost
DocumentRoot "D:/server/Tomcat/webapps/ROOT"
ServerName localhost
ErrorLog logs/localhost-error_log
CustomLog logs/localhost-access_log common
</VirtualHost>
<VirtualHost *:80>
ServerAdmin webmaster at dummy-host dot example.com
DocumentRoot D:/server/www/
ServerName www.ok.com
ErrorLog logs/ok.com-error_log
CustomLog logs/ok.com-access_log common
<Location /server-status> # 这样我可以看到apache服务器状态
SetHandler server-status
Order deny,allow
Deny from all
Allow from localhost
Allow from www.ok.com
</Location>
</VirtualHost>
2:Tomcat虚拟主机配置
添加新的www.ok.com虚拟主机,位置在
<Engine>
<Host name=”localhost” ……>
</Host>
<Host name="www.ok.com" debug="0" appBase="D:/server/www/" unpackWARs="true" autoDeploy="true" xmlValidation="false" xmlNamespaceAware="false">
<Context path="" docBase="." />
<Logger className="org.apache.catalina.logger.FileLogger" directory="logs" prefix="ok.com_log." suffix=".txt" timestamp="true" />
</Host>
</Engine>
3:测试虚拟主机效果
访问http://localhost/ 应该可以看到原来的tomcat默认页面。
写一个 index.jsp
内容如下
<html>
<title>
test jsp
</title>
<%out.println("Hello World!");%>
</html>
放在d:/server/www下面,访问 http://www.ok.com
应该看到页面显示Hello World! 就成功了
第三部分,部分相关性能优化及其它问题
如何使用server版jvm ?
看看你下面的这两个文件,是不是尺寸差别很大?
%JAVA_HOME%/jre/bin/client/jvm.dll
%JAVA_HOME%/jre/bin/server/jvm.dll
Jvm动态库有client和server两个版本,分别针对桌面应用和服务器应用做了相应的优化,client版本加 载速度较快,server版本加载速度较慢但运行起来较快。
让Tomcat 使用Server版本的jvm吧 在开始菜单 tomcat5 ->tomcat config的java属性中 有一项 jvm路径 指向server目录下的jvm就行了。
启动速度对比一下,在我的C4.17 512M 的机器上client 版本一般在8s-16s内启动完成 server版本 在21s-26s左右启动完成。
更改默认java.exe调用的jvm.dll,这个由jvm.cfg决定。
编辑%JAVA_HOME%\jre\lib\i386\jvm.cfg
里面第一行写的是 -client 默认就是client版本 ,把第二行的-server KNOWN 放到第一行, 如下面所示
-server KNOWN
-client KNOWN
-hotspot ALIASED_TO -client
-classic WARN
-native ERROR
-green ERROR
改完保存,然后看看默认版本:
C:\java -version
java version "1.4.2_07"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2_07-b05)
Java HotSpot(TM) Server VM (build 1.4.2_07-b05, mixed mode)
看到没有 Server VM 字样?是不是很酷啊!,小心机器不够快,启动等得你疯掉 :)
关于JAVA_HOME 与CATALINA_HOME、 CLASSPATH
ClassPath 网上有人说在j2sdk1.3开始就不需要配置了,而本例中实际是不需要配置JAVA_HOME和CATALINA_HOME的,因为tomcat 以service模式启动根本不认你的java_home,当然为了让你能够在命令行运行startup.bat时也能顺利启动Tomcat,可以配置也建议配置上JAVA_HOME 与CATALINA_HOME,ClassPath就免了吧,连Resin都不需要这个了。
有关路径设置
Path=d:\server\jdk\bin;…… 放到最前,避免有多个jdk时的很多问题
关于apache2在win平台上的一个小问题
可能apache的日志中常出现类似如下的提示
[error] (730038)An operation was attempted on something that is not a socket.: winnt_accept: AcceptEx failed. Attempting to recover.
这是由于apache 使用了微软的AcceptEx()调用的缘故,禁用掉即可,此问题只会出现在win平台且apache的2.0.49和更高版本上,出现错误的大概原因是防火墙和防病毒软件所导致,导致结果也有好几种,像apache占用很高cpu资源或者网站页面无法打开,而有的网友和我测试的结果一样,发现实际没有什么影响。
可以看看官方的E文信息
http://httpd.apache.org/docs-2.0/mod/mpm_winnt.html
解决方法修改d:\server\apache\conf\httpd.conf中的mpm部分
<IfModule mpm_winnt.c>
ThreadsPerChild 250
MaxRequestsPerChild 0
Win32DisableAcceptEx #添加这一行即可,做过压力测试,对性能影响很小,可以忽略
</IfModule>
题外话
顺便说一句apache2在win平台上的性能好过apache1很多! 个人以前做过一个压力测试说明了这一点,强烈建议在win平台使用apache2的版本,有空我把那份测试结果贴上来.
是不是觉得很麻烦,其实过程很简单,只是因为加进来一些个人遇到的一些问题的经验和看法显得罗索而已。
陆续调试和书写了3个晚上,每次还弄到1-2点,没有想到写点什么这么辛苦,可能文笔较差章节混乱,各位看官见谅 :)


06年热贴
