Httpd两种方案三种方式实现反向代理tomcat

时间:2024-03-08 15:29:04

目录

1、概述

2、方案一:以proxy_module方式反向代理

3、方案二:以mod_jk方式反向代理

4、总结

1、概述

    以httpd作为前端的反向代理,那有两种选择,一是利用"proxy_module"这个代理框架下的"proxy_http_module"与"proxy_ajp_module"这两个代理模块,这两个代理模块是独自工作的,二是利用“mod_jk”模块实现httpd的反向代理至后端tomcat。

2、方案一:以proxy_module方式反向代理

    在上一次博客中tomcat已能正常运行,并部署了shopxx一个测试电商站点,现在安装httpd套件并配置成能反向代理JSP请求到tomcat的场景。而我这里系统自带的httpd的rpm包是2.2版本的,而这个版本就包含了我们所需要的模块,所以就用此版本来实现我们的环境。

2.1、网站以"proxy_http_module"实现反应代理

httpd版本及模块检查:

1
2
3
4
5
6
7
8
9
10
[root@master ~]# rpm -q httpd
httpd-2.2.15-39.el6.centos.x86_64
[root@master ~]# httpd -M | grep proxy
Syntax OK
 proxy_module (shared)                    #主模块
 proxy_balancer_module (shared)
 proxy_ftp_module (shared)
 proxy_http_module (shared)   #走http协议的反向代理模块
 proxy_ajp_module (shared)    #走ajp协议的反向代理模块
 proxy_connect_module (shared)

配置httpd的配置文件,使其成为tomcat的代理服务器,这里我以虚拟主机的方式提供http服务:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[root@master ~]# vim /etc/httpd/conf/httpd.conf
#DocumentRoot "/var/www/html"    #注释掉中心主机
[root@master ~]# vim /etc/httpd/conf.d/virtual.conf  #虚拟主机我以单独的配置文件提供
<VirtualHost *:80>
    DocumentRoot /tomcat/webapps/shopxx
    ServerName test.shopxx.com
    ErrorLog logs/test.shopxx.com-error.log
    CustomLog logs/test.shopxx.com-access.log common
    ProxyVia Off
    ProxyRequests Off
    ProxyPreserveHost On
    ProxyPass / http://test.shopxx.com:8080/
    ProxyPassReverse / http://test.shopxx.com:8080/
</VirtualHost>

参数解释:

ProxyVia  {On|Off|Full|Block}:用于控制在http首部是否使用Via:,主要用于在多级代理中控制代理请求的流向。默认为Off,即不启用此功能;On表示每个请求和响应报文均添加Via:;Full表示每个Via:行都会添加当前apache服务器的版本号信息;Block表示每个代理请求报文中的Via:都会被移除。

 

ProxyRequests {On|Off}:是否开启apache正向代理的功能;启用此项时为了代理http协议必须启用mod_proxy_http模块。同时,如果为apache设置了ProxyPass,则必须将ProxyRequests设置为Off。

 

ProxyPreserveHost {On|Off}:如果启用此功能,代理会将用户请求报文中的Host:行发送给后端的服务器,而不再使用ProxyPass指定的服务器地址。如果想在反向代理中支持虚拟主机,则需要开启此项,否则就无需打开此功能。

 

ProxyPass  path  [!]|[url  [key=value key=value ...]]:将后端服务器某URL与当前服务器的某虚拟路径关联起来作为提供服务的路径,path为当前服务器上的某虚拟路径,url为后端服务器上某URL路径。使用此指令时必须将ProxyRequests的值设置为Off。需要注意的是,如果path以“/”结尾,则对应的url也必须以“/”结尾,反之亦然。

另外,mod_proxy模块在httpd 2.1的版本之后支持与后端服务器的连接池功能,连接在按需创建在可以保存至连接池中以备进一步使用。连接池大小或其它设定可以通过在ProxyPass中使用key=value的方式定义。常用的key如下所示:

