1. 程式人生 > >nginx配置解析之配置合併

nginx配置解析之配置合併

        上一篇文章分析了nginx.conf配置解析流程,解析完成後會把各個配置項存放到各個模組的上下文結構中。但此時還沒有對http模組、server模組、location模組公共部分進行合併處理。所謂的合併: server塊的模組上下文沒有值,則繼承http模組的模組上下文值。location塊的模組上下文沒有值,則繼承server塊模組上下文的值。接下來分析nginx是如何合併http模組、server模組、location模組公共部分。

        假設nginx.conf配置檔案結構如下

http
{	
	//server塊1
	server
	{
		//location塊1
		location
		{
		
		}
		//location塊2
		location
		{
		
		}
	}
	//server塊2
	server
	{
	
	}
}
        這是nginx.conf配置檔案的一個框架結構,其中省略了其他配置項。http模組下有兩個server塊。其中第一個server塊下還有兩個location塊。解析配置後,http模組的上下文結構如下圖:

        http塊下有兩個server塊,分別為server塊1,server塊2。這兩個server塊是通過陣列形式連線起來。http塊中的main_conf[0]核心模組上下文結構為ngx_http_core_main_conf_t,它的成員servers就是一個數組,存放這這兩個server塊。

        ngx_http_core_loc_conf_s結構中的成員locations是一個佇列,佇列元素為某個server塊下的各個location結構。圖中server塊1下有兩個location塊,server1塊loc_conf中的核心模組上下文結構的ocations,是由這兩個location塊組成的佇列。

        也就是說server塊是通過陣列串接起來的, location塊是通過連結串列串接起來的。

一、http塊與server塊的合併

        http塊與server塊的合併過程分析:包含server塊的合併,location塊的合併。

        (1)server塊的合併: 對於每一個模組,在每一個server塊中,找到模組在srv_conf中的位置,然後將該模組上下文與http塊中srv_conf對應模組所在位置模組上下文進行比較。如果server塊中的上下文沒有值,則使用http上下文的值,否則使用server塊中模組上下文自己的值。以ngx_core_module模組為例,這個模組是第一個模組,存放在srv_conf下標為0的位置。首先將server1塊中的srv_conf[0]與http塊的srv_conf[0]進行合併, 然後將server2塊中的srv_conf[0]與http塊的srv_conf[0]進行合併。這樣server塊的合併就完成了。

        (2)location塊的合併: 對於每一個模組,在每一個server塊中,找到模組在loc_conf中的位置,然後將該模組上下文與http塊中loc_conf對應模組所在模組上下文進行比較。如果location塊中的上下文沒有值,則使用http上下文中的值,否則使用location塊中模組上下文自己的值。以ngx_core_module模組為例,這個模組是第一個模組,存放在loc_conf下標為0的位置。首先將server1塊中的loc_conf[0]與http塊的loc_conf[0]進行合併, 然後將server2塊中的lco_conf[0]與http塊的loc_conf[0]進行合併。這樣loc塊的合併就完成了。

char * ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
    for (m = 0; ngx_modules[m]; m++) 
	{
        if (ngx_modules[m]->type != NGX_HTTP_MODULE) 
		{
            continue;
        }
		//(1)將http中的server與server塊的server合併
		//(2)將http中的loction與server塊的location合併
		//(3)將server塊中的location與localtion中的location合併
        rv = ngx_http_merge_servers(cf, cmcf, module, mi);
    }
}
        而其中的函式ngx_http_merge_servers負責具體的合併過程。這個函式一共使用了3個合併過程,先分來http塊與server的合併。
