nginx 模塊相關配置及結構理解

文章目錄

  • 模塊配置結構
  • 模塊配置指令
    • 先看一下 ngx_command_t 結構
    • 一個模塊配置的demo
    • 簡單模塊配置的案例演示
  • 模塊上下文結構
  • 模塊的定義

模塊配置結構

Nginx中每個模塊都會提供一些指令,以便于用戶通過配置去控制該模塊的行為。
Nginx的配置信息分成了幾個作用域(scope,有時也稱作上下文)。作用域有main, server, 以及location。

模塊配置指令

先看一下 ngx_command_t 結構

位置: src/core 目錄下 ngx_conf_file.h
ngx_command_t原型:

typedef struct ngx_command_s         ngx_command_t;
struct ngx_command_s {ngx_str_t             name;		// 配置指令名稱ngx_uint_t            type;		// 該配置的類型,其實更準確一點說,是該配置指令屬性的集合。(具體見下文)char               *(*set)(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);	// (具體見下文)ngx_uint_t            conf;		/*該字段被NGX_HTTP_MODULE類型模塊所用 (我們編寫的基本上都是NGX_HTTP_MOUDLE,只有一些nginx核心模塊是非NGX_HTTP_MODULE),該字段指定當前配置項存儲的內存位置。實際上是使用哪個內存池的問題。因為http模塊對所要保存的配置信息,劃分了main, server和location三個地方進行存儲,每個地方都有一個內存池用來分配存儲這些信息的內存。這里可能的值為 NGX_HTTP_MAIN_CONF_OFFSET、NGX_HTTP_SRV_CONF_OFFSET或NGX_HTTP_LOC_CONF_OFFSET。當然也可以直接置為0,就是NGX_HTTP_MAIN_CONF_OFFSET。*/ngx_uint_t            offset;	/*指定該配置項值的精確存放位置,一般指定為某一個結構體變量的字段偏移。因為對于配置信息的存儲,一般我們都是定義個結構體來存儲的。那么比如我們定義了一個結構體A,該項配置的值需要存儲到該結構體的b字段。那么在這里就可以填寫為offsetof(A, b)。對于有些配置項,它的值不需要保存或者是需要保存到更為復雜的結構中時,這里可以設置為0。*/void                 *post;		/* 該字段存儲一個指針。可以指向任何一個在讀取配置過程中需要的數據,以便于進行配置讀取的處理。大多數時候,都不需要,所以簡單地設為0即可。*/
};

補充說明:
1)對type字段
nginx提供了很多預定義的屬性值(一些宏定義),通過邏輯或運算符可組合在一起,形成對這個配置指令的詳細的說明。
屬性值可以有

NGX_CONF_NOARGS:配置指令不接受任何參數。
NGX_CONF_TAKE1:配置指令接受1個參數。
NGX_CONF_TAKE2:配置指令接受2個參數。
NGX_CONF_TAKE3:配置指令接受3個參數。
NGX_CONF_TAKE4:配置指令接受4個參數。
NGX_CONF_TAKE5:配置指令接受5個參數。
NGX_CONF_TAKE6:配置指令接受6個參數。
NGX_CONF_TAKE7:配置指令接受7個參數。
可以組合多個屬性,比如一個指令即可以不填參數,也可以接受1個或者2個參數。那么就是
NGX_CONF_NOARGS|NGX_CONF_TAKE1|NGX_CONF_TAKE2。

nginx還提供了一些定義,使用起來更簡潔:

NGX_CONF_TAKE12:配置指令接受1個或者2個參數。
NGX_CONF_TAKE13:配置指令接受1個或者3個參數。
NGX_CONF_TAKE23:配置指令接受2個或者3個參數。
NGX_CONF_TAKE123:配置指令接受1個或者2個或者3參數。
NGX_CONF_TAKE1234:配置指令接受1個或者2個或者3個或者4個參數。
NGX_CONF_1MORE:配置指令接受至少一個參數。
NGX_CONF_2MORE:配置指令接受至少兩個參數。
NGX_CONF_MULTI:配置指令可以接受多個參數,即個數不定。
NGX_CONF_BLOCK:配置指令可以接受的值是一個配置信息塊。也就是一對大括號括起來的內容。里面可以再包括很多的配置指令。比如常見的server指令就是這個屬性的。
NGX_CONF_FLAG:配置指令可以接受的值是”on”或者”off”,最終會被轉成bool值。
NGX_CONF_ANY:配置指令可以接受的任意的參數值。一個或者多個,或者”on”或者”off”,或者是配置塊。
需要說明的是,無論如何,nginx的配置指令的參數個數不可以超過NGX_CONF_MAX_ARGS個。目前這個值被定義為8,也就是不能超過8個參數值。