min:连接池的最小容量,此值与实际连接个数无关,仅表示连接池最小要初始化的空间大小。

 max:连接池的最大容量,每个MPM都有自己独立的容量;都值与MPM本身有关,如Prefork的总是为1,而其它的则取决于ThreadsPerChild指令的值。

 loadfactor:用于负载均衡集群配置中,定义对应后端服务器的权重,取值范围为1-100。

 retry:当apache将请求发送至后端服务器得到错误响应时等待多长时间以后再重试。单位是秒钟。

点击这里有更详细的说明:http://httpd.apache.org/docs/2.2/mod/mod_proxy.html#proxypass

 

配置文件修改好后启动httpd服务:

1
2
3
[root@master ~]# httpd -t
Syntax OK
[root@master ~]# service httpd start

访问主页,查看日志文件:

打开chrome浏览器,输入http://test.shopxx.com访问主页,如果之前访问过可按住“ctrl”键再按“F5”就可以绕过本地缓存直接从服务器取数据。

1
2
3
4
5
6
7
8
9
10
11
[root@master ~]# tail -20 /usr/local/tomcat/logs/test_access_log.2015-04-29.txt
####截取部份####
192.168.0.201 - - [29/Apr/2015:14:59:40 +0800] "GET / HTTP/1.1" 200 8432
192.168.0.201 - - [29/Apr/2015:14:59:40 +0800] "GET /shopxx/resources/shop/slider/slider.css HTTP/1.1" 200 633
192.168.0.201 - - [29/Apr/2015:14:59:40 +0800] "GET /shopxx/resources/shop/css/index.css HTTP/1.1" 200 1553
192.168.0.201 - - [29/Apr/2015:14:59:40 +0800] "GET /shopxx/resources/shop/js/jquery.tools.js HTTP/1.1" 200 3932
192.168.0.201 - - [29/Apr/2015:14:59:40 +0800] "GET /shopxx/resources/shop/css/common.css HTTP/1.1" 200 3603
192.168.0.201 - - [29/Apr/2015:14:59:40 +0800] "GET /shopxx/resources/shop/js/jquery.js HTTP/1.1" 200 33471
192.168.0.201 - - [29/Apr/2015:15:00:00 +0800] "GET /shopxx/resources/shop/js/common.js HTTP/1.1" 200 3103
192.168.0.201 - - [29/Apr/2015:15:00:00 +0800] "GET /shopxx/resources/shop/slider/slider.js HTTP/1.1" 200 3033
192.168.0.201 - - [29/Apr/2015:15:00:00 +0800] "GET /upload/image/logo.gif HTTP/1.1" 200 3445

仔细观察日志文件,第一列的IP地址就是本机的IP,并不是我发起访问主页的主机地址,因为做反向代理后访问tomcat的就只有前端的httpd进程,而httpd与tomcat在这里是同一主机,所以这里记录的就是本机的IP地址。再看请求的各个资源,有以下几类:.css、.js、.gif结尾的这三类,从后缀可推断这都是静态资源,从网站系统架构上讲这些静态文件是不应该让tomcat容器来响应的,从另一方面也说明一个网站的主页在设计上最好不要有动态资源的请求,因为静态资源的请求时间会远远短于动态资源请求的时间,这样主页打开的速度会更快。

在shopxx的主页随便点击几个链接,再来观察tomcat的日志文件:

1
2
3
4
5
6
7
8
9
10
11
[root@master ~]# tail /usr/local/tomcat/logs/test_access_log.2015-04-29.txt
192.168.0.201 - - [29/Apr/2015:14:59:40 +0800] "GET /shopxx/resources/shop/css/common.css HTTP/1.1" 200 3603
192.168.0.201 - - [29/Apr/2015:14:59:40 +0800] "GET /shopxx/resources/shop/js/jquery.js HTTP/1.1" 200 33471
192.168.0.201 - - [29/Apr/2015:15:00:00 +0800] "GET /shopxx/resources/shop/js/common.js HTTP/1.1" 200 3103
192.168.0.201 - - [29/Apr/2015:15:00:00 +0800] "GET /shopxx/resources/shop/slider/slider.js HTTP/1.1" 200 3033
192.168.0.201 - - [29/Apr/2015:15:00:00 +0800] "GET /upload/image/logo.gif HTTP/1.1" 200 3445
192.168.0.201 - - [29/Apr/2015:15:00:20 +0800] "GET /shopxx/resources/shop/images/common.gif HTTP/1.1" 200 5937
192.168.0.201 - - [29/Apr/2015:15:00:20 +0800] "GET /shopxx/resources/shop/images/index.gif HTTP/1.1" 200 4972
192.168.0.201 - - [29/Apr/2015:15:09:05 +0800] "GET /product/list/2.jhtml HTTP/1.1" 200 6674
192.168.0.201 - - [29/Apr/2015:15:09:05 +0800] "GET /resources/shop/js/common.js HTTP/1.1" 200 3103
192.168.0.201 - - [29/Apr/2015:15:09:28 +0800] "GET /product/list/3.jhtml HTTP/1.1" 200 5861

观察最后三行,可知这个网站的动态页面的后缀是jhtml结尾的,可不是jsp。

从tomcat日志输出中我们得到了做动静分离非常有用的信息如下:

a、静态文件(以.css、.js、..gif)存放目录,

b、动态文件的后缀是jhtml

2.2、网站动静分离实现

配置httpd配置文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[root@master ~]# vim /etc/httpd/conf.d/virtual.conf
<VirtualHost *:80>
    DocumentRoot /tomcat/webapps/shopxx
    ServerName test.shopxx.com
    ErrorLog logs/test.shopxx.com-error.log
    CustomLog logs/test.shopxx.com-access.log common
    ProxyVia Off
    ProxyRequests Off
    ProxyPreserveHost On
    ProxyPass /resources/shop/css !   #新增加
    ProxyPass /resources/shop/js !   #新增加
    ProxyPass /resources/shop/images !   #新增加
    ProxyPass /upload/image !     #新增加
    ProxyPass / http://test.shopxx.com:8080/
    ProxyPassReverse / http://test.shopxx.com:8080/
</VirtualHost>

#因"DocumentRoot /tomcat/webapps/shopxx"已指向了“shopxx”目录,所以增加的参数中去掉了开头的“/shopxx”,新增加的这几行表示这些目录不会转发到后端的tomcat上,只在本地进行处理。

重新启动httpd服务:

1
[root@master ~]# service httpd restart

用chrome绕过缓存再次打开主页,能正常打开,如下图:

wKiom1VIEHegxlrcAAIYGeotvPE167.jpg

点击主页中的各个链接,也都能正常的打开。

接下来验证动静分离,查看tomcat访问日志文件,如果没有处理静态资源,那就说明tomcat只是在处理动态页面,那从反面也证明了静态页面在前端被httpd处理了。

查看tomcat访问日志文件:

1
2
3
4
5
6
7
8
9
10
11
[root@master ~]# tail  /usr/local/tomcat/logs/test_access_log.2015-04-29.txt
192.168.0.201 - - [29/Apr/2015:16:11:53 +0800] "GET /shopxx/resources/shop/slider/slider.css HTTP/1.1" 200 633
192.168.0.201 - - [29/Apr/2015:16:11:53 +0800] "GET /shopxx/resources/shop/js/jquery.tools.js HTTP/1.1" 200 3932
192.168.0.201 - - [29/Apr/2015:16:11:53 +0800] "GET /shopxx/resources/shop/js/jquery.js HTTP/1.1" 200 33471
192.168.0.201 - - [29/Apr/2015:16:12:13 +0800] "GET /shopxx/resources/shop/slider/slider.js HTTP/1.1" 200 3033
192.168.0.201 - - [29/Apr/2015:16:12:13 +0800] "GET /shopxx/resources/shop/js/common.js HTTP/1.1" 200 3103
192.168.0.201 - - [29/Apr/2015:16:12:33 +0800] "GET /shopxx/resources/shop/images/common.gif HTTP/1.1" 200 5937
192.168.0.201 - - [29/Apr/2015:16:12:33 +0800] "GET /shopxx/resources/shop/images/index.gif HTTP/1.1" 200 4972
192.168.0.201 - - [29/Apr/2015:16:13:30 +0800] "GET /product/list/1.jhtml HTTP/1.1" 200 6820
192.168.0.201 - - [29/Apr/2015:16:13:30 +0800] "GET /product/list/2.jhtml HTTP/1.1" 200 6674
192.168.0.201 - - [29/Apr/2015:16:13:31 +0800] "GET /product/list/3.jhtml HTTP/1.1" 200 5861

