nginx配置遇到的一個大坑


鄙人負責的項目即將上線,今天團隊伙伴反應網站上的圖片,有的可以顯示有的不可以顯示報404,找我看看問題。

 

我心想啊,404,應該是沒有文件才出的,於是,我直接上nginx服務器上查看,檢查路徑下是否有相應的文件,文件是存在的。那為何還是報404呢????

 

一時間,我也覺得非常的奇怪,這種問題還是頭一回呢。。。。

問題的現象如下圖:

但是,我再136這個服務器上的相關路徑下找了文件:

 

僅僅這個,大伙可能還覺得不能說明問題,我的nginx配置如下:

 1 。。。。 此前的部分省略了。。。。
 2         location /uploadfiles {
 3              root html/TK_ROOT;
 4              allow all;
 5          }
 6 
 7          #shi suan shihuc added 2017-01-20
 8          rewrite ^/product/src/(.*)$ /pc/src/$1;
 9          rewrite ^/product/dist/(.*)$ /pc/dist/$1;
10          location ~ /(pc|hera_insure) {
11              proxy_pass http://10.137.146.93:80;
12              proxy_set_header Host $host:$server_port;
13              proxy_set_header Remote_Addr $remote_addr;
14              proxy_set_header X-Real-IP $remote_addr;
15              proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
16              proxy_intercept_errors on;
17          }
18 。。。。此后的部分省略了。。。。

上面圖片報404了,但是在nginx的logs目錄下的error.log中卻找不到錯誤記錄,這個就是非常奇怪的事情了。。。。

莫非,莫非這個url的請求沒有進入這個服務器的worker進程處理,莫非真是這樣,不知道,猜測的,猜測!

 

我的配置,關於uploadfiles的目錄關系是沒有問題的。因為其他的文件顯示是正常的,例如下面的:

我再次測試正常的圖片,將圖片改一個擴展名(png-》pngx),就上圖,效果如下圖:

重點看紅框中的nginx版本號信息,這個信息是我找到問題root cause的關鍵。因為我的nginx系統軟件版本就是1.9的,還記得最上面那個圖么,錯誤版本號是1.7

1 [nginx@t0-xxxxxx-nginx01 sbin]$ sudo ./nginx -V
2 [sudo] password for nginx:
3 nginx version: openresty/1.9.3.2
4 built by gcc 4.4.7 20120313 (Red Hat 4.4.7-16) (GCC)
5 built with OpenSSL 1.0.1e-fips 11 Feb 2013
6 TLS SNI support enabled
7 configure arguments: --prefix=/u02/nginx//nginx --with-cc-opt=-O2 --add-module=../ngx_devel_kit-0.2.19 --add-module=../echo-nginx-module-0.58 --add-module=../xss-nginx-module-0.05 --add-module=../ngx_coolkit-0.2rc3 --add-module=../set-misc-nginx-module-0.29 --add-module=../form-input-nginx-module-0.11 --add-module=../encrypted-session-nginx-module-0.04 --add-module=../srcache-nginx-module-0.30 --add-module=../ngx_lua-0.9.19 --add-module=../ngx_lua_upstream-0.04 --add-module=../headers-more-nginx-module-0.28 --add-module=../array-var-nginx-module-0.04 --add-module=../memc-nginx-module-0.16 --add-module=../redis2-nginx-module-0.12 --add-module=../redis-nginx-module-0.3.7 --add-module=../rds-json-nginx-module-0.14 --add-module=../rds-csv-nginx-module-0.07 --with-ld-opt=-Wl,-rpath,/u02/nginx/luajit/lib --add-module=/u02/nginx/install/nginx-sticky-module-master --with-http_ssl_module
8 [nginx@t0-xxxxxx-nginx01 sbin]$

 

是不是很神奇,哪里來的版本1.7的nginx呢????

 

問題一定出在nginx的配置上了,回到nginx.conf文件,這個1.7的版本,應該來自反向代理服務器。基於這個分析,就想到了反向代理服務的配置,重點在下面的這部分:

1          location ~ /(pc|hera_insure) {
2              proxy_pass http://10.137.146.93:80;
3              proxy_set_header Host $host:$server_port;
4              proxy_set_header Remote_Addr $remote_addr;
5              proxy_set_header X-Real-IP $remote_addr;
6              proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
7              proxy_intercept_errors on;
8          }

 

的確,我發現出現錯誤的圖片的名稱是以pc字符開頭的。。。

歐了,問題就是發生在這里,在nginx中有這么一個規則,location后面~的優先級高於什么都不寫的模式(局部匹配),即location ~ /(pc|hera_insure) 這個匹配規則優先級高於 location /uploadfiles這個規則。

 

我們期望URL中以/uploadfiles起始的請求都進入到 location /uploadfiles規則, 以/pc開頭或者/hera_insure開頭的url請求都進入到location ~ /(pc|hera_insure)規則。所以,就可以解決問題了,只需要將location ~ /(pc|hera_insure)規則修改一下:

1          location ~ ^/(pc|hera_insure) {
2              proxy_pass http://10.137.146.93:80;
3              proxy_set_header Host $host:$server_port;
4              proxy_set_header Remote_Addr $remote_addr;
5              proxy_set_header X-Real-IP $remote_addr;
6              proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
7              proxy_intercept_errors on;
8          }

主要是加了正則限定,必須以/pc或者/hera_insure開頭,才進入反向代理。。。

 

好了,修改了nginx.conf的配置,再次訪問最開始出問題的圖片:

 

 

到此,可以總結一下,這個問題的根本內容其實很簡單,就是location匹配規則的應用問題。注意:我的問題中url是比較長的(/uploadfiles/images/productPic/384/pc2b9471e-fe7_150_150.jpg)

1. location ~ url {...}的優先級高於location url {...}。【局部匹配情況下】

2. location ~ url {...}是正則匹配,只要url滿足正則規則,就會進入相關匹配段。

3. location    url {...}是起始匹配,只要url的起始部分和location中指定的url匹配,就會進入相關的匹配段。【注意,這個no modifier的規則,url不支持正則表達】

 

nginx的官方配置文件,要細讀,深入理解,才能避免這些坑啊。下面,附上官方文檔中關於nginx搜索匹配的先后順序:

The order you established in the configuration file is irrelevant. Nginx will search for matching patterns in a
specific order:
1. location blocks with the = modifier: If the specified string exactly matches
the requested URI, Nginx retains the location block.
2. location blocks with no modifier: If the specified string exactly matches the
requested URI, Nginx retains the location block.
3. location blocks with the ^~ modifier: If the specified string matches the
beginning of the requested URI, Nginx retains the location block.
4. location blocks with ~ or ~* modifier: If the regular expression matches the
requested URI, Nginx retains the location block.
5. location blocks with no modifier: If the specified string matches the
beginning of the requested URI, Nginx retains the location block.

注意理解2,5這兩條的差別。就能理解我這個問題的解決思路。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM