说明:
nginx处理静态内容是把好手,apache虽然占用内存多了点,性能上稍逊,但一直比较稳健。倒是nginx的FastCGI有时候会出现502 Bad Gateway错误。一个可选的方法是nginx做前端代理,处理静态内容,动态请求统统转发给后端apache。
本文就是实现Nginx作为前端,apache作为后端。当用户访问的是80端口的nginx,然后nginx将静态内容留给自己,其余的转发给非80端口的apache,apache处理完毕后再回传给nginx。例如这里我分别访问www.test.com/a.html,www.test.com/info.php。nginx因为做前面,nginx的访问日志应该都有a.html,info.php的记录;而apache作为后端,只处理php请求,应该只有info.php的访问记录。

实现:
1.修改nginx配置文件,将php动态请求转发给apache

# cat /usr/local/nginx/conf/vhosts/test.conf


server


{


    listen       80;


    server_name www.test.com test.com;


    index index.html index.htm index.php default.html default.htm default.php;


    root  /home/www/data/test;


    access_log  /usr/local/nginx/logs/test-access.log;


    # nginx找不到文件时,转发请求给后端Apache


    error_page 404 @proxy;


    # 这是原来lnmp时,nginx自己将php请求提交到127.0.0.1:9000。现在由apache来处理,因此注释掉这段。


    #location ~ .*\.(php|php5)?$


    #{


    #    fastcgi_pass  127.0.0.1:9000;


    #    fastcgi_index index.php;


    #    include fastcgi.conf;


    #}


    location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$


    {


        expires      30d;


    }


    location ~ .*\.(js|css)?$


    {


        expires      12h;


    }


    # 动态文件.php请求转发给后端Apache


    location ~ \.php$ {


        # 向后端服务器发起请求时添加指定的header头信息


        proxy_set_header Host $http_host;


        # 向后端服务器发送真实 IP


        proxy_set_header X-Real-IP $remote_addr;


        # 让后端如php能直接通过变量获取真实IP


        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;


        proxy_pass   http://127.0.0.1:8080;


    }


    # nginx找不到文件时,转发请求给后端Apache


    location @proxy {


        proxy_set_header Host $http_host;


        proxy_set_header X-Real-IP $remote_addr;


        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;


        proxy_pass http://127.0.0.1:8080;


    }


}


 
然后只要开启nginx监听80端口,apache监听8080端口,开启php,就可以了。这边,我同时开启nginx,apache的访问日志。当我访问www.test.com/a.html,www.test.com/info.php时,nginx记录下了所有a.html,info.html的访问请求。
nginx访问日志

192.168.45.30 - - [19/Jun/2013:14:41:06 +0800] "GET /a.html HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.110 Safari/537.36"


192.168.45.30 - - [19/Jun/2013:14:41:06 +0800] "GET /favicon.ico HTTP/1.1" 404 209 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.110 Safari/537.36"


192.168.45.30 - - [19/Jun/2013:14:41:08 +0800] "GET /info.php HTTP/1.1" 200 10518 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.110 Safari/537.36"


192.168.45.30 - - [19/Jun/2013:14:41:08 +0800] "GET /info.php?=PHPE9568F35-D428-11d2-A769-00AA001ACF42 HTTP/1.1" 200 2158 "http://www.test.com/info.php" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.110 Safari/537.36"


192.168.45.30 - - [19/Jun/2013:14:41:08 +0800] "GET /info.php?=PHPE9568F34-D428-11d2-A769-00AA001ACF42 HTTP/1.1" 200 2536 "http://www.test.com/info.php" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.110 Safari/537.36"


192.168.45.30 - - [19/Jun/2013:14:41:08 +0800] "GET /favicon.ico HTTP/1.1" 404 209 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.110 Safari/537.36"


192.168.45.30 - - [19/Jun/2013:14:41:09 +0800] "GET /info.php HTTP/1.1" 200 10518 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.110 Safari/537.36"


 
当我访问www.test.com/a.html,www.test.com/info.php时,apache只记录了info.html的访问请求。说明nginx将php请求转发给了apache。这里可以看到来源都是127.0.0.1。而不是真实的来源ip。
apache访问日志

127.0.0.1 - - [19/Jun/2013:11:04:16 +0800] "GET /favicon.ico HTTP/1.0" 404 209


127.0.0.1 - - [19/Jun/2013:11:04:23 +0800] "GET /favicon.ico HTTP/1.0" 404 209


127.0.0.1 - - [19/Jun/2013:11:04:31 +0800] "GET /favicon.ico HTTP/1.0" 404 209


127.0.0.1 - - [19/Jun/2013:11:04:34 +0800] "GET /favicon.ico HTTP/1.0" 404 209


127.0.0.1 - - [19/Jun/2013:11:04:39 +0800] "GET /favicon.ico HTTP/1.0" 404 209