下面介紹一組說明配置指令作用域的相關屬性:

NGX_DIRECT_CONF:可以出現在配置文件中最外層。例如已經提供的配置指令daemon,master_process等。
NGX_MAIN_CONF:http、mail、events、error_log等。
NGX_ANY_CONF:該配置指令可以出現在任意配置級別上。
對于我們編寫的大多數模塊而言,都是在處理http相關的事情,也就是所謂的都是NGX_HTTP_MODULE,對于這樣類型的模塊,其配置可能出現的位置也是分為直接出現在http里面,以及其他位置:
NGX_HTTP_MAIN_CONF: 可以直接出現在http配置指令里。
NGX_HTTP_SRV_CONF:可以出現在http里面的server配置指令里。
NGX_HTTP_LOC_CONF:可以出現在http server塊里面的location配置指令里。
NGX_HTTP_UPS_CONF:可以出現在http里面的upstream配置指令里。
NGX_HTTP_SIF_CONF:可以出現在http里面的server配置指令里的if語句所在的block中。
NGX_HTTP_LMT_CONF:可以出現在http里面的limit_except指令的block中。
NGX_HTTP_LIF_CONF:可以出現在http server塊里面的location配置指令里的if語句所在的block中。

2)對set字段
這是一個函數指針,當nginx在解析配置的時候,如果遇到這個配置指令,將會把讀取到的值傳遞給這個函數進行分解處理。因為具體每個配置指令的值如何處理,只有定義這個配置指令的人是最清楚的。
函數原型:

// 處理成功時,返回NGX_OK,否則返回NGX_CONF_ERROR或者是一個自定義的錯誤信息的字符串。
/* cf: 該參數里面保存從配置文件讀取到的原始字符串以及相關的一些信息。特別注意的是這個參數的args字段是一個ngx_str_t
類型的數組,該數組的首個元素是這個配置指令本身,第二個元素是指令的第一個參數,第三個元素是第二個參數,依次類推。*/
/* cmd:  這個配置指令對應的ngx_command_t結構。*/
/* conf: 就是定義的存儲這個配置值的結構體,用戶在處理的時候可以使用類型轉換,轉換成自己知道的類型,再進行字段的賦值。*/
char *(*set)(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);

為了更加方便的實現對配置指令參數的讀取,nginx已經默認提供了對一些標準類型的參數進行讀取的函數,可以直接賦值給set字段使用。
下面列出這些已經實現的set類型函數:

ngx_conf_set_flag_slot:讀取NGX_CONF_FLAG類型的參數。
ngx_conf_set_str_slot:讀取字符串類型的參數。
ngx_conf_set_str_array_slot:讀取字符串數組類型的參數。
ngx_conf_set_keyval_slot:讀取鍵值對類型的參數。
ngx_conf_set_num_slot:讀取整數類型(有符號整數ngx_int_t)的參數。
ngx_conf_set_size_slot:讀取size_t類型的參數,也就是無符號數。
ngx_conf_set_off_slot:讀取off_t類型的參數。
ngx_conf_set_msec_slot: 讀取毫秒值類型的參數。
ngx_conf_set_sec_slot:讀取秒值類型的參數。
ngx_conf_set_bufs_slot:讀取的參數值是2個,一個是buf的個數,一個是buf的大小。例如: output_buffers 1 128k;
ngx_conf_set_enum_slot:讀取枚舉類型的參數,將其轉換成整數ngx_uint_t類型。
ngx_conf_set_bitmask_slot:讀取參數的值,并將這些參數的值以bit位的形式存儲。例如:HttpDavModule模塊的dav_methods指令。

一個模塊配置的demo

static ngx_command_t ngx_http_hello_commands[] = {{ngx_string("hello_string"),NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS|NGX_CONF_TAKE1,ngx_http_hello_string,NGX_HTTP_LOC_CONF_OFFSET,offsetof(ngx_http_hello_loc_conf_t, hello_string),NULL },ngx_null_command	// 每個模塊配置后必不可少的  // 它的原型是 #define ngx_null_command  { ngx_null_string, 0, NULL, 0, 0, NULL }
};

我們定義的配置指令,一個叫hello_string可以接收一個或零個參數,可以出現在http server塊里面的location配置指令里。該配置的處理函數是ngx_http_hello_string。該配置作用域在NGX_HTTP_LOC_CONF_OFFSET(location中)。該配置信息保存在自定義結構體ngx_http_hello_loc_conf_t 的hello_string字段。

簡單模塊配置的案例演示

  1. 首先我們在src/core/nginx.c文件中找到ngx_core_commands數組。

  2. 在該數組中添加一條自定義配置。
    在這里插入圖片描述

  3. 實現處理函數ngx_conf_my_handler(這個函數名是自己起的)。
    在這里插入圖片描述

  4. 重新編譯install。

  5. 在nginx.conf配置文件中加上自定義的配置。
    在這里插入圖片描述

  6. 測試:./nginx -t
    在這里插入圖片描述

模塊上下文結構

這是一個ngx_http_module_t類型的靜態變量。這個變量實際上是提供一組回調函數指針,這些函數有在創建存儲配置信息的對象的函數,也有在創建前和創建后會調用的函數。

ngx_http_module_t結構原型:

typedef struct {ngx_int_t   (*preconfiguration)(ngx_conf_t *cf);	// 在創建和讀取該模塊的配置信息之前被調用。ngx_int_t   (*postconfiguration)(ngx_conf_t *cf);	// 在創建和讀取該模塊的配置信息之后被調用。void   *(*create_main_conf)(ngx_conf_t *cf);	/* 調用該函數創建本模塊位于http block的配置信息存儲結構。該函數成功的時候,返回創建的配置對象。失敗的話,返回NULL。*/char   *(*init_main_conf)(ngx_conf_t *cf, void *conf);	/* 調用該函數初始化本模塊位于http block的配置信息存儲結構。該函數成功的時候,返回NGX_CONF_OK。失敗的話,返回NGX_CONF_ERROR或錯誤字符串。*/void       *(*create_srv_conf)(ngx_conf_t *cf);		/* 調用該函數創建本模塊位于http server block的配置信息存儲結構,每個server block會創建一個。該函數成功的時候,返回創建的配置對象。失敗的話,返回NULL。*/char       *(*merge_srv_conf)(ngx_conf_t *cf, void *prev, void *conf);	/* 因為有些配置指令既可以出現在http block,也可以出現在http server block中。那么遇到這種情況,每個server都會有自己存儲結構來存儲該server的配置,但是在這種情況下http block中的配置與server block中的配置信息發生沖突的時候,就需要調用此函數進行合并,該函數并非必須提供,當預計到絕對不會發生需要合并的情況的時候,就無需提供。當然為了安全起見還是建議提供。該函數執行成功的時候,返回NGX_CONF_OK。失敗的話,返回NGX_CONF_ERROR或錯誤字符串。*/void       *(*create_loc_conf)(ngx_conf_t *cf);	/* 調用該函數創建本模塊位于location block的配置信息存儲結構。每個在配置中指明的location創建一個。該函數執行成功,返回創建的配置對象。失敗的話,返回NULL。*/char       *(*merge_loc_conf)(ngx_conf_t *cf, void *prev, void *conf);	/* 與merge_srv_conf類似,這個也是進行配置值合并的地方。該函數成功的時候,返回NGX_CONF_OK。失敗的話,返回NGX_CONF_ERROR或錯誤字符串。*/
} ngx_http_module_t;

Nginx里面的配置信息都是上下一層層的嵌套的,對于具體某個location的話,對于同一個配置,如果當前層次沒有定義,那
么就使用上層的配置,否則使用當前層次的配置。
這些配置信息一般默認都應該設為一個未初始化的值,針對這個需求,Nginx定義了一系列的宏定義來代表各種配置所對應
數據類型的未初始化值,如下:

#define NGX_CONF_UNSET       -1
#define NGX_CONF_UNSET_UINT  (ngx_uint_t) -1
#define NGX_CONF_UNSET_PTR   (void *) -1
#define NGX_CONF_UNSET_SIZE  (size_t) -1
#define NGX_CONF_UNSET_MSEC  (ngx_msec_t) -1

模塊的定義

對于開發一個模塊來說,我們都需要定義一個ngx_module_t類型的變量來說明這個模塊本身的信息,從某種意義上來說,這是這個模塊最重要的一個信息,它告訴了nginx這個模塊的一些信息,上面定義的配置信息,還有模塊上下文信息,都是通過這個結構來告訴nginx系統的,也就是加載模塊的上層代碼,都需要通過定義的這個結構,來獲取這些信息。