//cmcf = ctx->main_conf[ngx_http_core_module.ctx_index],其中ctx是http塊的ngx_http_conf_ctx_t結構
//module指的是模組上下文
//ctx_index指的是該模組在同一型別中的位置
static char * ngx_http_merge_servers(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf,
    ngx_http_module_t *module, ngx_uint_t ctx_index)
{
	//cscfp指向所有http塊下的所有server塊
    cscfp = cmcf->servers.elts;
	//ctx指向http塊的ngx_http_conf_ctx_t結構
    ctx = (ngx_http_conf_ctx_t *) cf->ctx;  
	//遍歷http塊下有所有server塊
    for (s = 0; s < cmcf->servers.nelts; s++) 
	{
		//指向每一個server塊中的srv_conf結構
        ctx->srv_conf = cscfp[s]->ctx->srv_conf;
        if (module->merge_srv_conf) 
		{
			//將http塊中的某個server與server塊中的某個server進行合併
			//saved.srv_conf[ctx_index]是http塊下的srv_conf中某個元素
			//cscfp[s]->ctx->srv_conf[ctx_index]是server塊下的srv_conf中某個元素
            rv = module->merge_srv_conf(cf, saved.srv_conf[ctx_index], cscfp[s]->ctx->srv_conf[ctx_index]);
         
        }

        if (module->merge_loc_conf) 
		{
            ctx->loc_conf = cscfp[s]->ctx->loc_conf;
			//將server塊中loc_conf的某個loc與http塊中loc_conf的某個loc合併
            rv = module->merge_loc_conf(cf, saved.loc_conf[ctx_index],  cscfp[s]->ctx->loc_conf[ctx_index]);
        }
    }
}
二、server塊與location塊的合併
        server塊與location塊合併的內容就比較少了,只需要將各個location塊中的loc_conf與server塊中的loc_conf進行合併。

        location塊的合併: 對於每一個模組,在每一個location塊中,找到模組在loc_conf中的位置,然後將該模組上下文與所屬server塊中loc_conf對應模組所在模組上下文進行比較。如果location塊中的上下文沒有值,則使用所屬server塊上下文中的值,否則使用location塊中模組上下文自己的值。以ngx_core_module模組為例,這個模組是第一個模組,存放在loc_conf下標為0的位置。首先將location1塊中的loc_conf[0]與server塊1的loc_conf[0]進行合併, 然後將locatio2塊中的lco_conf[0]與server1塊的loc_conf[0]進行合併。這樣loc塊的合併就完成了。


        函式ngx_http_merge_locations負責server塊與location塊的合併。當然如果location還巢狀location塊,則會遞迴合併location塊與location內的所有子locaton塊。

//locations為server塊中ngx_http_core_module的lociton中佇列
//loc_conf為server塊的loc_conf
//module為模組上下文
//ctx_index指module對應模組在同一類模組中的索引
static char * ngx_http_merge_locations(ngx_conf_t *cf, ngx_queue_t *locations,
    void **loc_conf, ngx_http_module_t *module, ngx_uint_t ctx_index)
{
    for (q = ngx_queue_head(locations);
         q != ngx_queue_sentinel(locations);
         q = ngx_queue_next(q))
    {
		//合併server塊與locatin塊中相應的location
		//loc_conf[ctx_index]為server塊中loc_conf的某個loc
		//clcf->loc_conf[ctx_index]為location塊中的loc_conf的某個loc
        rv = module->merge_loc_conf(cf, loc_conf[ctx_index], clcf->loc_conf[ctx_index]);

		//遞迴合併location塊下的location
		//clcf->locations為location塊中的loc_conf某個loc對應的佇列
		//clcf->loc_conf為location塊中的loc_conf
        rv = ngx_http_merge_locations(cf, clcf->locations, clcf->loc_conf, module, ctx_index);
    }
}
        最終ngx_core_module模組的合併結果如下:


        以上只是ngx_core_module模組的合併結果,其它模組合併的過程也是一樣的。最終一個for迴圈,就可以合併所有http模組。這樣每一個http模組的上下文結構都有值,這個值要麼來自nginx.conf配置檔案,要麼繼承上一層結構。


相關推薦

nginx配置解析配置合併

        上一篇文章分析了nginx.conf配置解析流程,解析完成後會把各個配置項存放到各個模組的上下文結構中。但此時還沒有對http模組、server模組、location模組公共部分進行合併處理。所謂的合併: server塊的模組上下文沒有值,則繼承http模組

nginx配置解析客戶端真實IP的傳遞

形式 bubuko 轉發 pre 反向代理 The 用戶 地址 添加 前後端分離之後,采用nginx作為靜態服務器,並通過反向代理的方式實現接口跨域的方式,在降低開發成本的同時也帶來了諸多問題,例如客戶端真實IP的獲取。 在一些特殊場景下,比如風控和支付流程,往往需要獲取用

Nginx(六)、配置解析location解析

  nginx成為非常流行的代理服務軟體,最根本的原因也許是在於其強悍效能。但還有一些必要的條件,比如功能的完整,配置的易用,能夠解決各種各樣的實際需求問題,這些是一個好的軟體的必備特性。   那麼,今天我們就來看看nginx配置的部分原則和解析原理吧。我們只做location部分的細節解析,但其他配置道理基

aserver配置解析單元化規則

最近有空把aserver的線上配置看了一遍,大體上了解了接入層對整個請求的流轉和控制。 aserver是tengine的一個分支,其中包含了很多的私有指令,不過大部分根據指令名稱也能猜出個大概。 本篇主要是講解一下單元化規則的相關內容。 我理解的單元化規則問題,就是當用戶請求過來的時候,as

Nginx入門筆記————配置檔案結構

Nginx入門筆記之————配置檔案結構   ... #全域性塊 events { #events塊 ... } http #http塊 { ... #http全域性塊 server #

[Vue CLI 3] 配置解析 css.extract

