微信公衆號:鄭爾多斯
關注可瞭解更多的Nginx知識。任何問題或建議,請公衆號留言;
關注公衆號,有趣有內涵的文章第一時間送達!正則表達式
本篇文章主要是分析配置文件解析完畢以後對location的進一步優化。這一部分主要完成了靜態樹的構建,一切的目的就是爲了更快捷的找到對應的location,提升http響應的速度。數組
在ngx_http_block()
中有下面的一部分代碼,以下:微信
1 /* create location trees */
2 for (s = 0; s < cmcf->servers.nelts; s++) {
3 // 當前server的ctx的loc_conf[ngx_http_core_module.ctx_index]
4 clcf = cscfp[s]->ctx->loc_conf[ngx_http_core_module.ctx_index];
5
6 if (ngx_http_init_locations(cf, cscfp[s], clcf) != NGX_OK) {
7 return NGX_CONF_ERROR;
8 }
9
10 if (ngx_http_init_static_location_trees(cf, clcf) != NGX_OK) {
11 return NGX_CONF_ERROR;
12 }
13 }
複製代碼
上面的cmcf
是ngx_http_core_module
在http
級別的ctx
的main_conf數組
中對應的配置結構體,類型爲ngx_http_core_main_conf_t
類型。通過前面分析,咱們知道它的servers
字段是一個動態數組,保存了當前配置文件中的全部server
指令塊對應的配置結構體。上面的代碼就是遍歷這個server
數組,而後對每一個server下面的location進行處理。下面咱們看一下處理的過程:app
代碼以下:函數
1static ngx_int_t
2ngx_http_init_locations(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
3 ngx_http_core_loc_conf_t *pclcf)
4{
5 ngx_uint_t n;
6 ngx_queue_t *q, *locations, *named, tail;
7 ngx_http_core_loc_conf_t *clcf;
8 ngx_http_location_queue_t *lq;
9 ngx_http_core_loc_conf_t **clcfp;
10#if (NGX_PCRE)
11 ngx_uint_t r;
12 ngx_queue_t *regex;
13#endif
14
15 locations = pclcf->locations;
16
17 if (locations == NULL) {
18 return NGX_OK;
19 }
20
21 ngx_queue_sort(locations, ngx_http_cmp_locations);
22
23 named = NULL;
24 n = 0;
25#if (NGX_PCRE)
26 regex = NULL;
27 r = 0;
28#endif
29
30 for (q = ngx_queue_head(locations);
31 q != ngx_queue_sentinel(locations);
32 q = ngx_queue_next(q))
33 {
34 lq = (ngx_http_location_queue_t *) q;
35
36 clcf = lq->exact ? lq->exact : lq->inclusive;
37
38 if (ngx_http_init_locations(cf, NULL, clcf) != NGX_OK) {
39 return NGX_ERROR;
40 }
41
42#if (NGX_PCRE)
43
44 if (clcf->regex) {
45 r++;
46
47 if (regex == NULL) {
48 regex = q;
49 }
50
51 continue;
52 }
53
54#endif
55
56 if (clcf->named) {
57 n++;
58
59 if (named == NULL) {
60 named = q;
61 }
62
63 continue;
64 }
65
66 if (clcf->noname) {
67 break;
68 }
69 }
70
71 if (q != ngx_queue_sentinel(locations)) {
72 ngx_queue_split(locations, q, &tail);
73 }
74
75 if (named) {
76 clcfp = ngx_palloc(cf->pool,
77 (n + 1) * sizeof(ngx_http_core_loc_conf_t *));
78 if (clcfp == NULL) {
79 return NGX_ERROR;
80 }
81
82 cscf->named_locations = clcfp;
83
84 for (q = named;
85 q != ngx_queue_sentinel(locations);
86 q = ngx_queue_next(q))
87 {
88 lq = (ngx_http_location_queue_t *) q;
89
90 *(clcfp++) = lq->exact;
91 }
92
93 *clcfp = NULL;
94
95 ngx_queue_split(locations, named, &tail);
96 }
97
98#if (NGX_PCRE)
99
100 if (regex) {
101
102 clcfp = ngx_palloc(cf->pool,
103 (r + 1) * sizeof(ngx_http_core_loc_conf_t *));
104 if (clcfp == NULL) {
105 return NGX_ERROR;
106 }
107
108 pclcf->regex_locations = clcfp;
109
110 for (q = regex;
111 q != ngx_queue_sentinel(locations);
112 q = ngx_queue_next(q))
113 {
114 lq = (ngx_http_location_queue_t *) q;
115
116 *(clcfp++) = lq->exact;
117 }
118
119 *clcfp = NULL;
120
121 ngx_queue_split(locations, regex, &tail);
122 }
123
124#endif
125
126 return NGX_OK;
127}
複製代碼
上面的代碼首先調用ngx_queue_sort()
函數對全部的location進行排序,排序以後的結果他以下:優化
緊接着將全部屬於正則表達式和named的location分別放置到不一樣的地方,對於咱們的例子,以下:
ui
這個函數主要是爲了構建靜態的location三叉樹,因爲咱們的config文件中的location數量太少,這裏沒有辦法進行仔細的講解,因此具體的構建過程這裏不詳細的介紹,後面文章會仔細介紹這個過程,咱們這裏僅僅展現構建的最終結果:spa
因爲咱們的配置文件只有一個location,因此造成的樹結構只有一個節點,後面咱們會分析多個location的時候如何構建這棵樹。code
喜歡本文的朋友們,歡迎長按下圖關注訂閱號鄭爾多斯,更多精彩內容第一時間送達
orm