ngx_module_t 原型:

typedef struct ngx_module_s          ngx_module_t;
struct ngx_module_s {ngx_uint_t            ctx_index;ngx_uint_t            index;char                 *name;ngx_uint_t            spare0;ngx_uint_t            spare1;ngx_uint_t            version;const char           *signature;void                 *ctx;ngx_command_t        *commands;ngx_uint_t            type;ngx_int_t           (*init_master)(ngx_log_t *log);ngx_int_t           (*init_module)(ngx_cycle_t *cycle);ngx_int_t           (*init_process)(ngx_cycle_t *cycle);ngx_int_t           (*init_thread)(ngx_cycle_t *cycle);void                (*exit_thread)(ngx_cycle_t *cycle);void                (*exit_process)(ngx_cycle_t *cycle);void                (*exit_master)(ngx_cycle_t *cycle);uintptr_t             spare_hook0;uintptr_t             spare_hook1;uintptr_t             spare_hook2;uintptr_t             spare_hook3;uintptr_t             spare_hook4;uintptr_t             spare_hook5;uintptr_t             spare_hook6;uintptr_t             spare_hook7;
};

模塊可以提供一些回調函數給nginx,當nginx在創建進程線程或者結束進程線程時進行調用。但大多數模塊在這些時刻并不需要做什么,所以都簡單賦值為NULL。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/164698.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/164698.shtml
英文地址,請注明出處:http://en.pswp.cn/news/164698.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

使用注解的AOP編程

使用注解的AOP編程 當注解沒有參數時 當使用注解進行面向切面編程(AOP)時,你可以按照以下步驟來實現: 步驟: 1. 創建自定義注解: 首先,創建自定義的注解,以便在代碼中標記需要進…

Excel換不了行怎么解決?

方法一: 使用Alt Enter鍵 在Excel中,輸入文字時按下回車鍵,光標將會移到下一個單元格,如果想要換行,可以嘗試使用Alt Enter鍵。具體操作如下: 1.在單元格中輸入文字; 2.想要換行時,在需要換行的位置按下Alt Enter鍵; 3…

延時任務定時發布,基于 Redis 與 DB 實現

目錄 1、什么是延時任務,分別可以使用哪些技術實現? 1.2 使用 Redis 和 DB 相結合的思路圖以及分析 2、實現添加任務、刪除任務、拉取任務 3、實現未來數據的定時更新 4、將數據庫中的任務數據,同步到 Redis 中 1、什么是延時任務&#xff…

網絡運維與網絡安全 學習筆記2023.11.23

網絡運維與網絡安全 學習筆記 第二十四天 今日目標 VRRP負載均衡、BFD原理與配置、BFD典型應用 DHCP工作原理、全局模式DHCP VRRP負載均衡 VRRP單組缺陷 每網段存在一個VRRP組,缺點如下: 主網關數據轉發壓力大 備份網關不轉發任何數據 網絡設備利用…

Hook技術(鉤子技術)

HOOK(鉤子技術) 這里的hook我理解的意思就是通過攔截指令,將指令換成自己想要的指令,從而做道繞過原本的程序指令,要修改這個指令,要用匯編技術,從二進制入手。 擴展: 木馬病毒之…

git clone慢的解決辦法

在網站 https://www.ipaddress.com/ 分別搜索: github.global.ssl.fastly.net github.com 得到ip: 打開hosts文件 sudo vim /etc/hosts 在hosts文件末尾添加 140.82.114.3 github.com 151.101.1.194 github.global-ssl.fastly.net 151.101.65.194 g…

外部網關協議_邊界網關協議BGP

一.邊界網關協議BGP的基本概念 邊界網關協議(Border Gateway Protocol,BGP)屬于外部網關協議EGP這個類別,用于自治系統AS之間的路由選擇協議。由于在不同AS內度量路由的“代價”(距離、帶寬、費用等)可能不同,因此對于…

elasticsearch 7安裝

問題提前報 max virtual memory areas error max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144] 如果您的環境是Linux,注意要做以下操作,否則es可能會啟動失敗 1 用編輯工具打開文件/etc/sysctl.conf 2 …

qml渲染引擎介紹

