問題描述
我們已知有一個map命令,可以用在http block和stream block中。
用於定義個新的變量,變量的取值由map里邊的key和value定義。
如我在前文有個SNI的使用中,便用到了這個方式。[nginx][tls] nginx配置https與ssl/tls的sni的方法
map $ssl_server_name $sni_string {
test1.www.local test1;
test2.www.local test2;
test3.www.local test3;
}
當key的字符串(test1.www.local)長度特別長的時候,nginx讀取配置會失敗,並打印如下的錯誤信息:
could not build map_hash, you should increase map_hash_bucket_size: 64
[classic_tong@ https://www.cnblogs.com/hugetong/p/12266235.html ]
問題分析
map命令由 ngx_http_map_module 提供。之后調用 nginx_hash,並在函數 ngx_hash_init()函數中由於構建hash表失敗返回以上錯誤信息。
通過閱讀代碼,我們知道。ngx_hash主要是為了在鏈接處理過程中加速訪問,在配置文件的初始化階段便構建完成。
使用開放定址法實現,hash的key放置在bucket中,bucket根據key的長度變長。並放置在連續的數組中。
故上文報錯中的bucket size實際指的是這個用來裝key的bucket的最大長度。
同時,另外一個參數,map_hash_max_size也與該數組密切相關。
此外,bucket size需要cache line對齊,並與性能相關。(沒有細致的閱讀該部分代碼,有關性能的內容,並不能給出一個准確的結論。)
但是在SNI場景里,由於SNI的每鏈接會產生IO操作,所以該部分的性能損失,似乎可以忽略?
(SNI的IO問題見:[nginx] nginx源碼分析--SNI性能分析)
參考
1,參考nginx的配置手冊:
https://nginx.org/en/docs/http/ngx_http_map_module.html#map_hash_bucket_size
https://nginx.org/en/docs/hash.html
2,一篇隨手google的文字。(其中提到的“開放鏈表法”為筆誤,應更正為“開放定址法”。)
https://www.cnblogs.com/chengxuyuancc/p/3782808.html
----
[classic_tong@ https://www.cnblogs.com/hugetong/p/12266235.html ]
完