Nginx的client_header_buffer_size和large_client_header_buffers學習
之前看到有人寫的一篇關於nginx配置中large_client_header_buffers的問題排查的文章,其中提到:large_client_header_buffers 雖然也可以在server{}內生效,但是隻有 低於 nginx主配置中的值才有意義。
對這個結論,我心存疑慮,總覺得這種設計很奇怪,於是自己做了個測試,希望能瞭解的更深入一些。
測試方法
nginx主配置中加入配置項:(在主配置中將header大小控制在1k)
刪除所有干擾vhost,僅留下一個:
構造請求的shell:(構造header超過1k的請求)
1 第一次測試結果
測試得到的結果和之前看到的文章的結果不同,該長url請求成功被nginx處理。
什麼情況啊?於是檢視和文章中環境上的不同,發現很重要的一點:我只有這一個vhost。
於是新增了另外一個vhost,新增vhost配置如下:(沒有設定 large_client_header_buffers)
2 第二次測試結果
測試發現,nginx依舊可以處理該長url請求。
再次思考不同點,想到:這些vhost是被主配置中include進來的,是否會和讀取順序有關呢?
於是再次調整配置,將兩個vhost放到了一個conf檔案中,配置如下:
3 第三次測試結果
得到和文章中相同的結果,nginx返回414 Request-URI Too Large。
帶著好奇心,我顛倒了下兩個vhost的順序,如下:
4 第四次測試結果
nginx成功處理該長url請求。
初步結論
透過上面的現象,我得到一個初步結論:在第一個vhost中配置的large_client_header_buffers引數會起作用。
好奇怪的現象啊,我對自己得出的結論也是心存疑惑,於是決定從手冊中好好讀下控制header_buffer相關的指令。
從手冊上理解nginx有關header_buffer配置指令
從手冊上找到有兩個指令和header_buffer有關:
1.client_header_buffer_size
2.large_client_header_buffers
對nginx處理header時的方法,學習後理解如下:
1.先處理請求的request_line,之後才是request_header。
2.這兩者的buffer分配策略相同。
3.先根據client_header_buffer_size配置的值分配一個buffer,如果分配的buffer無法容納 request_line/request_header,那麼就會再次根據large_client_header_buffers配置的引數分配large_buffer,如果large_buffer還是無法容納,那麼就會返回414(處理request_line)/400(處理request_header)錯誤。
根據對手冊的理解,我理解這兩個指令在配置header_buffer時的使用場景是不同的,個人理解如下:
1.如果你的請求中的header都很大,那麼應該使用client_header_buffer_size,這樣能減少一次記憶體分配。
2.如果你的請求中只有少量請求header很大,那麼應該使用large_client_header_buffers,因為這樣就僅需在處理大header時才會分配更多的空間,從而減少無謂的記憶體空間浪費。
為了印證自己對兩個配置指令的理解,我把large_client_header_buffer
換成client_header_buffer_size,重新跑上面的多種測試,得到了和之前各種場景相同的結論。
手冊上也只是說明了這兩個指令的使用場景,沒有說更多的東西了,之前的疑惑還是沒有得到解答,那麼只有最後一招了,也是絕招:從原始碼中尋找答案!
原始碼學習
這裡從client_header_buffer_size指令入手,先檢視這個指令的定義部分:
由定義看到,我們在server{}中解析到的值會和http{}中的值做一次merge,作為該server{}下的最終值。檢視merge相關的邏輯:
從這段邏輯中得到結論:如果我們在server{}中配置了client_header_buffer_size,那麼針對這個server{}塊的最終值應該就是我們配置的值。
為了印證我的結論,我重新寫了vhost配置,並在程式碼中加入除錯資訊,把最終結果列印出來:
除錯程式碼:
重新編譯nginx,測試每個server{}中client_header_buffer_size的最終值為:
從值的最終結果看,的確是之前設定的1m,但是請求時卻返回了414。
由於將兩個server{}的位置顛倒後可以正常處理請求,所以在顛倒的情況下又測試了下最終值,輸出如下:
最終值的輸出還是1m,但是這次就可以正常處理請求了。
看來nginx在實際處理請求的過程中,一定還有之前不知道的一套邏輯,用來判斷
client_header_buffer_size的最終值。
nginx處理請求時的相關程式碼如下:
這裡真相大白:
原來client_header_buffer_size的最終值,是nginx在解析conf後,default_server中經過merge的最終值。
而default_server在nginx中的定義為:在listen指令中定義:
為了驗證這一點,我修改vhost配置為:
重啟nginx觀察merge結果:
merge結果沒有不同。測試請求,這次nginx成功處理該請求,和預期的效果一致。
結束語
筆者又測試了large_client_header_buffers,得到和client_header_buffer_size同樣的結果。可以得出結論:nginx在處理header時實際分配的buffer大小,是解析conf後,default_server中的最終值。
個人水平有限,上面的測試方法和理解如有不當的地方,還望大家指正,謝謝!
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31555491/viewspace-2640947/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Nginx配置和Linux核心引數的學習與驗證NginxLinux
- 【Nginx學習筆記】-初識NginxNginx筆記
- Nginx 學習筆記Nginx筆記
- Nginx入門學習Nginx
- nginx學習之模組Nginx
- 學習openresty時,nginx的一個坑RESTNginx
- nginx學習之負載均衡Nginx負載
- nginx 學習之反向代理(1)Nginx
- 神器 Nginx 的學習手冊 ( 建議收藏 )Nginx
- nginx的檔案描述符的學習之二Nginx
- docker學習6:Docker 安裝 NginxDockerNginx
- laravel學習之nginx配置站點LaravelNginx
- Nginx 學習系列(二) ————- 負載均衡Nginx負載
- Nginx 學習系列(二) ------------- 負載均衡Nginx負載
- 【持續更新...】Nginx 學習筆記Nginx筆記
- Nginx處理請求的11個階段(agentzh的Nginx 教程學習記錄)Nginx
- Nginx學習系列三Nginx的啟動、停止、修改配置檔案後重啟Nginx
- 學習 Nginx 的一些筆記,命令配置等Nginx筆記
- Nginx支援WebSocket反向代理-學習小結NginxWeb
- Nginx 學習筆記--程式與模組Nginx筆記
- Nginx 學習總結(4)—— Rewrite 模組Nginx
- 機器學習和深度學習的區別機器學習深度學習
- 機械學習和深度學習的區別深度學習
- Nginx 學習系列(三) ------------- alias、root指令區別Nginx
- nginx學習-ngx_http_rewrite_module模組NginxHTTP
- Nginx變數詳解(學習筆記十九)Nginx變數筆記
- Nginx學習筆記(反向代理&搭建叢集)Nginx筆記
- Nginx 學習系列(一) ------------- 正向代理與反向代理Nginx
- Nginx 學習筆記--程式與模組(二)Nginx筆記
- Linux學習之路(三) — 搭建nginx伺服器LinuxNginx伺服器
- 我眼中的 Nginx(一):Nginx 和位運算Nginx
- nginx面試題-nginx和apache的區別Nginx面試題Apache
- reduce()方法的學習和整理
- Nginx效能優化(學習筆記二十五)Nginx優化筆記
- nginx和apache的區別NginxApache
- NGINX的配置和基本使用Nginx
- 分享一些自己的學習過程和學習方法
- Flutter之FutureBuilder的學習和使用FlutterRebuild