127.0.0.1 - - [19/Jun/2013:11:05:09 +0800] "GET /favicon.ico HTTP/1.0" 404 209


127.0.0.1 - - [19/Jun/2013:11:05:18 +0800] "GET /favicon.ico HTTP/1.0" 404 209


127.0.0.1 - - [19/Jun/2013:11:05:24 +0800] "GET /info.php HTTP/1.0" 200 55447


127.0.0.1 - - [19/Jun/2013:11:05:24 +0800] "GET /info.php?=PHPE9568F34-D428-11d2-A769-00AA001ACF42 HTTP/1.0" 200 2524


127.0.0.1 - - [19/Jun/2013:11:05:24 +0800] "GET /info.php?=PHPE9568F35-D428-11d2-A769-00AA001ACF42 HTTP/1.0" 200 2146


127.0.0.1 - - [19/Jun/2013:11:05:24 +0800] "GET /favicon.ico HTTP/1.0" 404 209


 
2.apache添加mod_rpaf, 获取nginx转发过来的真实IP
mod_rpaf模块不是必须安装,除非你需要开启apache日志,但有多此一举之嫌,因为已经有nginx日志了,再开apache日志话就出现重复了。
Apache rpaf模块作用是获取Nginx转发过来的真实IP,否则在Apache日子中来访IP全部为127.0.0.1。

# wget http://stderr.net/apache/rpaf/download/mod_rpaf-0.6.tar.gz


# tar zxvf mod_rpaf-0.6.tar.gz


# cd mod_rpaf-0.6


# /usr/local/www/apache/bin/apxs -i -c -n mod_rpaf-2.0.so mod_rpaf-2.0.c


安装过程中,若出现error: 'conn_rec' has no member named 'remote_ip,请参考附录1.mod_rpaf-2.0.c error: 'conn_rec' has no member named 'remote_ip
 

# vim /usr/local/apache/conf/httpd.conf  //在LoadModule后添加以下内容


LoadModule rpaf_module modules/mod_rpaf-2.0.so


RPAFenable On


RPAFproxy_ips 127.0.0.1


RPAFsethostname On


RPAFheader X-Forwarded-For


 
下面是apache添加了mod_rpaf模块后,apache的访问日志

192.168.45.30 - - [19/Jun/2013:14:41:09 +0800] "GET /info.php?=PHPE9568F35-D428-11d2-A769-00AA001ACF42 HTTP/1.1" 200 2158 "http://www.test.com/info.php" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.110 Safari/537.36"


192.168.45.30 - - [19/Jun/2013:14:41:09 +0800] "GET /info.php?=PHPE9568F34-D428-11d2-A769-00AA001ACF42 HTTP/1.1" 200 2536 "http://www.test.com/info.php" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.110 Safari/537.36"


192.168.45.30 - - [19/Jun/2013:14:41:09 +0800] "GET /favicon.ico HTTP/1.1" 404 209 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.110 Safari/537.36"


192.168.45.30 - - [19/Jun/2013:14:41:09 +0800] "GET /info.php HTTP/1.1" 200 10520 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.110 Safari/537.36"


192.168.45.30 - - [19/Jun/2013:14:41:09 +0800] "GET /info.php?=PHPE9568F34-D428-11d2-A769-00AA001ACF42 HTTP/1.1" 200 2536 "http://www.test.com/info.php" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.110 Safari/537.36"


 
附录:
附录1.mod_rpaf-2.0.c error: 'conn_rec' has no member named 'remote_ip

mod_rpaf-2.0.c: In function 'rpaf_cleanup':
mod_rpaf-2.0.c:150: error: 'conn_rec' has no member named 'remote_ip'
mod_rpaf-2.0.c:151: error: 'conn_rec' has no member named 'remote_addr'
mod_rpaf-2.0.c:151: warning: implicit declaration of function 'inet_addr'
mod_rpaf-2.0.c:151: error: 'conn_rec' has no member named 'remote_ip'
mod_rpaf-2.0.c: In function 'change_remote_ip':
mod_rpaf-2.0.c:164: error: 'conn_rec' has no member named 'remote_ip'
mod_rpaf-2.0.c:183: error: 'conn_rec' has no member named 'remote_ip'
mod_rpaf-2.0.c:186: error: 'conn_rec' has no member named 'remote_ip'
mod_rpaf-2.0.c:187: error: 'conn_rec' has no member named 'remote_addr'
mod_rpaf-2.0.c:187: error: 'conn_rec' has no member named 'remote_ip'
apxs:Error: Command failed with rc=65536
只要将mod_rpaf-2.0.c的150、151、164、183、186、187这几行的remote_ip修改成client_ip,remote_addr修改成client_addr,
然后再/usr/local/www/apache/bin/apxs -i -c -n mod_rpaf-2.0.so mod_rpaf-2.0.c即可