Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 老年人一级毛片,国产亚洲精品网站,韩国黄色三级视频

          整合營(yíng)銷(xiāo)服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費(fèi)咨詢熱線:

          nginx的http塊配置項(xiàng)有哪些?

          nginx的http塊配置項(xiàng)有哪些?

          ain配置項(xiàng)

          1. worker_processes:nginx的worker進(jìn)程數(shù),默認(rèn)為auto,表示根據(jù)系統(tǒng)CPU核數(shù)來(lái)設(shè)置。
          2. worker_connections:每個(gè)worker進(jìn)程能夠同時(shí)處理的最大連接數(shù),默認(rèn)為512。
          3. keepalive_timeout:長(zhǎng)連接的超時(shí)時(shí)間,即客戶端與服務(wù)器保持連接的時(shí)間,超過(guò)該時(shí)間則關(guān)閉連接。
          4. server_names_hash_bucket_size:用于存儲(chǔ)虛擬主機(jī)的hash桶大小,默認(rèn)為32或64,根據(jù)服務(wù)器的虛擬主機(jī)數(shù)量來(lái)設(shè)置。
          5. client_header_buffer_size:nginx服務(wù)器接收客戶端請(qǐng)求頭的緩沖區(qū)大小,默認(rèn)為1K。

          下面是一個(gè)完整的 http 塊的配置示例:

          http {
              # 設(shè)置worker進(jìn)程數(shù)
              worker_processes auto;
          
              # 設(shè)置每個(gè)worker進(jìn)程最大連接數(shù)
              worker_connections 512;
          
              # 設(shè)置長(zhǎng)連接超時(shí)時(shí)間
              keepalive_timeout 65;
          
              # 設(shè)置server_name的hash桶大小
              server_names_hash_bucket_size 128;
          
              # 設(shè)置客戶端請(qǐng)求頭緩沖區(qū)大小
              client_header_buffer_size 2k;
          }

          server配置項(xiàng)

          用于配置具體的虛擬主機(jī),包括監(jiān)聽(tīng)的端口、域名、SSL證書(shū)、反向代理等。主要的server配置項(xiàng)包括:

          1. listen:指定server監(jiān)聽(tīng)的端口和IP地址。
          2. server_name:指定虛擬主機(jī)的域名,可以設(shè)置多個(gè)域名,用空格分隔。
          3. root:指定網(wǎng)站的根目錄,用于存放靜態(tài)文件。
          4. index:指定默認(rèn)的首頁(yè)文件。
          5. access_log:指定訪問(wèn)日志的保存路徑和格式。
          6. error_log:指定錯(cuò)誤日志的保存路徑和格式。
          7. location:用于配置請(qǐng)求的處理規(guī)則,可以包括正則表達(dá)式、反向代理等。

          下面是一個(gè)簡(jiǎn)單的server塊的配置示例:

          server {
              # 監(jiān)聽(tīng)的端口和IP地址
              listen 80;
          
              # 指定虛擬主機(jī)的域名
              server_name example.com www.example.com;
          
              # 網(wǎng)站的根目錄
              root /var/www/example.com;
          
              # 默認(rèn)的首頁(yè)文件
              index index.html;
          
              # 訪問(wèn)日志的保存路徑和格式
              access_log /var/log/nginx/example.access.log combined;
          
              # 錯(cuò)誤日志的保存路徑和格式
              error_log /var/log/nginx/example.error.log;

          location配置項(xiàng):

          1. location:用于匹配請(qǐng)求URI,可以使用正則表達(dá)式或者精確匹配字符串。例如:
          location /images/ {
              root /data/www;
          }
          
          1. alias:用于指定文件系統(tǒng)路徑,可以使用正則表達(dá)式或者精確匹配字符串。例如:
          location /images/ {
              alias /data/www/images/;
          }
          
          1. if:用于判斷某個(gè)條件是否成立,如果成立則執(zhí)行特定的操作。例如:
          location / {
              if ($request_method=POST) {
                  return 405;
              }
          }
          
          1. limit_except:用于限制請(qǐng)求方法。例如:
          location / {
              limit_except GET POST {
                  deny all;
              }
          }
          
          1. proxy_pass:用于反向代理。例如:
          location / {
              proxy_pass http://backend;
          }
          
          1. root:用于指定根目錄。例如:
          location / {
              root /data/www;
          }
          
          1. try_files:用于按照指定的順序查找文件。例如:
          location / {
              try_files $uri $uri/ /index.html;
          }
          
          1. rewrite:用于重寫(xiě)URI。例如:
          location / {
              rewrite ^/admin/(.*)$ /$1 break;
          }
          
          1. error_page:用于指定錯(cuò)誤頁(yè)面。例如:

          . Nginx模塊

          1.1 Nginx中的模塊化設(shè)計(jì)

          Nginx 的內(nèi)部結(jié)構(gòu)是由核心部分和一系列的功能模塊所組成。這樣劃分是為了使得每個(gè)模塊的功能相對(duì)簡(jiǎn)單,便于開(kāi)發(fā),同時(shí)也便于對(duì)系統(tǒng)進(jìn)行功能擴(kuò)展。Nginx 將各功能模塊組織成一條鏈,當(dāng)有請(qǐng)求到達(dá)的時(shí)候,請(qǐng)求依次經(jīng)過(guò)這條鏈上的部分或者全部模塊,進(jìn)行處理。例如前面講到的 http 請(qǐng)求,會(huì)有11個(gè)處理階段,而每個(gè)階段有對(duì)應(yīng)著許多在此階段生效的模塊對(duì)該 http 請(qǐng)求進(jìn)行處理。同時(shí),Nginx 開(kāi)放了第三方模塊編寫(xiě)功能,用戶可以自定義模塊,控制 http 請(qǐng)求的處理與響應(yīng),這種高度可定制化催生了 Nginx 的大量第三方模塊,也使得 Nginx 定制化開(kāi)發(fā)在各大互聯(lián)網(wǎng)公司十分流行。

          1.2 Nginx中的模塊分類(lèi)

          關(guān)于 Nginx 模塊的分類(lèi)有很多種方式,目前網(wǎng)上博客中寫(xiě)的較多的是按照功能進(jìn)行分類(lèi),有如下幾大類(lèi):

          • event 模塊: 搭建 獨(dú)立于操作系統(tǒng)的事件處理機(jī)制的框架,以及 提供各種具體事件的處理。代表性的模塊有:ngx_events_module, ngx_event_core_module, ngx_epoll_module;
          • handler 模塊: 主要負(fù)責(zé)處理客戶端請(qǐng)求并產(chǎn)生待響應(yīng)的內(nèi)容,比如 ngx_http_static_module 模塊,負(fù)責(zé)客戶端的靜態(tài)頁(yè)面請(qǐng)求處理并將對(duì)應(yīng)的磁盤(pán) 文件準(zhǔn)備為響應(yīng)內(nèi)容輸出;
          • filter 模塊: 主要 負(fù)責(zé)處理輸出的內(nèi)容,包括修改輸出內(nèi)容。代表性的模塊有: ngx_http_sub_module;
          • upstream 模塊: 該類(lèi)模塊都是用于實(shí)現(xiàn)反向代理功能,將真正的請(qǐng)求轉(zhuǎn)發(fā)到后端服務(wù)器上,并從后端服務(wù)器上讀取響應(yīng),發(fā)回給客戶端。比如前面介紹到轉(zhuǎn)發(fā) http、websocket、grpc、rtmp等協(xié)議的模塊都可以劃分為這一類(lèi);
          • 負(fù)載均衡模塊: 負(fù)載均衡的模塊,實(shí)現(xiàn)相應(yīng)算法。這類(lèi)模塊都是用于實(shí)現(xiàn) Nginx 的負(fù)載均衡功能。
          • extend 模塊: 又稱(chēng)第三方模塊,非 Nginx 官方提供,由各大企業(yè)的開(kāi)發(fā)人員結(jié)合自身業(yè)務(wù)開(kāi)發(fā)而成。Nginx 提供了非常好的模塊編寫(xiě)機(jī)制,遵循相關(guān)的標(biāo)準(zhǔn)可以很快定制出符合我們業(yè)務(wù)場(chǎng)景的模塊,而且內(nèi)部調(diào)用 Nginx 內(nèi)部提供的方法進(jìn)行處理,使得第三方模塊往往都具備很好的性能

          對(duì)于官方提供的模塊,我們可以直接在官網(wǎng)文檔上學(xué)習(xí),學(xué)習(xí)的方式和學(xué)習(xí)其他互聯(lián)網(wǎng)組件的方式一致,首先學(xué)習(xí)如何使用,在用至熟練后可以深入分析其源碼了解功能實(shí)現(xiàn)背后的原理。

          我們以前面介紹到的 Nginx 的限速模塊(limit_req模塊)進(jìn)行說(shuō)明。首先是掌握該模塊的用法,在該模塊的官方地址中,有關(guān)于該模塊的詳細(xì)介紹,包括該模塊提供的所有指令以及所有變量說(shuō)明。此外,還有比較豐富的指令用例。在多次使用該指令并自認(rèn)為掌握了該模塊的用法之后,想了解限速背后的原理以及相關(guān)算法時(shí),就可以深入到源碼學(xué)習(xí)了。

          進(jìn)入 Nginx 的源碼目錄,使用ls查看源碼文件,限速模塊是在 http 目錄中的。

          [root@server nginx-1.17.6]# cd src/
          
          [root@server src]# ls
          core  event  http  mail  misc  os  stream
          
          [root@server src]# ls http/modules/ngx_http_limit_*.c
          http/modules/ngx_http_limit_conn_module.c
          http/modules/ngx_http_limit_req_module.c
          代碼塊12345678

          找到 Nginx 模塊對(duì)應(yīng)的代碼文件后,我們就可以閱讀里面的代碼進(jìn)行學(xué)習(xí)。往往源碼的閱讀是枯燥無(wú)味的,我們可以借助海量的網(wǎng)絡(luò)資源輔助我們學(xué)習(xí)。這里就有一篇文章,作者深入分析了 Nginx 的限流模塊的源碼以及相應(yīng)限流算法,最后進(jìn)行了相關(guān)的實(shí)驗(yàn)測(cè)試。通過(guò)這樣一個(gè)個(gè)模塊深入學(xué)習(xí),最后在使用每一個(gè) Nginx 指令時(shí),也會(huì)非常熟練,最后成為 Nginx 高手。

          1.3 如何學(xué)習(xí)和使用第三方模塊

          這里我們演示在 Nginx 中使用第三方模塊。 Openresty 社區(qū)提供了一款 Nginx 中的 Echo 模塊,即echo-nginx-module。在 Nginx 中添加了該模塊后,我們?cè)谂渲梦募锌梢允褂迷撃K提供的 echo 指令返回用戶響應(yīng),簡(jiǎn)單方便。該模塊的源碼在 github 上,并且有良好的文檔和使用示例,非常方便開(kāi)發(fā)者使用。

          現(xiàn)在我們?cè)?Nginx 的源碼編譯階段加入該第三方模塊,具體操作如下:

          [root@server shencong]# pwd
          /root/shencong
          [root@server shencong]# mkdir nginx-echo
          # 下載 nginx 源碼包和第三方模塊的源碼包 
          [root@server shencong]# wget http://nginx.org/download/nginx-1.17.6.tar.gz
          [root@server shencong]# wget https://github.com/openresty/echo-nginx-module/archive/v0.62rc1.tar.gz
          
          # 解壓
          [root@server shencong]# tar -xzf nginx-1.17.6.tar.gz
          [root@server shencong]# tar -xzf v0.62rc1.tar.gz
          
          [root@server shencong]# ls
          echo-nginx-module-0.62rc1  nginx-1.17.6  nginx-1.17.6.tar.gz  nginx-echo  v0.62rc1.tar.gz
          
          [root@server shencong]# cd nginx-1.17.6
          # 使用--add-module添加第三方模塊,參數(shù)為第三方模塊源碼
          [root@server shencong]# ./configure --prefix=/root/shencong/nginx-echo  --add-module=/root/shencong/echo-nginx-module-0.62rc1
          

          編譯完成后,我們就可以去nginx-echo目錄中的 nginx.conf文件中添加echo 指令 。準(zhǔn)備如下的配置(可以參參考社區(qū)提供的示例):

          ...
          http {
             server {
                  listen       80;
                  server_name  localhost;
          
                  #charset koi8-r;
          
                  #access_log  logs/host.access.log  main;
          
                  location / {
                      root   html;
                      index  index.html index.htm;
                  }
                  
                  # 新增測(cè)試 echo 指令配置
                  location /timed_hello {
                      default_type text/plain;
                      echo_reset_timer;
                      echo hello world;
                      echo "'hello world' takes about $echo_timer_elapsed sec.";
                      echo hiya igor;
                      echo "'hiya igor' takes about $echo_timer_elapsed sec.";
                  }
          
                  location /echo_with_sleep {
                      default_type text/plain;
                      echo hello world;
                      echo_flush;  # ensure the client can see previous output immediately
                      echo_sleep   2.5;  # in sec
                      echo "'hello' takes about $echo_timer_elapsed sec.";
                  }
          
              }
          }
          ...
          

          啟動(dòng) Nginx 后,我們就可以在瀏覽器上請(qǐng)求者兩個(gè) URI 地址,看到相應(yīng) echo 返回的信息了。第二個(gè)配置是使用了 echo_sleep 指令,會(huì)使得請(qǐng)求在休眠 2.5s 后才返回。

          1.4 如何編寫(xiě)自己的模塊

          想要編寫(xiě) Nginx 模塊,首先需要對(duì) Nginx 模塊中的源碼以及相關(guān)的數(shù)據(jù)結(jié)構(gòu)有所了解,還要知曉 Nginx HTTP 模塊的調(diào)用流程。假設(shè)我要實(shí)現(xiàn)前面第三方模塊Echo的最簡(jiǎn)單形式,即只輸出相應(yīng)的字符串即可。假定模塊支持的指令名稱(chēng)還是 echo, 這個(gè) echo 指令需要跟一個(gè)參數(shù),即輸出的字符串。我們需要做如下幾步:

          • 確定模塊名稱(chēng),以及模塊中的指令以及參數(shù),還有運(yùn)行的環(huán)境。這里涉及的結(jié)構(gòu)是 ngx_command_t,它定義了模塊里的所有指令格式。下面的代碼表示該模塊中只有一個(gè) echo 指令,它出現(xiàn)的上下文環(huán)境為 location,且有一個(gè)參數(shù)(NGX_CONF_TAKE1)。當(dāng)某個(gè)配置塊中出現(xiàn)echo指令時(shí),Nginx 將調(diào)用ngx_http_echo方法。然后在該方法中,會(huì)設(shè)置處理請(qǐng)求的 handler,這個(gè) handler 就是處理請(qǐng)求的方法。
            static ngx_command_t  ngx_http_echo_commands[]={  
                   { ngx_string("echo"),      /* 指令名稱(chēng),利用ngx_string宏定義 */
                    NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,  /* 用在 location 指令塊內(nèi),且有1個(gè)參數(shù) */
                    ngx_http_echo,            /* 處理回調(diào)函數(shù) */
                    NGX_HTTP_LOC_CONF_OFFSET,    
                    offsetof(ngx_http_echo_loc_conf_t, ed), /* 指定參數(shù)讀取位置 */
                    NULL },
                    ngx_null_command
            };
          
          • 完成請(qǐng)求處理的 handler 函數(shù),最重要的部分就在這里;
           static char *
           ngx_http_echo(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
           {
               ngx_http_core_loc_conf_t  *clcf;
               /* 找到指令所屬的配置塊,這里我們限定echo指令的上下文環(huán)境只有l(wèi)ocation */
               clcf=ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
               /* 指定處理的handler */
               clcf->handler=ngx_http_echo_handler;
               ...
               return NGX_CONF_OK;
           }
           
           static ngx_int_t
           ngx_http_echo_handler(ngx_http_request_t *r)
           {
               ...
               
               /* 向用戶發(fā)送相應(yīng)包 */
               return ngx_http_output_filter(r, &out);
           }
          
          • 一些收尾工作,比如配置模塊介入 http 請(qǐng)求的哪些階段等。
            /* Http context of the module */
            static ngx_http_module_t  ngx_http_echo_module_ctx={
                NULL,                                  /* preconfiguration */
                NULL,                                  /* postconfiguration */
                NULL,                                  /* create main configuration */
                NULL,                                  /* init main configuration */
                NULL,                                  /* create server configuration */
                NULL,                                  /* merge server configuration */
                ngx_http_echo_create_loc_conf,         /* create location configration */
                ngx_http_echo_merge_loc_conf           /* merge location configration */
            };
            /* Module */
            ngx_module_t  ngx_http_echo_module={
                NGX_MODULE_V1,
                &ngx_http_echo_module_ctx,             /* module context */
                ngx_http_echo_commands,                /* module directives */
                NGX_HTTP_MODULE,                       /* module type */
                NULL,                                  /* init master */
                NULL,                                  /* init module */
                NULL,                                  /* init process */
                NULL,                                  /* init thread */
                NULL,                                  /* exit thread */
                NULL,                                  /* exit process */
                NULL,                                  /* exit master */
                NGX_MODULE_V1_PADDING
            };
          

          完成以上幾步,一個(gè)簡(jiǎn)易的自定義模塊就算大功告成了。接下來(lái)我們動(dòng)手完成第一個(gè)自定義的模塊,將其編譯進(jìn)Nginx 二進(jìn)制文件中并進(jìn)行測(cè)試。

          2. 案例

          我們來(lái)完成一個(gè)簡(jiǎn)單的自定義 http 模塊,來(lái)實(shí)現(xiàn)前面Echo模塊的最簡(jiǎn)單形式,即使用指令輸出 “hello, world” 字符串。首先新建一個(gè)目錄echo-nginx-module,然后在目錄下新建兩個(gè)文件configngx_http_echo_module.c

          [root@server echo-nginx-module]# pwd
          /root/shencong/echo-nginx-module
          
          [root@server echo-nginx-module]# ls
          config  ngx_http_echo_module.c
          

          兩個(gè)文件內(nèi)容分別如下:

          [root@server echo-nginx-module]# cat config 
          ngx_addon_name=ngx_http_echo_module
          # 指定模塊名稱(chēng)
          HTTP_MODULES="$HTTP_MODULES ngx_http_echo_module"
          # 指定模塊源碼路徑
          NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_echo_module.c"
          
          [root@server echo-nginx-module]# cat ngx_http_echo_module.c
          #include <ngx_config.h>
          #include <ngx_core.h>
          #include <ngx_http.h>
          
          /* Module config */
          typedef struct {
              ngx_str_t  ed;
          } ngx_http_echo_loc_conf_t;
          
          static char *ngx_http_echo(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
          static void *ngx_http_echo_create_loc_conf(ngx_conf_t *cf);
          static char *ngx_http_echo_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child);
          
          /* 定義指令 */
          static ngx_command_t  ngx_http_echo_commands[]={
              { ngx_string("echo"),      /* 指令名稱(chēng),利用ngx_string宏定義 */
                  NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,  /* 用在 location 指令塊內(nèi),且有1個(gè)參數(shù) */
                  ngx_http_echo,         /* 處理回調(diào)函數(shù) */
                  NGX_HTTP_LOC_CONF_OFFSET,    
                  offsetof(ngx_http_echo_loc_conf_t, ed), /* 指定參數(shù)讀取位置 */
                  NULL },
                  ngx_null_command
          };
          /* Http context of the module */
          static ngx_http_module_t  ngx_http_echo_module_ctx={
              NULL,                                  /* preconfiguration */
              NULL,                                  /* postconfiguration */
              NULL,                                  /* create main configuration */
              NULL,                                  /* init main configuration */
              NULL,                                  /* create server configuration */
              NULL,                                  /* merge server configuration */
              ngx_http_echo_create_loc_conf,         /* create location configration */
              ngx_http_echo_merge_loc_conf           /* merge location configration */
          };
          /* Module */
          ngx_module_t  ngx_http_echo_module={
              NGX_MODULE_V1,
              &ngx_http_echo_module_ctx,             /* module context */
              ngx_http_echo_commands,                /* module directives */
              NGX_HTTP_MODULE,                       /* module type */
              NULL,                                  /* init master */
              NULL,                                  /* init module */
              NULL,                                  /* init process */
              NULL,                                  /* init thread */
              NULL,                                  /* exit thread */
              NULL,                                  /* exit process */
              NULL,                                  /* exit master */
              NGX_MODULE_V1_PADDING
          };
          /* Handler function */
          static ngx_int_t
          ngx_http_echo_handler(ngx_http_request_t *r)
          {
              ngx_int_t rc;
              ngx_buf_t *b;
              ngx_chain_t out;
              ngx_http_echo_loc_conf_t *elcf;
              /* 獲取指令的參數(shù) */
              elcf=ngx_http_get_module_loc_conf(r, ngx_http_echo_module);
              if(!(r->method & (NGX_HTTP_HEAD|NGX_HTTP_GET|NGX_HTTP_POST)))
              {
                  /* 如果不是 HEAD/GET/PUT 請(qǐng)求,則返回405 Not Allowed錯(cuò)誤 */
                  return NGX_HTTP_NOT_ALLOWED;
              }
              r->headers_out.content_type.len=sizeof("text/html") - 1;
              r->headers_out.content_type.data=(u_char *) "text/html";
              r->headers_out.status=NGX_HTTP_OK;
              r->headers_out.content_length_n=elcf->ed.len;
              if(r->method==NGX_HTTP_HEAD)
              {
                  rc=ngx_http_send_header(r);
                  if(rc !=NGX_OK)
                  {
                      return rc;
                  }
              }
              b=ngx_pcalloc(r->pool, sizeof(ngx_buf_t));
              if(b==NULL)
              {
                  ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Failed to allocate response buffer.");
                  return NGX_HTTP_INTERNAL_SERVER_ERROR;
              }
              out.buf=b;
              out.next=NULL;
              b->pos=elcf->ed.data;
              b->last=elcf->ed.data + (elcf->ed.len);
              b->memory=1;
              b->last_buf=1;
              rc=ngx_http_send_header(r);
              if(rc !=NGX_OK)
              {
                  return rc;
              }
              /* 向用戶發(fā)送相應(yīng)包 */
              return ngx_http_output_filter(r, &out);
          }
          static char *
          ngx_http_echo(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
          {
              ngx_http_core_loc_conf_t  *clcf;
              clcf=ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
              /* 指定處理的handler */
              clcf->handler=ngx_http_echo_handler;
              ngx_conf_set_str_slot(cf,cmd,conf);
              return NGX_CONF_OK;
          }
          static void *
          ngx_http_echo_create_loc_conf(ngx_conf_t *cf)
          {
              ngx_http_echo_loc_conf_t  *conf;
              conf=ngx_pcalloc(cf->pool, sizeof(ngx_http_echo_loc_conf_t));
              if (conf==NULL) {
                  return NGX_CONF_ERROR;
              }
              conf->ed.len=0;
              conf->ed.data=NULL;
              return conf;
          }
          static char *
          ngx_http_echo_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
          {
              ngx_http_echo_loc_conf_t *prev=parent;
              ngx_http_echo_loc_conf_t *conf=child;
              ngx_conf_merge_str_value(conf->ed, prev->ed, "");
              return NGX_CONF_OK;
          }
          

          這樣一個(gè)第三方模塊包就完成了,接下來(lái)我們要向之前使用第三方模塊一樣,將它編譯進(jìn) Nginx,具體操作如下。

          [root@server shencong]# cd nginx-1.17.6/
          [root@server nginx-1.17.6]# ./configure --prefix=/root/shencong/nginx-echo --add-module=/root/shencong/echo-nginx-module
          ...
          [root@server nginx-1.17.6] # make && make install
          ...
          [root@server nginx-1.17.6]# cd ../nginx-echo/sbin/
          [root@server sbin]# ./nginx -V
          nginx version: nginx/1.17.6
          built by gcc 4.8.5 20150623 (Red Hat 4.8.5-39) (GCC) 
          configure arguments: --prefix=/root/shencong/nginx-echo --add-module=/root/shencong/echo-nginx-module
          

          接下來(lái),我們只要在 nginx.conf 中加入我們的指令,并給一個(gè)參數(shù),就能看到我們自定義的輸出了。

          ...
          http {
             ...
             server {
                 listen       80;
                 server_name  localhost;
                 location / {
                      root   html;
                      index  index.html index.htm;
                 }
                 
                 location /test {
                      echo hello,world;
                 }
                 ...
             }
          }
          ...
          

          最后我們請(qǐng)求主機(jī)的80端口,URI=/test,瀏覽器輸出"hello, world",說(shuō)明我們的自定義模塊成功了!

          3. 小結(jié)

          在 Nginx 基礎(chǔ)架構(gòu)介紹的最后,主要是介紹了 Nginx 的模塊設(shè)計(jì)以及相應(yīng)的模塊用法。最后,我們簡(jiǎn)單給出了一個(gè)簡(jiǎn)單編寫(xiě)自己模塊的案例作為本章的實(shí)戰(zhàn)案例。希望這一節(jié)之后,大家能對(duì) Nginx 的模塊化設(shè)計(jì)有所了解,并有興趣在模塊的源碼方向深入學(xué)習(xí)。

          篇介紹比較基礎(chǔ)的Nginx常用命令及配置。

          啟動(dòng)、檢查、重啟及關(guān)閉命令

          #假設(shè)Nginx的安裝目錄為
          /home/nginx/nginx/
          
          #啟動(dòng)命令
          /home/nginx/nginx/sbin/nginx -c /home/nginx/nginx/conf/nginx.conf
          #狀態(tài)檢查
          /home/nginx/nginx/sbin/nginx -t
          #重新加載配置
          /home/nginx/nginx/sbin/nginx -s reload
          
          #關(guān)閉
          #查詢nginx主進(jìn)程號(hào) 
          ps -ef | grep nginx
          #從容停止   
          kill -QUIT 主進(jìn)程號(hào)
          #快速停止   
          kill -TERM 主進(jìn)程號(hào)
          #強(qiáng)制停止   
          kill -9 主進(jìn)程號(hào)
          
          #若nginx.conf配置了pid文件路徑,如果沒(méi)有,則在logs目錄下
          kill -信號(hào)類(lèi)型 '/usr/local/nginx/logs/nginx.pid'

          基礎(chǔ)配置

          events事件驅(qū)動(dòng)配置

          • use指令
          • worker_connections指令
          • accept_mutex指令
          events {
          	use epoll;										#使用epoll類(lèi)型的IO多路復(fù)用模型,性能比select高
            worker_connections 204800;		#Worker進(jìn)程能夠打開(kāi)的最大并發(fā)連接數(shù)
            accept_mutex on;							#各個(gè)Worker進(jìn)程通過(guò)鎖來(lái)獲取新連接
          }

          server虛擬主機(jī)配置

          server {
          	listen	80;
            server_name admin.cloudxue.com;		#后臺(tái)管理服務(wù)的域名前綴
            location / {
            	default_type 'text/html';
              charset utf-8;
              echo "this is admin server";
            }
          }
          
          server {
          	listen	80;
            server_name file.cloudxue.com;		#文件服務(wù)的域名前綴
            location / {
            	default_type 'text/html';
              charset utf-8;
              echo "this is file server";
            }
          }
          
          server {
          	listen	80 default;
            server_name cloudxue.com *.cloudxue.com;		#若未指定前綴,配置默認(rèn)訪問(wèn)的虛擬主機(jī)
            location / {
            	default_type 'text/html';
              charset utf-8;
              echo "this is default server";
            }
          }

          多個(gè)虛擬主機(jī)之間根絕server_name匹配的優(yōu)先級(jí)從高到低:

          • 精確匹配
          • 左側(cè)通配符匹配
          • 右側(cè)通配符匹配
          • 正則表達(dá)式匹配
          • defalt_server:在listen指令后面如果帶有default指令參數(shù),表示默認(rèn)的、最后兜底的虛擬主機(jī)。

          錯(cuò)誤頁(yè)面配置

          error_page指令,該指令可用于http、server、location、if in location等上下文。

          server {
          	listen			80;
            server_name admin.cloudxue.com;		#后臺(tái)管理服務(wù)的域名前綴
            root 				/usr/local/openresty/www;
            
            location / {
            	default_type 'text/html';
              charset utf-8;
              echo "this is admin server";
            }
            
            #設(shè)置錯(cuò)誤頁(yè)面
            #error_page 404 /404.html;
            error_page 404=200 /404.html			#防止404頁(yè)面被劫持
            error_page 500 502 503 504 /50x.html;
          }

          長(zhǎng)鏈接配置

          keepalive_timeout	75;				#長(zhǎng)鏈接有效時(shí)長(zhǎng),0表示禁用長(zhǎng)鏈接,默認(rèn)75秒
          keepalive_requests	100;		#一條長(zhǎng)鏈接上允許被請(qǐng)求的資源的最大數(shù)量,默認(rèn)100

          訪問(wèn)日志配置

          access_log path [format [buffer=size] [gzip[=level]] [flush=time] [if=condition]];

          http {
            #先定義日志格式,名為為
          	log_format  format_main  '$remote_addr - $remote_user [$time_local] "$request" '
                               '$status $body_bytes_sent "$http_referer" '
                               '"$http_user_agent" "$http_x_forwarded_for"';
            #日志文件、日志訪問(wèn)格式
            access_log	logs/access_main.log format_main;
          }

          location路由規(guī)則配置

          • 精確匹配:標(biāo)記符號(hào)為"="
          • 普通匹配:標(biāo)記符號(hào)為"^~"。是Nginx默認(rèn)的匹配類(lèi)型,標(biāo)記符號(hào)可以省略。如果一個(gè)URL命中多個(gè)普通匹配,則最長(zhǎng)的location普通匹配獲勝。
          • 正則匹配:標(biāo)記符號(hào)為"~"、 "~*"、 "!~"、 "!~*"。若配置文件中有多個(gè)正則匹配location,只要匹配到第一個(gè)正則類(lèi)型的location就停止匹配。正則匹配與location規(guī)則定義在配置文件中的先后順序強(qiáng)相關(guān)。
          • 默認(rèn)匹配:標(biāo)記符號(hào)為"/"。通常用來(lái)配置默認(rèn)靜態(tài)頁(yè)(index.html)。

          rewrite模塊指令配置

          Nginx的rewrite模塊即ngx_http_rewrite_module標(biāo)準(zhǔn)模塊,默認(rèn)安裝的模塊。主要功能是對(duì)URI進(jìn)行重寫(xiě),然后再一次進(jìn)行l(wèi)ocation匹配或者直接進(jìn)行30X重定向返回給客戶端。

          • set指令:用于向變量賦值。當(dāng)變量存在時(shí)就賦值,不存在時(shí),先創(chuàng)建再賦值。創(chuàng)建后的可見(jiàn)范圍為Nginx整個(gè)配置
          set	$variable	value
          
          #實(shí)例
          set	$a "foo";
          set $b "$a, $a";
          • rewrite指令:主要功能是重寫(xiě)URI。
          rewrite regrex replacement [flag];
          
          #實(shí)例
          location /download/ {
          	rewrite ^/download/(.*)/video/(.*)$	/view/$1/mp3/$2.mp3/	last;
            rewrite ^/download/(.*)/audio/(.*)$	/view/$1/mp3/$2.rmvb/	last;
            return 404;
          }
          
          location /view {
          	echo "uri: $uri ";
          }
          
          #訪問(wèn)如下地址
          curl http://demo.cloudxue.com/download/1/video/10
          
          #rewrite模塊進(jìn)行匹配后,占位變量$1的值為1, $2的值為10
          uri: /view/1/mp3/10.mp3

          如果同一個(gè)上下文中出現(xiàn)多個(gè)rewrite指令,匹配會(huì)按照rewrite指令出現(xiàn)的順序先后依次進(jìn)行下去,匹配成功后并不會(huì)終止,而是繼續(xù)往下匹配,知道返回最后一個(gè)匹配為止。可以通過(guò)指令參數(shù)flag控制是否中途停止匹配,假設(shè)在location上下文中:

          • last:停止rewrite匹配,使用當(dāng)前計(jì)算后的新URI進(jìn)行l(wèi)ocation匹配和跳轉(zhuǎn)。
            • break:停止rewrite匹配,但是不進(jìn)行l(wèi)ocation跳轉(zhuǎn)。
          • redirect:外部重定向,返回302響應(yīng)碼
            • permanent:服務(wù)器將新URI地址返回給客戶端瀏覽器,并返回301響應(yīng)碼給客戶端,客戶端使用新地址再發(fā)一次請(qǐng)求(地址欄會(huì)變)

          注意事項(xiàng):

          • last和break的區(qū)別僅僅發(fā)生在location上下文中,如果發(fā)生在server上下文,那么last和break的作用是一樣的。
          • location上下文中的rewrite指令使用last指令參數(shù)會(huì)再次以新的URI重新發(fā)起內(nèi)部重定向,再次進(jìn)行l(wèi)ocation匹配,而新的URI若和舊的URI一樣,會(huì)發(fā)生死循環(huán)。當(dāng)循環(huán)發(fā)生到第10次時(shí),Nginx會(huì)終止這樣無(wú)意義的循環(huán),并返回500錯(cuò)誤。
          • if指令:相當(dāng)于引入了一個(gè)新的上下文作用于,適用于server、location兩個(gè)上下文。
          if (condition) {...}
          #實(shí)例
          location /if_demo {
            if ($http_user_agent ~*"Firefox") { 	#匹配Firefox瀏覽器
            	return 403;
            }
            if ($http_user_agent ~*"Chrome") { 	  #匹配Chrome瀏覽器
            	return 301;
            }
            if ($http_user_agent ~*"iphone") { 	  #匹配iPhone手機(jī)
            	return 302;
            }
            if ($http_user_agent ~*"android") { 	#匹配安卓手機(jī)
            	return 404;
            }
            return 405;														#其他瀏覽器默認(rèn)規(guī)則
          }
          • return指令:可用于server、location、if上下文中,執(zhí)行階段是rewrite階段。
          #格式1:返回響應(yīng)的狀態(tài)碼和提示文字,提示文字可選
          return code [text];
          
          #格式2:返回響應(yīng)的重定向狀態(tài)碼和重定向URL
          return code URL;
          
          #格式3:返回響應(yīng)的重定向URL,默認(rèn)的返回狀態(tài)碼是臨時(shí)重定向302
          return URL;
          • add_header指令:設(shè)置返回客戶端的響應(yīng)。

          使用Ajax進(jìn)行跨域請(qǐng)求時(shí),瀏覽器會(huì)向跨域資源的服務(wù)端發(fā)送一個(gè)OPTION請(qǐng)求,用于判斷實(shí)際請(qǐng)求是否安全或者判斷服務(wù)端是否允許跨域訪問(wèn),這種請(qǐng)求也叫預(yù)檢請(qǐng)求。跨域訪問(wèn)的預(yù)檢請(qǐng)求是瀏覽器自動(dòng)發(fā)出的,用戶程序不知情,如果不進(jìn)行特殊的配置,那么客戶端發(fā)出一次請(qǐng)求,在服務(wù)端會(huì)收到兩個(gè)請(qǐng)求:一個(gè)是預(yù)檢請(qǐng)求,一個(gè)是正式的請(qǐng)求。會(huì)比較影響性能,通常Nginx代理服務(wù)器對(duì)預(yù)檢請(qǐng)求進(jìn)行攔截,同時(shí)對(duì)預(yù)檢請(qǐng)求設(shè)置比較長(zhǎng)時(shí)間的有效期。

          add_header Cache-Control no-store;
          add_header Content-Encoding gzip;
          add_header Content-Type 'text/html; charset=utf-8';
          
          #實(shí)例
          upstream zuul {
          	server "192.168.233.122:7799";
            keepalive 1000;
          }
          
          server {
          	listen      80;
            server_name	nginx.server *.nginx.server;
            default_type 'text/html';
            charset utf-8;
            
            #轉(zhuǎn)發(fā)到上游服務(wù)器,但是‘OPTIONS’請(qǐng)求直接返回空
            location / {
            	add_header	Access-Control-Max-Age 1728000;		#指定本次預(yù)檢請(qǐng)求的有效期,單位秒,允許緩存該條回應(yīng)20天,此期間內(nèi)客戶端不用發(fā)出另一條預(yù)檢請(qǐng)求
              add_header	Access-Control-Allow-Origin	*;
              add_header	Access-Control-Allow-Credentials	true;
              add_header	Access-Control-Allow-Methods	'GET, POST, OPTIONS';
              add_header	Access-Control-Allow-Headers	'Keep-Alive, User-Agent, X-Requested-With, \
                If-Modified-Since, Cache-Control, COntent-Type,token';
              return 204;
            }
            proxy_pass	http://zuul/;
          }
          • 指令的執(zhí)行順序:與Nginx的請(qǐng)求處理的11各階段有密切關(guān)系。其中3個(gè)比較常見(jiàn)的按照?qǐng)?zhí)行時(shí)的先后順序依次是rewrite階段、access階段、content階段。Nginx的配置指令一般只會(huì)注冊(cè)并運(yùn)行在其中的某一個(gè)處理階段,比如set指令就是在rewrite階段運(yùn)行的,而echo指令只會(huì)在content階段運(yùn)行,在一次請(qǐng)求處理流程中,rewrite階段總是在content階段之前執(zhí)行。
          location /sequence_demo {
          	set $a foo;
            echo $a;
            
            set $a bar;
            echo $a;
          }
          
          #訪問(wèn)測(cè)試:
          curl http://cloudxue.com/sequence_demo 
          #響應(yīng)
          bar bar
          
          #若按照請(qǐng)求處理階段的先后次序排序
          location /sequence_demo {
          	#rewrite 階段的配置指令,執(zhí)行在前面
            set $a foo;
            set $a bar;
            
            #content階段的配置指令,執(zhí)行在后面
            echo $a;
            echo $a;
          }
          
          #所以以上輸出為 bar bar

          反向代理與負(fù)載均衡配置

          proxy_pass反向代理指令

          位于ngx_http_proxy_module模塊,注冊(cè)在HTTP請(qǐng)求11個(gè)階段的content階段。

          • 不帶location前綴的代理:proxy_pass指令后面的目標(biāo)URL格式為:"協(xié)議" + "IP[:PORT]" + "/",最終的代理URL不帶location前綴。
          • 帶location前綴的代理:proxy_pass指令后面的目標(biāo)URL格式未:"協(xié)議" + "IP[:PORT]" ,最終的代理URL帶有l(wèi)ocation前綴。
          • 帶部分URI路徑的代理:最終的代理URL為配置項(xiàng)中的目標(biāo)URL前綴+請(qǐng)求URI中去掉location中前綴的剩余部分
          worker_processes  1;
          error_log logs/error.log;
          events {
              worker_connections 1024;
          }
          
          http {
              server {
          			listen 8080;
            		server_name localhost;
            		default_type 'text/html';
            		charset utf-8;
            		location / {
            			echo "-uri=$uri"
                   		 "-host=$host"
                	 		 "-remote=$remote_addr"
                   		 "-proxy_add_x_forwarded=$proxy_add_x_forwarded_for"
                   		 "-http_x_forwarded_for=$http_x_forwarded_for";
                  }
            	}
            	
            	server {
          		  listen 80;
            		server_name localhost;
            		default_type 'text/html';
            		charset utf-8;
            
            		location / {
            			echo "默認(rèn)根路徑匹配:/";
            		}
            
            		#不帶location前綴的代理類(lèi)型
          			location /foo_no_prefix {
          				proxy_pass http://127.0.0.1:8080/;
          			}
            
            		#帶location前綴的代理類(lèi)型
            		location /foo_prefix {
            			proxy_pass http://127.0.0.1:8080;
            		}
            
            		#帶部分URI路徑的代理
            		location /foo_uri_1 {
            			proxy_pass http://127.0.0.1:8080/contextA/;
            		}
            
            		#帶部分URI路徑的代理
            		location /foo_uri_2 {
            			proxy_pass http://127.0.0.1:8080/context-A;
            		}
          		}
          	
          }
          

          測(cè)試結(jié)果如下

          ?  ~ curl http://127.0.0.1/foo_no_prefix/bar.html
          -uri=/bar.html -host=127.0.0.1 -remote=127.0.0.1 -proxy_add_x_forwarded=127.0.0.1 -http_x_forwarded_for=?  ~ curl http://127.0.0.1/foo_prefix/bar.html 
          -uri=/foo_prefix/bar.html -host=127.0.0.1 -remote=127.0.0.1 -proxy_add_x_forwarded=127.0.0.1 -http_x_forwarded_for=?  ~ curl http://127.0.0.1/foo_uri_1/bar.html
          -uri=/contextA/bar.html -host=127.0.0.1 -remote=127.0.0.1 -proxy_add_x_forwarded=127.0.0.1 -http_x_forwarded_for=?  ~ curl http://127.0.0.1/foo_uri_2/bar.html
          -uri=/context-A/bar.html -host=127.0.0.1 -remote=127.0.0.1 -proxy_add_x_forwarded=127.0.0.1 -http_x_forwarded_for=?  ~ 

          proxy_set_header請(qǐng)求頭設(shè)置指令

          在反向代理前,proxy_set_header指令能重新定義添加字段傳遞給代理服務(wù)的請(qǐng)求頭。請(qǐng)求頭的值可以包含文本、變量和它們的組合,格式如下

          proxy_set_header head_field field_value;

          該指令在發(fā)生反向代理之前,將保持在內(nèi)置變量$remote_addr中的真實(shí)客戶端地址保持到請(qǐng)求頭中,通常請(qǐng)求頭參數(shù)名為X-real-ip。

          在Java端可以使用request.getHeader("X-real-ip")獲取請(qǐng)求頭的值,就可以拿到客戶的真實(shí)IP。

          由于在整個(gè)請(qǐng)求處理鏈條上可能不僅一次反向代理,可能會(huì)經(jīng)過(guò)N次反向代理,為了獲取整個(gè)轉(zhuǎn)發(fā)記錄,可以使用$proxy_add_x_forwarded_for內(nèi)置變量,該值的第一個(gè)就是真實(shí)地址

          為了不丟失信息,反向代理的設(shè)置如下:

          location /hello {
          	proxy_pass http://127.0.0.1:8080;
            proxy_set_header Host $host;
            proxy_set_header X-real-ip $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_redirect off; #修改從上游被代理服務(wù)器傳來(lái)的應(yīng)答頭中的Location和Refresh字段
          }

          以上配置,設(shè)置了Host、X-real-ip、X-Forwarded-For,分別將當(dāng)前的目標(biāo)主機(jī)、客戶端IP、轉(zhuǎn)發(fā)記錄保存在請(qǐng)求頭中。

          當(dāng)上游服務(wù)器返回的響應(yīng)碼是重定向301或者刷新302請(qǐng)求時(shí),proxy_redirect指令可以重設(shè)HTTP頭部的location或refresh字段值,off參數(shù)表示禁止所有的proxy_redirect指令,即反向代理時(shí),禁止重定向。

          upstream上有服務(wù)器組

          作為Nginx的一大特色,若沒(méi)有負(fù)載均衡,只有反向代理,那么其使用價(jià)值會(huì)大打折扣。Nginx在配置反向代理時(shí),可以通過(guò)負(fù)載均衡機(jī)制配置一個(gè)上有服務(wù)器組。當(dāng)組內(nèi)某臺(tái)機(jī)器宕機(jī)時(shí),仍能維持系統(tǒng)可用,從而實(shí)現(xiàn)高可用。

          Nginx的負(fù)載均衡配置主要用到upstream指令,其格式為:

          upstream name {
          	server name address [parameters];
          }
          #上下文為http配置快,內(nèi)部使用server指令定義組內(nèi)的上游候選服務(wù)器

          配置示例:

          upstream zuul {
            #名為upstream_zuul的共享內(nèi)存區(qū),大小為64k
          	zone upstream_zuul 64k;
            #組內(nèi)該機(jī)器的權(quán)重為5,最大并發(fā)連接數(shù)為500
            server "192.168.223.121:7799" weight=5 max_conns=500;
            #組內(nèi)該機(jī)器的默認(rèn)權(quán)重為1,同時(shí)設(shè)置20秒內(nèi)失敗2次,判定該服務(wù)器不可用
            server "192.168.233.122:7799" fail_timeout=20s max_fails=2;
            #后備服務(wù)
            server "192.168.233.123:7799" backup;
          }

          upstream的負(fù)載分配方式

          • 加權(quán)輪詢:默認(rèn)負(fù)載方式,組內(nèi)各服務(wù)器的權(quán)重默認(rèn)為1,且上游各服務(wù)器的weight值相同,表示每個(gè)請(qǐng)求按到達(dá)的先后順序逐一分配到不同的上游服務(wù)器,若果某個(gè)上游服務(wù)器宕機(jī),就自動(dòng)剔除。
          • hash指令:基于hash函數(shù)值進(jìn)行負(fù)載均衡,hash函數(shù)的key可以包含文本、變量或二者的組合。是一個(gè)獨(dú)立的指令,通常與consistent參數(shù)搭配使用,避免組中某臺(tái)機(jī)器宕機(jī)后,原來(lái)的大多數(shù)key可能會(huì)尋址到不同的server上。使用consistent參數(shù),則hash一致性將選擇Ketama算法,從而只有少數(shù)key會(huì)重新映射到其他server上,即大多數(shù)key不受server宕機(jī)的影響,還走原來(lái)的server,這對(duì)高緩存server命中率有很大幫助。配置示例如下:
          upstream backend {
            #通過(guò)請(qǐng)求的$request_uri的hash值進(jìn)行負(fù)載均衡
          	hash $request_uri	consistent;
            server 192.168.233.121;
            server 192.168.233.122;
            server 192.168.233.123;
          }
          • ip_hash指令:基于客戶端的IP的hash值進(jìn)行負(fù)載均衡,這樣每個(gè)客戶端固定訪問(wèn)同一個(gè)后端服務(wù)器,可以解決類(lèi)似session不能跨服務(wù)器的問(wèn)題。如果上游server不可用,就需要手工摘除或者配置down參數(shù)。是一個(gè)獨(dú)立的指令。配置示例如下:

          主站蜘蛛池模板: 中文字幕一区二区日产乱码| 无码精品人妻一区二区三区免费| 国产综合精品一区二区| 亚洲高清成人一区二区三区| 无码国产精品一区二区免费I6| 国产在线一区二区| 色噜噜AV亚洲色一区二区| 国产一区二区精品在线观看| 国产精品久久亚洲一区二区| 国产一区二区精品| 91一区二区三区| 国产精品免费视频一区| 亚洲日韩国产欧美一区二区三区| 中文字幕精品一区二区2021年| 中文字幕一区二区人妻| 亚洲一区综合在线播放| 精品无码一区二区三区在线| 欧美日韩一区二区成人午夜电影| 色噜噜狠狠一区二区三区果冻| 中文乱码人妻系列一区二区 | 伊人久久精品一区二区三区| 国产成人无码一区二区在线观看| 国产在线精品一区二区不卡麻豆| 国产不卡视频一区二区三区| 精品国产AⅤ一区二区三区4区 | 国产精品无码一区二区三区不卡| 制服美女视频一区| 视频一区视频二区在线观看| 久久精品一区二区东京热| 亚洲国产一区在线| 日韩精品乱码AV一区二区| 亚洲一区二区在线视频| 亚洲香蕉久久一区二区| 无码av免费毛片一区二区| 高清一区二区三区视频| 一区二区三区在线|日本| 亚洲av成人一区二区三区在线观看 | 精品视频一区二区| 人妻久久久一区二区三区| 亚洲一区二区三区高清不卡 | 无码人妻精品一区二区三18禁|