仔细观察日志,你会发现tomcat静态页面、动态页面都在处理,所以动静分离并没有成功。

再查看httpd的访问日志:

1
2
3
4
5
6
7
8
9
10
11
[root@master ~]# tail /var/log/httpd/test.shopxx.com-access.log
192.168.0.102 - - [29/Apr/2015:16:11:53 +0800] "GET /shopxx/resources/shop/css/common.css HTTP/1.1" 200 3603
192.168.0.102 - - [29/Apr/2015:16:11:53 +0800] "GET /shopxx/resources/shop/js/jquery.js HTTP/1.1" 200 33471
192.168.0.102 - - [29/Apr/2015:16:12:13 +0800] "GET /shopxx/resources/shop/slider/slider.js HTTP/1.1" 200 3033
192.168.0.102 - - [29/Apr/2015:16:12:13 +0800] "GET /shopxx/resources/shop/js/common.js HTTP/1.1" 200 3103
192.168.0.102 - - [29/Apr/2015:16:12:33 +0800] "GET /shopxx/resources/shop/images/index.gif HTTP/1.1" 200 4972
192.168.0.102 - - [29/Apr/2015:16:12:33 +0800] "GET /shopxx/resources/shop/images/common.gif HTTP/1.1" 200 5937
192.168.0.102 - - [29/Apr/2015:16:13:30 +0800] "GET /product/list/1.jhtml HTTP/1.1" 200 6820
192.168.0.102 - - [29/Apr/2015:16:13:30 +0800] "GET /resources/shop/js/common.js HTTP/1.1" 304 -
192.168.0.102 - - [29/Apr/2015:16:13:30 +0800] "GET /product/list/2.jhtml HTTP/1.1" 200 6674
192.168.0.102 - - [29/Apr/2015:16:13:31 +0800] "GET /product/list/3.jhtml HTTP/1.1" 200 5861

仔细查看httpd的日志,似乎发现哪里不对,在virtual.conf配置文件中"DocumentRoot /tomcat/webapps/shopxx",但日志中怎么访问资源时还在开头带了“/shopxx”,如果访问过程是这样,那我们在virtual.conf中配置的过虑规则就要有所修改才行。

修改virtual.conf文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[root@master ~]# vim /etc/httpd/conf.d/virtual.conf
<VirtualHost *:80>
    DocumentRoot /tomcat/webapps    #第一处修改
    ServerName test.shopxx.com
    ErrorLog logs/test.shopxx.com-error.log
    CustomLog logs/test.shopxx.com-access.log common
    ProxyVia Off
    ProxyRequests Off
    ProxyPreserveHost On
    ProxyPass /shopxx/resources/shop/css !   #第二处修改
    ProxyPass /shopxx/resources/shop/js !  #第三处修改
    ProxyPass /shopxx/resources/shop/images !  #第四处修改
    ProxyPass /shopxx/resources/shop/slider !  #第五处修改
    ProxyPass /shopxx/upload/image !  #第六处修改
    ProxyPass / http://test.shopxx.com:8080/
    ProxyPassReverse / http://test.shopxx.com:8080/
</VirtualHost>

注意:这次修改的地方可不只是在各个静态资源路径前加上“/shopxx”,一定不要忘记把“DocumentRoot /tomcat/webapps/shopxx ”修改成“DocumentRoot /tomcat/webapps ”,为什么?因为如果不修改那httpd在处理静态页面时它会去“/tomcat/webapps/shopxx/shopxx/resources/shop/css......”这样的路径去找,显然路径是不对的。