qml項目啟動入口 Qt Quick項目qml腳本在C++代碼里啟動,main.cpp如下: #include <QGuiApplication> #include <QQmlApplicationEngine>int main(int argc, char *argv[]) {

VUE excel表格導出

js代碼 //下載模板 downloadExl() { // 標題 const tHeader [‘xxx’,xxx,xx名稱,電槍xx,協議xx,snxx]; // key const filterVal [agentName, stationName, equName, channelNumber, manufacturer, sn, ]; // 值 const datas [ { agentName: 你好, stationName: 我們, e…

激光雷達與慣導標定 | Lidar_IMU_Init : 編譯

激光雷達與慣導標定&#xff1a;Lidar_IMU_Init 編譯 功能包安裝安裝ceres-solver-2.0.0 &#xff08;注意安裝2.2.0不行&#xff0c;必須要安裝2.0.0&#xff09; LI-Init是一種魯棒、實時的激光雷達慣性系統初始化方法。該方法可校準激光雷達與IMU之間的時間偏移量和外部參數…

unity shaderGraph實例-可交互瀑布

不要問我水在哪里&#xff0c;你自己相像這是一個瀑布&#xff0c;瀑布的效果我還不會做 效果展示 整體結構 這里片元著色器最后輸出的baseColor應該是黑色&#xff0c;白色為錯誤。 各區域內容 區域1 計算球到瀑布的距離&#xff0c;然后減去一個值&#xff0c;實現黑色區域…

UNETR:用于三維醫學圖像分割的Transformer

論文鏈接&#xff1a;https://arxiv.org/abs/2103.10504 代碼鏈接&#xff1a; https://monai.io/research/unetr 機構&#xff1a;Vanderbilt University, NVIDIA 最近琢磨不出來怎么把3d體數據和文本在cnn中融合&#xff0c;因為確實存在在2d里面用的transformer用在3d里面…

wpf使用CefSharp.OffScreen模擬網頁登錄,并獲取身份cookie,C#后臺執行js

目錄 框架信息&#xff1a;MainWindow.xamlMainWindow.xaml.cs爬取邏輯模擬登錄攔截請求Cookie獲取 CookieVisitorHandle 框架信息&#xff1a; CefSharp.OffScreen.NETCore 119.1.20 MainWindow.xaml <Window x:Class"Wpf_CHZC_Img_Identy_ApiDataGet.MainWindow&qu…

API自動化測試:如何構建高效的測試流程

一、引言 在當前的軟件開發環境中&#xff0c;API&#xff08;Application Programming Interface&#xff09;扮演了極為重要的角色&#xff0c;連接著應用的各個部分。對API進行自動化測試能夠提高測試效率&#xff0c;降低錯誤&#xff0c;確保軟件產品的質量。本文將通過實…

SpringMVC(三)

十、攔截器 1、攔截器的配置 SpringMVC中的攔截器用于攔截控制器方法的執行 SpringMVC中的攔截器需要實現HandlerInterceptor SpringMVC的攔截器必須在SpringMVC的配置文件中進行配置&#xff1a; <bean class"com.atguigu.interceptor.FirstInterceptor">…

constexpt

constexpt constexpt是C11引入的新的關鍵字&#xff0c;它用于在編譯時而非運行時計算函數或變量的值。這個特性對于提高程序效率和優化代非常有用。 編譯時常量和運行時常量 編譯時常量&#xff08;Compile-time Constants&#xff09;和運行時常量&#xff08;Runtime Con…

8年經驗之談 —— 如何使用自動化工具編寫測試用例?

以下為作者觀點&#xff0c;僅供參考&#xff1a; 在快速變化的軟件開發領域&#xff0c;保證應用程序的可靠性和質量至關重要。隨著應用程序復雜性和規模的不斷增加&#xff0c;僅手動測試無法滿足行業需求。 這就是測試自動化發揮作用的地方&#xff0c;它使軟件測試人員能…

leetcode做題筆記1410. HTML 實體解析器

「HTML 實體解析器」 是一種特殊的解析器&#xff0c;它將 HTML 代碼作為輸入&#xff0c;并用字符本身替換掉所有這些特殊的字符實體。 HTML 里這些特殊字符和它們對應的字符實體包括&#xff1a; 雙引號&#xff1a;字符實體為 &quot; &#xff0c;對應的字符是 "…

python appium 官網下載

找了半天吐了 https://github.com/appium/appium-desktop/releases/tag/v1.22.3-4