一個nginx配置小問題


【結論】
目前的配置,可以完成基本的功能,但使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;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章