再次重启httpd服务后去访问主页,再去验证动静是否已分离:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
[root@master ~]# service httpd restart
[root@master ~]# tail /usr/local/tomcat/logs/test_access_log.2015-04-29.txt
192.168.0.201 - - [29/Apr/2015:17:13:17 +0800] "GET /shopxx/product/hits/200.jhtml HTTP/1.1" 200 36
192.168.0.201 - - [29/Apr/2015:17:14:17 +0800] "GET /shopxx/ HTTP/1.1" 200 8432
192.168.0.201 - - [29/Apr/2015:17:14:20 +0800] "GET / HTTP/1.1" 200 8432
192.168.0.201 - - [29/Apr/2015:17:14:21 +0800] "GET / HTTP/1.1" 200 8432
192.168.0.201 - - [29/Apr/2015:17:14:21 +0800] "GET /upload/image/logo.gif HTTP/1.1" 200 3445
192.168.0.201 - - [29/Apr/2015:17:14:42 +0800] "GET /product/list/1.jhtml HTTP/1.1" 200 6820
192.168.0.201 - - [29/Apr/2015:17:14:42 +0800] "GET /product/list/2.jhtml HTTP/1.1" 200 6674
192.168.0.201 - - [29/Apr/2015:17:14:43 +0800] "GET /product/list/3.jhtml HTTP/1.1" 200 5861
192.168.0.201 - - [29/Apr/2015:17:14:43 +0800] "GET /product/list/4.jhtml HTTP/1.1" 200 4698
192.168.0.201 - - [29/Apr/2015:17:14:45 +0800] "GET /product/list/2.jhtml HTTP/1.1" 200 6674
#看上边的日志,网站的logo.gif这个图片还是发到tomcat上来处理了。
[root@master ~]# tail -15 /var/log/httpd/test.shopxx.com-access.log
192.168.0.102 - - [29/Apr/2015:17:14:21 +0800] "GET /shopxx/resources/shop/js/jquery.tools.js HTTP/1.1" 200 10663
192.168.0.102 - - [29/Apr/2015:17:14:21 +0800] "GET /shopxx/resources/shop/js/common.js HTTP/1.1" 200 9247
192.168.0.102 - - [29/Apr/2015:17:14:21 +0800] "GET /shopxx/resources/shop/slider/slider.js HTTP/1.1" 200 11561
192.168.0.102 - - [29/Apr/2015:17:14:21 +0800] "GET /shopxx/resources/shop/js/jquery.js HTTP/1.1" 200 93637
192.168.0.102 - - [29/Apr/2015:17:14:21 +0800] "GET /upload/image/logo.gif HTTP/1.1" 200 3445
192.168.0.102 - - [29/Apr/2015:17:14:21 +0800] "GET /shopxx/resources/shop/images/index.gif HTTP/1.1" 200 4972
192.168.0.102 - - [29/Apr/2015:17:14:21 +0800] "GET /shopxx/resources/shop/images/common.gif HTTP/1.1" 200 5937
192.168.0.102 - - [29/Apr/2015:17:14:17 +0800] "GET /shopxx/ HTTP/1.1" 200 8432
192.168.0.102 - - [29/Apr/2015:17:14:20 +0800] "GET / HTTP/1.1" 200 8432
192.168.0.102 - - [29/Apr/2015:17:14:21 +0800] "GET / HTTP/1.1" 200 8432
192.168.0.102 - - [29/Apr/2015:17:14:42 +0800] "GET /product/list/1.jhtml HTTP/1.1" 200 6820
192.168.0.102 - - [29/Apr/2015:17:14:42 +0800] "GET /product/list/2.jhtml HTTP/1.1" 200 6674
#看到“/upload/image/logo.gig”这一行了吧,好奇怪这个资源没有“/shopxx”开头,这样的话,那virtual.conf里的过虑规则就过虑不掉它了,如果过虑规则修改成“ProxyPass /upload/image !  ”,那logo.gif这个图片在主页上无法显示,这个问题一直没办法排除,但动静分离还是几乎实现了,除了这个logo.gif外。

2.3、网站以"proxy_ajp_module"实现反应代理

在以httpd来反向代理tomcat的架构中,除了支持http协议外,还支持ajp(apache jserv protocol)协议,默认时tomcat监听在ajp的8009端口上。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[root@master ~]# vim /etc/httpd/conf.d/virtual.conf
<VirtualHost *:80>
    DocumentRoot /tomcat/webapps
    ServerName test.shopxx.com
    ErrorLog logs/test.shopxx.com-error.log
    CustomLog logs/test.shopxx.com-access.log common
    ProxyVia Off
    ProxyRequests Off
    ProxyPreserveHost On
    ProxyPass /shopxx/resources/shop/css !
    ProxyPass /shopxx/resources/shop/js !
    ProxyPass /shopxx/resources/shop/images !
    ProxyPass /shopxx/resources/shop/slider !
    ProxyPass /shopxx/upload/image !
    ProxyPass / ajp://test.shopxx.com:8009/   #修改一
    ProxyPassReverse / ajp://test.shopxx.com:8009/   #修改二
