大家看到在構建一個ngx_hash_wildcard_t的時候,需要對通配符的哪些key進行預處理。這個處理起來比較麻煩。而當有一組key,這些里面既有無通配符的key,也有包含通配符的key的時候。我們就需要構建三個hash表,一個包含普通的key的hash表,一個包含前向通配符的hash表,一個包含后向通配符的hash表(或者也可以把這三個hash表組合成一個ngx_hash_combined_t)。在這種情況下,為了讓大家方便的構造這些hash表,nginx提供給了此輔助類型。
該類型以及相關的操作函數也定義在src/core/ngx_hash.h|c里。我們先來看一下該類型的定義。
[](http:// "點擊提交Issue,反饋你的意見...")
typedef struct {
ngx_uint_t hsize;
ngx_pool_t *pool;
ngx_pool_t *temp_pool;
ngx_array_t keys;
ngx_array_t *keys_hash;
ngx_array_t dns_wc_head;
ngx_array_t *dns_wc_head_hash;
ngx_array_t dns_wc_tail;
ngx_array_t *dns_wc_tail_hash;
} ngx_hash_keys_arrays_t;
<table class="docutils field-list" frame="void" rules="none" style="margin: 0px -0.5em; border: 0px; color: rgb(0, 0, 0); font-family: 'segoe UI', sans-serif; letter-spacing: -0.1599999964237213px; line-height: 24px; white-space: normal; background-color: rgb(255, 255, 255);"><colgroup><col class="field-name"/><col class="field-body"/></colgroup><tbody valign="top"><tr class="field-odd field"><th class="field-name" style="padding: 1px 8px 1px 5px; border: 0px !important;">hsize:</th><td class="field-body" style="padding: 1px 8px 1px 5px; border: 0px !important;">將要構建的hash表的桶的個數。對于使用這個結構中包含的信息構建的三種類型的hash表都會使用此參數。</td></tr><tr class="field-even field"><th class="field-name" style="padding: 1px 8px 1px 5px; border: 0px !important;">pool:</th><td class="field-body" style="padding: 1px 8px 1px 5px; border: 0px !important;">構建這些hash表使用的pool。</td></tr><tr class="field-odd field"><th class="field-name" style="padding: 1px 8px 1px 5px; border: 0px !important;">temp_pool:</th><td class="field-body" style="padding: 1px 8px 1px 5px; border: 0px !important;">在構建這個類型以及最終的三個hash表過程中可能用到臨時pool。該temp_pool可以在構建完成以后,被銷毀掉。這里只是存放臨時的一些內存消耗。</td></tr><tr class="field-even field"><th class="field-name" style="padding: 1px 8px 1px 5px; border: 0px !important;">keys:</th><td class="field-body" style="padding: 1px 8px 1px 5px; border: 0px !important;">存放所有非通配符key的數組。</td></tr><tr class="field-odd field"><th class="field-name" style="padding: 1px 8px 1px 5px; border: 0px !important;">keys_hash:</th><td class="field-body" style="padding: 1px 8px 1px 5px; border: 0px !important;">這是個二維數組,第一個維度代表的是bucket的編號,那么keys_hash[i]中存放的是所有的key算出來的hash值對hsize取模以后的值為i的key。假設有3個key,分別是key1,key2和key3假設hash值算出來以后對hsize取模的值都是i,那么這三個key的值就順序存放在keys_hash[i][0],keys_hash[i][1], keys_hash[i][2]。該值在調用的過程中用來保存和檢測是否有沖突的key值,也就是是否有重復。</td></tr><tr class="field-even field"><th class="field-name" style="padding: 1px 8px 1px 5px; border: 0px !important;">dns_wc_head:</th><td class="field-body" style="padding: 1px 8px 1px 5px; border: 0px !important;">放前向通配符key被處理完成以后的值。比如:“*.abc.com” 被處理完成以后,變成 “com.abc.” 被存放在此數組中。</td></tr><tr class="field-odd field"><th class="field-name" style="padding: 1px 8px 1px 5px; border: 0px !important;">dns_wc_tail:</th><td class="field-body" style="padding: 1px 8px 1px 5px; border: 0px !important;">存放后向通配符key被處理完成以后的值。比如:“mail.xxx.*” 被處理完成以后,變成 “mail.xxx.” 被存放在此數組中。</td></tr><tr class="field-even field"><th class="field-name" colspan="2" style="padding: 1px 8px 1px 5px; border: 0px !important;">dns_wc_head_hash:</th></tr><tr class="field-even field"><td style="padding: 1px 8px 1px 5px; border: 0px !important;">?</td><td class="field-body" style="padding: 1px 8px 1px 5px; border: 0px !important;">該值在調用的過程中用來保存和檢測是否有沖突的前向通配符的key值,也就是是否有重復。</td></tr><tr class="field-odd field"><th class="field-name" colspan="2" style="padding: 1px 8px 1px 5px; border: 0px !important;">dns_wc_tail_hash:</th></tr><tr class="field-odd field"><td style="padding: 1px 8px 1px 5px; border: 0px !important;">?</td><td class="field-body" style="padding: 1px 8px 1px 5px; border: 0px !important;">該值在調用的過程中用來保存和檢測是否有沖突的后向通配符的key值,也就是是否有重復。</td></tr></tbody></table>
在定義一個這個類型的變量,并對字段pool和temp_pool賦值以后,就可以調用函數ngx_hash_add_key把所有的key加入到這個結構中了,該函數會自動實現普通key,帶前向通配符的key和帶后向通配符的key的分類和檢查,并將這個些值存放到對應的字段中去, 然后就可以通過檢查這個結構體中的keys、dns_wc_head、dns_wc_tail三個數組是否為空,來決定是否構建普通hash表,前向通配符hash表和后向通配符hash表了(在構建這三個類型的hash表的時候,可以分別使用keys、dns_wc_head、dns_wc_tail三個數組)。
構建出這三個hash表以后,可以組合在一個ngx_hash_combined_t對象中,使用ngx_hash_find_combined進行查找。或者是仍然保持三個獨立的變量對應這三個hash表,自己決定何時以及在哪個hash表中進行查詢。
[](http:// "點擊提交Issue,反饋你的意見...")
ngx_int_t ngx_hash_keys_array_init(ngx_hash_keys_arrays_t *ha, ngx_uint_t type);
初始化這個結構,主要是對這個結構中的ngx_array_t類型的字段進行初始化,成功返回NGX_OK。
| ha: | 該結構的對象指針。 |
|-----|-----|
| type: | 該字段有2個值可選擇,即NGX_HASH_SMALL和NGX_HASH_LARGE。用來指明將要建立的hash表的類型,如果是NGX_HASH_SMALL,則有比較小的桶的個數和數組元素大小。NGX_HASH_LARGE則相反。 |
[](http:// "點擊提交Issue,反饋你的意見...")
ngx_int_t ngx_hash_add_key(ngx_hash_keys_arrays_t *ha, ngx_str_t *key,
void *value, ngx_uint_t flags);
一般是循環調用這個函數,把一組鍵值對加入到這個結構體中。返回NGX_OK是加入成功。返回NGX_BUSY意味著key值重復。
| ha: | 該結構的對象指針。 |
|-----|-----|
| key: | 參數名自解釋了。 |
| value: | 參數名自解釋了。 |
| flags: | 有兩個標志位可以設置,NGX_HASH_WILDCARD_KEY和NGX_HASH_READONLY_KEY。同時要設置的使用邏輯與操作符就可以了。NGX_HASH_READONLY_KEY被設置的時候,在計算hash值的時候,key的值不會被轉成小寫字符,否則會。NGX_HASH_WILDCARD_KEY被設置的時候,說明key里面可能含有通配符,會進行相應的處理。如果兩個標志位都不設置,傳0。 |
有關于這個數據結構的使用,可以參考src/http/ngx_http.c中的ngx_http_server_names函數。
- 上篇:nginx模塊開發篇
- nginx平臺初探
- 初探nginx架構
- nginx基礎概念
- connection
- request
- keepalive
- pipe
- lingering_close
- 基本數據結構
- ngx_str_t
- ngx_pool_t
- ngx_array_t
- ngx_hash_t
- ngx_hash_wildcard_t
- ngx_hash_combined_t
- ngx_hash_keys_arrays_t
- ngx_chain_t
- ngx_buf_t
- ngx_list_t
- ngx_queue_t
- nginx的配置系統
- 指令參數
- 指令上下文
- nginx的模塊化體系結構
- 模塊的分類
- nginx的請求處理
- handler模塊
- handler模塊簡介
- 模塊的基本結構
- 模塊配置結構
- 模塊配置指令
- 模塊上下文結構
- 模塊的定義
- handler模塊的基本結構
- handler模塊的掛載
- handler的編寫步驟
- 示例: hello handler 模塊
- handler模塊的編譯和使用
- 更多handler模塊示例分析
- http access module
- http static module
- http log module
- 過濾模塊
- 過濾模塊簡介
- 過濾模塊的分析
- upstream模塊
- upstream模塊
- upstream模塊接口
- memcached模塊分析
- 本節回顧
- 負載均衡模塊
- 配置
- 指令
- 鉤子
- 初始化配置
- 初始化請求
- peer.get和peer.free回調函數
- 本節回顧
- 其他模塊
- core模塊
- event模塊
- 模塊開發高級篇
- 變量
- 下篇:nginx原理解析篇
- nginx架構詳解
- nginx的源碼目錄結構
- nginx的configure原理
- 模塊編譯順序
- nginx基礎設施
- 內存池
- nginx的啟動階段
- 概述
- 共有流程
- 配置解析
- nginx的請求處理階段
- 接收請求流程
- http請求格式簡介
- 請求頭讀取
- 解析請求行
- 解析請求頭
- 請求體讀取
- 讀取請求體
- 丟棄請求體
- 多階段處理請求
- 多階段執行鏈
- POST_READ階段
- SERVER_REWRITE階段
- FIND_CONFIG階段
- REWRITE階段
- POST_REWRITE階段
- PREACCESS階段
- ACCESS階段
- POST_ACCESS階段
- TRY_FILES階段
- CONTENT階段
- LOG階段
- Nginx filter
- header filter分析
- body filter分析
- ngx_http_copy_filter_module分析
- ngx_http_write_filter_module分析
- subrequest原理解析
- https請求處理解析
- 附錄A 編碼風格
- 附錄B 常用API
- 附錄C 模塊編譯,調試與測試