大家還記得我們在老版本中,對於線上環境配置中會把所有的 css 多打成一個檔案: 核心是使用了外掛 extract-text-webpack-plugin,方式如下: 第一步都是載入外掛 const ExtractTextPlugin = require('extr

Nginx深入學習配置詳解

A、正常執行的配置項 (1)Nginx worker程序執行的使用者及使用者組 語法: user username [groupname]; 預設: user nobody nobody;       user用於設定master程序啟動後,fork出的worker

[Vue CLI 3] 配置解析 parallel

官方文件中介紹過在 vue.config.js 檔案中可以配置 parallel,作用如下: 是否為 Babel 或 TypeScript 使用 thread-loader。 該選項在系統的 CPU 有多於一個核心時自動啟用,僅作用於生產構建 我們看一下原始碼部分: parallel 接受 boole

[Vue CLI 3] 配置解析 indexPath

=== amp .config 其他 tput compiler require 指定 .html 在 vue.config.js 配置中有一個 indexPath 的配置,我們先看看它有什麽用? 用來指定 index.html 最終生成的路徑(相對於 outputDir)

# Mybatis原始碼解析配置載入(二)

Mybatis原始碼解析之配置載入(二) 這一篇是承接上一篇文章Mybatis原始碼解析之配置載入(一),上一篇原本是想把整個配置載入都分析完全,然後發現內容還是比較多,所以決定分成兩篇來說好了,現在就開始剩下的配置分析。 配置載入 繼續回到parseConfigura

Mybatis原始碼解析配置載入(一)

Mybatis原始碼解析之配置載入(一) 用了好幾年的mybatis了,但是很少來鑽研mybatis原理所在,最近抽出空來,就把這一整套原始碼都研究了下,然後發現就是這些東西,mybatis沒啥難度,於是決定把研究的這一整套寫一個mybatis系列,記錄一下,在這些完了以後,順便寫一

Spring Boot參考教程(五)Spring Boot配置使用配置類用法

expr web程序 成功 驗證 pan hub parameter lan fix 4.2. SpringBoot配置使用之配置類使用 Spring Boot的大部分自動配置都可以滿足應用要求,但如果想精確的控制應用,或者想覆蓋自動配置,使用配置類是另一種很好的選擇,強調

Spring Boot參考教程(四)Spring Boot配置使用配置文件用法

point rop 推薦書 endpoint size int == 需要 相同 4.1 Spring Boot配置使用之配置文件用法 Spring Boot旨在簡化配置,但依然需要進行少量配置來滿足應用的特定需要。 配置方式拋棄了XML文件的配置方式,主要使用配置文件

RocketMQ4.2.0-引數配置解析-Producer配置-compressMsgBodyOverHowmuch

引數解析系列不會寫太多,看到哪兒寫到哪兒 根據RocketMQ3.2.4的開發手冊定義,compressMsgBodyOverHowmuch 是指 “訊息 Body 超過多大開始壓縮(Consumer 收到訊息會自動解壓縮),單位位元組”,預設是1024*4即4096 此引

Cloudera Manager5配置管理配置Namenode 的HA

此文章介紹Cloudera Manager配置Hive Metastore 1,環境資訊 2,配置Namenode 的HA 2,配置Namenode 的HA 2.1,進入HDFS介面,點選“啟用High Availability” 2.2,輸入

nginx 1.12 配置解析php

alt 配置解析 cgi fast file lan try_files 技術 cati server { listen 80; server_name foo.com; root /path; index index.html index

Nginx(五)-- 配置文件Rewrite

log 技術分享 判斷 placement ble png per 大小寫 遠程 Rewrite支持URL重寫 1.常用指令以及語法   1) if指令    if語法: if 空格 (condition) {}    條件:    1. &ld

Nginx服務器 Nginx的基本配置

connect cast body netmask gin 主機ip ash 操作 日誌輸出 本文使用 Linux centos系統 一、Nginx虛擬主機的配置 虛擬主機:通常情況下,為了使每個服務器可以供更多用戶使用,可以將一個服務器分為很多虛擬的子服務器,每個子服務器

NGINX——配置HTTPS加密反向代理訪問–自簽CA

left https rac lan -s tar 一個 eight fcm 轉載請註明出處:http://blog.csdn.net/l1028386804/article/details/46695495 出於公司內部訪問考慮,採用的CA是本機Openssl

nsq源碼閱讀筆記nsqd(一)——nsqd的配置解析和初始化

con views pos 直接 rgba 函數調用 程序 spa 重命名 配置解析nsqd的主函數位於apps/nsqd.go中的main函數首先main函數調用nsqFlagset和Parse進行命令行參數集初始化, 然後判斷version參數是否存在,若存在,則打印版