</VirtualHost>

重启httpd服务后,网站依然能够正常访问。

3、方案二:以mod_jk方式反向代理

    mod_jk是一个工作于apache端基于AJP协议与Tomcat通信的连接器,它是apache的一个模块,是AJP协议的客户端(服务端是Tomcat的AJP连接器),这个模块默认没有被编译进系统自带的rpm包,所以要自己编译这个连接器。下载地址:http://tomcat.apache.org/download-connectors.cgi,而要把模块编译进httpd需要httpd-devel环境,如果没有安装此环境,请用“yum -y install httpd-devel”安装。

3.1、mod_jk模块编译安装

1
2
3
4
5
6
7
8
9
[root@master software]# tar xf tomcat-connectors-1.2.40-src.tar.gz
[root@master software]# cd tomcat-connectors-1.2.40-src
[root@master tomcat-connectors-1.2.40-src]# ls
conf  docs  HOWTO-RELEASE.txt  jkstatus  LICENSE  native  NOTICE  README.txt  support  tools  xdocs
[root@master tomcat-connectors-1.2.40-src]# cd native/
[root@master native]# ./configure --with-apxs=/usr/sbin/apxs
[root@master native]# make && make install
[root@master native]# ls /usr/lib64/httpd/modules/ | grep mod_jk   #安装好后模块生成
mod_jk.so

3.2、基于mod_jk的配置

1
2
3
[root@master conf.d]# pwd 
/etc/httpd/conf.d
[root@master conf.d]# mv virtual.conf virtual.conf.back  #先把基于proxy_moduel反向代理tomcat的配置文件禁用掉

再去启用/etc/httpd/conf/http.conf主配置文件中的中心主机,即启用“DocumentRoot /var/www/html”

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[root@master conf.d]# vim mod_jk.conf
LoadModule jk_module modules/mod_jk.so
JkWorkersFile /etc/httpd/conf.d/workers.properties
JkMountFile /etc/httpd/conf.d/uriworkermap.properties
JkLogFile logs/mod_jk.log
JkLogLevel warn   #在调试时可设置为debug
[root@master conf.d]# vim workers.properties 
worker.list=TomcatA,statA
worker.TomcatA.host=192.168.0.201
worker.TomcatA.port=8009
worker.TomcatA.type=ajp13
worker.TomcatA.lbfactor=1
worker.statA.type=status
[root@master conf.d]# vim uriworkermap.properties 
/*=TomcatA
/jkstatus=statA

编辑tomcat主配置文件:

1
2
3
4
5
6
[root@master conf.d]# vim /usr/local/tomcat/conf/server.xml  #在Engine中最后加上“jvmRoute=TomcatA”
...略...
<Engine name="Catalina" defaultHost="localhost" jvmRoute=TomcatA>
...略...
[root@master conf.d]# service httpd restart
[root@master conf.d]# service tomcat restart

重启服务后,网站也可正常访问,但这里没有涉及到站点动静分离。

访问http://test.shopxx.com/jkstatus即可访问到监控界面,如下图:

wKioL1VIEhPCqkQvAAMlXLTe4OM640.jpg

4、总结

用apache来做反向代理后端的tomcat,有两种方案三种方式,一种方案是利用proxy_module模块,这种方案又支持http和ajp两种协议,而另一种方案是单独采用mode_jk连接器实现采用ajp协议与后端的tomcat进行连接。shopxx这个webapp有点诡异,在访问日志中老是会发现“/shopxx”这样开头的路径,但在“DocumentRoot”中已指定到了“/tomcat/webapps/shopxx”,所以在做动静分离时会有一定的困难,上边在用mode_jk做反向代理时我没有实现网站的动静分离,得再研究一下。