【結論】
目前的配置,可以完成基本的功能,但使nginx要處理的請求的數量,增加了一倍(下面詳述),所以,要儘可能避免像目前這樣配置,可以有更合適的配置。
【要實現的功能】
使客戶端發起的類似http://cq01-testing-ibase11.vm.baidu.com:8080/lightapp/1767031這樣的請求,首先變成http://cq01-testing-ibase11.vm.baidu.com:8080/lightapp/locate/1767031這樣,然後再由php-fcgi處理。
【目前的配置】
在rewrites.conf中,增加兩條重寫規則,依次如下:
rewrite ^/lightapp/([0-9]+)$ /lightapp/locate/$1 last;
rewrite ^/lightapp(/.*)$ /phpsrc/lightapp/index.php last;
在php.conf中,增加一個location:
location ^~ /lightapp/ {
proxy_pass http://127.0.0.1:8080;
break;
}
這樣配置的問題,如開頭所述。即當客戶端發起一個請求時,nginx爲完成客戶端的請求,實際處理了兩個完整的請求。這兩個請求的區別是,一個來自客戶端,最後把請求代理到本機8080端口上的進程,也就是nginx;一個來自nginx所在的機器,最後把請求代理到php-fcgi。總之,nginx工作量增加了一倍。
【更好的配置】
在rewrites.conf中,只增加一條重寫規則,即上面的第一條重寫規則:
rewrite ^/lightapp/([0-9]+)$ /lightapp/locate/$1 last;
在php.conf中,有兩種配置方式,第一種如下:
location ^~ /lightapp/ {
fastcgi_pass fpm_us;
include fastcgi_params;
fastcgi_param REQUEST_URI $uri; #重點在這裏
fastcgi_param SCRIPT_FILENAME $document_root/phpsrc/lightapp/index.php;
break;
}
思路就是,讓客戶端發給nginx的請求,經nginx server rewrite後,直接請求php-fcgi,以此來避免第二次相同的請求。
但這種配置的一個問題是,當有很多類似的需求時,就需要多次重複寫上面的nginx fastcgi module的指令,很不方面。所以,有了下面的第二種配置方式:
在nginx.conf或者php.conf中,http {}內、所有server {}外:
map $kw $my_script {
default /phpsrc/developer/index.php;
lightapp /phpsrc/lightapp/index.php;
}
location ^~ /lightapp/ {
set $kw lightapp;
try_files $uri @normalized_request_uri;
}
#以下named location可以重用
location @normalized_request_uri {
fastcgi_pass fpm_us;
include fastcgi_params;
fastcgi_param REQUEST_URI $uri;
fastcgi_param SCRIPT_FILENAME $document_root$my_script;
break;
}
【其他】
乍一想,用nginx的rewrite指令,或者ngx_lua的ngx.exec或ngx.location.capture等api,可以有看似更簡單的配置方式,這些配置方式我不一一列舉了。但由於以下原因,這些配置方式其實都不可行:
1) 最根本的,nginx的$request_uri變量是read-only的
2) rewrite的第一個參數,依據是raw uri,而不是normalized uri;而location依據的是normalized uri
3) 在fastcgi_params配置文件中,把fcgi的環境變量REQUEST_URI的值,寫死了爲nignx的$request_uri變量的值。這滿足絕大多數的需求和場景
4) 在php程序中,用了$_SERVER['REQUEST_URI']來取得請求的uri,這其實是很合理的
-----------------------
【臨時方案】
好處是,新增配置語句簡單,好理解;壞處是,擴展性很差。
在rewrites.conf中,只需要以下這一句配置,多餘的去掉:
rewrite ^/lightapp/([0-9]+)$ /lightapp/locate/$1 last;
在php.conf中,增加以下配置語句:
location ^~ /lightapp/ {
fastcgi_pass fpm_us;
include fastcgi_params;
fastcgi_param REQUEST_URI $uri; #重點在這裏
fastcgi_param SCRIPT_FILENAME $document_root/phpsrc/lightapp/index.php;
break;
}
【長期方案】
好處是,擴展性好;壞處是,增加的配置語句多(但僅僅是這一次多,以後就簡單了),複雜。
在rewrites.conf中,只需要以下這一句配置,多餘的去掉:
rewrite ^/lightapp/([0-9]+)$ /lightapp/locate/$1 last;
在nginx.conf中,http {} block內,增加以下配置語句:
map $kw $my_script {
default /phpsrc/developer/index.php;
lightapp /phpsrc/lightapp/index.php;
}
在php.conf中,第一個server {} block內(即目前的php.conf中,最重要的那個server block),增加以下配置語句:
location ^~ /lightapp/ {
set $kw lightapp;
try_files $uri @normalized_request_uri;
}
#以下named location可以重用
location @normalized_request_uri {
fastcgi_pass fpm_us;
include fastcgi_params;
fastcgi_param REQUEST_URI $uri;
fastcgi_param SCRIPT_FILENAME $document_root$my_script;
break;
}