目錄
基本概述
數據結構
接口描述
具體實現
ngx_list_create
ngx_list_init
ngx_list_push
使用案例
整理自?nginx?1.9.2 源碼 和 《深入理解 Nginx:模塊開發與架構解析》
基本概述
????????Nginx 中的 ngx_list_t 是一個單向鏈表容器,鏈表中的每一個節點同時又是數據數組。ngx_list_t 作為鏈表容器,確定了 ngx_list_part_s 節點的存儲空間容量、內存管理入口(內存池)和數據訪問入口(鏈表+數組)。
????????ngx_list_t? 鏈表具體結構如下圖所示。可靈活定義 ngx_list_part_s 中數據結構,同時因為其內部存儲地址連續,可通過數組偏移進行快速訪問。
數據結構
typedef struct ngx_list_part_s ngx_list_part_t; /*鏈表中的一個節點,該節點中的 elts 記錄一個數組的數據,數組類型可以自定義 ;節點使用的數組,容量(成員個數)已經固定(由 ngx_list_t 中的 nalloc 確定),使用 nelts 記錄該數組已使用容量,所以 nelts 肯定小于 nalloc
*/
struct ngx_list_part_s { void *elts; // 指向數組的起始地址。ngx_uint_t nelts; // 數組已使用了多少個元素ngx_list_part_t *next; // 下一個鏈表節點
};/*ngx_list_part_s 鏈表容器,該結構體內確定了 ngx_list_part_s 的存儲空間容量、內存管理入口和訪問入口。
*/
typedef struct { ngx_list_part_t *last; //指向鏈表的最后一個節點。ngx_list_part_t part; //鏈表的首個數組節點。// 限制 ngx_list_part_s elts 中每個數組元素的占用空間的大小size_t size; // 限制 ngx_list_part_s elts 中每個數組最大元素數量,一旦分配后是不可更改的ngx_uint_t nalloc;// //鏈表中管理內存分配的內存池對象。用戶要存放的數據占用的內存都是由 pool 分配的。ngx_pool_t *pool;
} ngx_list_t;
接口描述
// 創建新的鏈表,指定內存池對象,和數組容量(元素個數和每個元素大小)
// 該函數調用后會返回一個鏈表,該鏈表內至少有一個數組,不會是空鏈表的
ngx_list_t *ngx_list_create(ngx_pool_t *pool, ngx_uint_t n, size_t size);// 初始化已有鏈表,與 ngx_list_create 使用方法相似,其實 ngx_list_create 里面也會調用 ngx_list_init
static ngx_inline ngx_int_t
ngx_list_init(ngx_list_t *list, ngx_pool_t *pool, ngx_uint_t n, size_t size)// 往鏈表中新增元素,傳入鏈表,返回新元素的首地址供使用。注意此時返回的是 ngx_list_part_s 中的 elts 成員
void *ngx_list_push(ngx_list_t *list);
具體實現
ngx_list_create
ngx_list_t *
ngx_list_create(ngx_pool_t *pool, ngx_uint_t n, size_t size) //實際上就是為nginx_list_t的part成員創建指定的n*size空間,并且創建了空間sizeof(ngx_list_t)
{ngx_list_t *list;// 分配 ngx_list_t 大小的內存list = ngx_palloc(pool, sizeof(ngx_list_t));if (list == NULL) {return NULL;}// 對空鏈表進行初始化if (ngx_list_init(list, pool, n, size) != NGX_OK) {return NULL;}return list;
}
ngx_list_init
static ngx_inline ngx_int_t
ngx_list_init(ngx_list_t *list, ngx_pool_t *pool, ngx_uint_t n, size_t size)
{// 對鏈表的首個 ngx_list_part_s 元素中的數組分配內存,大小為 n * size,n 為數組元素個數,size 為數組內每個元素的大小,我們可以看到,這些配置在鏈表初始化的時候就已經寫死了,不可再改變,除非再次初始化list->part.elts = ngx_palloc(pool, n * size); if (list->part.elts == NULL) {return NGX_ERROR;}// 對鏈表的一些屬性進行賦值list->part.nelts = 0;list->part.next = NULL;// 初始化時,鏈表只有一個節點,所以首節點也是末尾節點list->last = &list->part;list->size = size;list->nalloc = n;list->pool = pool;return NGX_OK;
}
ngx_list_push
// 往鏈表的末尾節點中新增數組,函數返回可用地址指針
void *
ngx_list_push(ngx_list_t *l)
{void *elt;ngx_list_part_t *last;last = l->last;// 判斷末尾節點的數組空間是否滿了if (last->nelts == l->nalloc) {/* the last part is full, allocate a new list part */// 若末尾節點空間滿了,則往鏈表中新增節點,刷新末尾節點地址last = ngx_palloc(l->pool, sizeof(ngx_list_part_t));if (last == NULL) {return NULL;}last->elts = ngx_palloc(l->pool, l->nalloc * l->size);if (last->elts == NULL) {return NULL;}// 新的末尾節點last->nelts = 0;last->next = NULL;// 刷新末尾節點指針,新節點變為末尾節點l->last->next = last;l->last = last;}elt = (char *) last->elts + l->size * last->nelts;last->nelts++;return elt;
}
使用案例
// 創建一個鏈表,鏈表中每個數組長度限制為 4,每個數組元素數據類型為 ngx_str_t
// 創建鏈表的時候,內部會調用 ngx_list_init
ngx_list_t* testlist = ngx_list_create(r->pool, 4, sizeof(ngx_str_t));
if (testlist == null )
{return NGX_ERORR;
}// 往鏈表中添加數據,該數據會添加到鏈表末尾節點的數組中,若該數組剩余容量不足,會往鏈表中新增節點
ngx_str_t* str = ngx_list_push(testlist);
if ( str == null )
{return NGX_ERROR;
}
str->len = sizeof("hello world");
str->value = "he11o world";// 遍歷鏈表
// part 用于指向鏈表中的每一個 ngx_list_part_t 數組,剛開始執行鏈表中第一個節點
ngx_list_part_t* part = &testlist.part;
//根據鏈表中的數據類型,把數組里的 elts 轉化為該類型使用
ngx_str_t* str = part->elts;
// i 表示元素在鏈表的每個 ngx_list_part_t 數組里的序號
for (i ; 0; /* void */; i++)
{// 如果數組已使用的數組元素已經遍歷完,則需要跳轉到鏈表中下一個節點if ( i >= part->nelts ){if ( part -> next == NULL ){// 如果某個 ngx_list_part_t 數組的 next 指針為空// 則說明已經遍歷完鏈表了break;}// 訪問下一個 ngx_list_part_tpart = part->next;header = part->elts;// 將 i 序號置為 0,準備重新訪問下一個數組i = 0;}// 遍歷每個鏈表節點數組內的元素printf("list element : %*s\n", str[i].len, str[i].data);
}
------------------------------------以下為廢話,不需要再閱讀------------------------------------------
NGINX是一款高性能的HTTP服務器和反向代理服務器,它以其穩定性、豐富的功能集、以及輕量級架構而聞名。在互聯網技術棧中,NGINX扮演著至關重要的角色,廣泛應用于負載均衡、靜態內容服務以及作為反向代理來提高應用的可用性和擴展性。它的事件驅動架構使其能夠支持高并發連接,處理大量請求而不顯著增加延遲。
NGINX的配置文件采用簡潔明了的語法,使得用戶可以輕松地進行性能調優和功能定制。通過模塊化設計,NGINX不僅支持HTTP/2協議,還提供了對TLS/SSL的全面支持,確保數據傳輸的安全性。此外,它還具備WebSocket支持,使得實時通信應用能夠無縫運行。
NGINX的反向代理能力尤為突出,它可以根據URL路徑、頭部信息等多種規則將客戶端請求智能地轉發到后端服務器群中的某一臺或多臺服務器上,實現請求的高效分發。同時,NGINX還支持健康檢查機制,能夠自動剔除故障節點,保證服務的高可用性。
對于靜態內容的高效處理也是NGINX的一大亮點。它可以快速響應并交付HTML頁面、圖片、CSS文件等靜態資源,極大地提升了網站訪問速度。結合其緩存機制,NGINX能有效減輕后端服務器的壓力,優化整體系統性能。
NGINX還提供了豐富的第三方模塊,如安全防護、流量控制等,進一步增強了其功能性。無論是小型網站還是大型企業級應用,NGINX都能提供靈活且強大的解決方案,是現代Web架構中不可或缺的組成部分。
NGINX是一款高性能的HTTP服務器和反向代理服務器,它以其穩定性、豐富的功能集、以及輕量級架構而聞名。在互聯網技術棧中,NGINX扮演著至關重要的角色,廣泛應用于負載均衡、靜態內容服務以及作為反向代理來提高應用的可用性和擴展性。它的事件驅動架構使其能夠支持高并發連接,處理大量請求而不顯著增加延遲。
NGINX的配置文件采用簡潔明了的語法,使得用戶可以輕松地進行性能調優和功能定制。通過模塊化設計,NGINX不僅支持HTTP/2協議,還提供了對TLS/SSL的全面支持,確保數據傳輸的安全性。此外,它還具備WebSocket支持,使得實時通信應用能夠無縫運行。
NGINX的反向代理能力尤為突出,它可以根據URL路徑、頭部信息等多種規則將客戶端請求智能地轉發到后端服務器群中的某一臺或多臺服務器上,實現請求的高效分發。同時,NGINX還支持健康檢查機制,能夠自動剔除故障節點,保證服務的高可用性。
對于靜態內容的高效處理也是NGINX的一大亮點。它可以快速響應并交付HTML頁面、圖片、CSS文件等靜態資源,極大地提升了網站訪問速度。結合其緩存機制,NGINX能有效減輕后端服務器的壓力,優化整體系統性能。
NGINX還提供了豐富的第三方模塊,如安全防護、流量控制等,進一步增強了其功能性。無論是小型網站還是大型企業級應用,NGINX都能提供靈活且強大的解決方案,是現代Web架構中不可或缺的組成部分。