整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          nginx的http塊配置項有哪些?

          nginx的http塊配置項有哪些?

          ain配置項

          1. worker_processes:nginx的worker進程數,默認為auto,表示根據系統CPU核數來設置。
          2. worker_connections:每個worker進程能夠同時處理的最大連接數,默認為512。
          3. keepalive_timeout:長連接的超時時間,即客戶端與服務器保持連接的時間,超過該時間則關閉連接。
          4. server_names_hash_bucket_size:用于存儲虛擬主機的hash桶大小,默認為32或64,根據服務器的虛擬主機數量來設置。
          5. client_header_buffer_size:nginx服務器接收客戶端請求頭的緩沖區大小,默認為1K。

          下面是一個完整的 http 塊的配置示例:

          http {
              # 設置worker進程數
              worker_processes auto;
          
              # 設置每個worker進程最大連接數
              worker_connections 512;
          
              # 設置長連接超時時間
              keepalive_timeout 65;
          
              # 設置server_name的hash桶大小
              server_names_hash_bucket_size 128;
          
              # 設置客戶端請求頭緩沖區大小
              client_header_buffer_size 2k;
          }

          server配置項

          用于配置具體的虛擬主機,包括監聽的端口、域名、SSL證書、反向代理等。主要的server配置項包括:

          1. listen:指定server監聽的端口和IP地址。
          2. server_name:指定虛擬主機的域名,可以設置多個域名,用空格分隔。
          3. root:指定網站的根目錄,用于存放靜態文件。
          4. index:指定默認的首頁文件。
          5. access_log:指定訪問日志的保存路徑和格式。
          6. error_log:指定錯誤日志的保存路徑和格式。
          7. location:用于配置請求的處理規則,可以包括正則表達式、反向代理等。

          下面是一個簡單的server塊的配置示例:

          server {
              # 監聽的端口和IP地址
              listen 80;
          
              # 指定虛擬主機的域名
              server_name example.com www.example.com;
          
              # 網站的根目錄
              root /var/www/example.com;
          
              # 默認的首頁文件
              index index.html;
          
              # 訪問日志的保存路徑和格式
              access_log /var/log/nginx/example.access.log combined;
          
              # 錯誤日志的保存路徑和格式
              error_log /var/log/nginx/example.error.log;

          location配置項:

          1. location:用于匹配請求URI,可以使用正則表達式或者精確匹配字符串。例如:
          location /images/ {
              root /data/www;
          }
          
          1. alias:用于指定文件系統路徑,可以使用正則表達式或者精確匹配字符串。例如:
          location /images/ {
              alias /data/www/images/;
          }
          
          1. if:用于判斷某個條件是否成立,如果成立則執行特定的操作。例如:
          location / {
              if ($request_method=POST) {
                  return 405;
              }
          }
          
          1. limit_except:用于限制請求方法。例如:
          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:用于重寫URI。例如:
          location / {
              rewrite ^/admin/(.*)$ /$1 break;
          }
          
          1. error_page:用于指定錯誤頁面。例如:

          . Nginx模塊

          1.1 Nginx中的模塊化設計

          Nginx 的內部結構是由核心部分和一系列的功能模塊所組成。這樣劃分是為了使得每個模塊的功能相對簡單,便于開發,同時也便于對系統進行功能擴展。Nginx 將各功能模塊組織成一條鏈,當有請求到達的時候,請求依次經過這條鏈上的部分或者全部模塊,進行處理。例如前面講到的 http 請求,會有11個處理階段,而每個階段有對應著許多在此階段生效的模塊對該 http 請求進行處理。同時,Nginx 開放了第三方模塊編寫功能,用戶可以自定義模塊,控制 http 請求的處理與響應,這種高度可定制化催生了 Nginx 的大量第三方模塊,也使得 Nginx 定制化開發在各大互聯網公司十分流行。

          1.2 Nginx中的模塊分類

          關于 Nginx 模塊的分類有很多種方式,目前網上博客中寫的較多的是按照功能進行分類,有如下幾大類:

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

          對于官方提供的模塊,我們可以直接在官網文檔上學習,學習的方式和學習其他互聯網組件的方式一致,首先學習如何使用,在用至熟練后可以深入分析其源碼了解功能實現背后的原理。

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

          進入 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 模塊對應的代碼文件后,我們就可以閱讀里面的代碼進行學習。往往源碼的閱讀是枯燥無味的,我們可以借助海量的網絡資源輔助我們學習。這里就有一篇文章,作者深入分析了 Nginx 的限流模塊的源碼以及相應限流算法,最后進行了相關的實驗測試。通過這樣一個個模塊深入學習,最后在使用每一個 Nginx 指令時,也會非常熟練,最后成為 Nginx 高手。

          1.3 如何學習和使用第三方模塊

          這里我們演示在 Nginx 中使用第三方模塊。 Openresty 社區提供了一款 Nginx 中的 Echo 模塊,即echo-nginx-module。在 Nginx 中添加了該模塊后,我們在配置文件中可以使用該模塊提供的 echo 指令返回用戶響應,簡單方便。該模塊的源碼在 github 上,并且有良好的文檔和使用示例,非常方便開發者使用。

          現在我們在 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添加第三方模塊,參數為第三方模塊源碼
          [root@server shencong]# ./configure --prefix=/root/shencong/nginx-echo  --add-module=/root/shencong/echo-nginx-module-0.62rc1
          

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

          ...
          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;
                  }
                  
                  # 新增測試 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.";
                  }
          
              }
          }
          ...
          

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

          1.4 如何編寫自己的模塊

          想要編寫 Nginx 模塊,首先需要對 Nginx 模塊中的源碼以及相關的數據結構有所了解,還要知曉 Nginx HTTP 模塊的調用流程。假設我要實現前面第三方模塊Echo的最簡單形式,即只輸出相應的字符串即可。假定模塊支持的指令名稱還是 echo, 這個 echo 指令需要跟一個參數,即輸出的字符串。我們需要做如下幾步:

          • 確定模塊名稱,以及模塊中的指令以及參數,還有運行的環境。這里涉及的結構是 ngx_command_t,它定義了模塊里的所有指令格式。下面的代碼表示該模塊中只有一個 echo 指令,它出現的上下文環境為 location,且有一個參數(NGX_CONF_TAKE1)。當某個配置塊中出現echo指令時,Nginx 將調用ngx_http_echo方法。然后在該方法中,會設置處理請求的 handler,這個 handler 就是處理請求的方法。
            static ngx_command_t  ngx_http_echo_commands[]={  
                   { ngx_string("echo"),      /* 指令名稱,利用ngx_string宏定義 */
                    NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,  /* 用在 location 指令塊內,且有1個參數 */
                    ngx_http_echo,            /* 處理回調函數 */
                    NGX_HTTP_LOC_CONF_OFFSET,    
                    offsetof(ngx_http_echo_loc_conf_t, ed), /* 指定參數讀取位置 */
                    NULL },
                    ngx_null_command
            };
          
          • 完成請求處理的 handler 函數,最重要的部分就在這里;
           static char *
           ngx_http_echo(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
           {
               ngx_http_core_loc_conf_t  *clcf;
               /* 找到指令所屬的配置塊,這里我們限定echo指令的上下文環境只有location */
               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)
           {
               ...
               
               /* 向用戶發送相應包 */
               return ngx_http_output_filter(r, &out);
           }
          
          • 一些收尾工作,比如配置模塊介入 http 請求的哪些階段等。
            /* 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
            };
          

          完成以上幾步,一個簡易的自定義模塊就算大功告成了。接下來我們動手完成第一個自定義的模塊,將其編譯進Nginx 二進制文件中并進行測試。

          2. 案例

          我們來完成一個簡單的自定義 http 模塊,來實現前面Echo模塊的最簡單形式,即使用指令輸出 “hello, world” 字符串。首先新建一個目錄echo-nginx-module,然后在目錄下新建兩個文件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
          

          兩個文件內容分別如下:

          [root@server echo-nginx-module]# cat config 
          ngx_addon_name=ngx_http_echo_module
          # 指定模塊名稱
          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"),      /* 指令名稱,利用ngx_string宏定義 */
                  NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,  /* 用在 location 指令塊內,且有1個參數 */
                  ngx_http_echo,         /* 處理回調函數 */
                  NGX_HTTP_LOC_CONF_OFFSET,    
                  offsetof(ngx_http_echo_loc_conf_t, ed), /* 指定參數讀取位置 */
                  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;
              /* 獲取指令的參數 */
              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 請求,則返回405 Not Allowed錯誤 */
                  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;
              }
              /* 向用戶發送相應包 */
              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;
          }
          

          這樣一個第三方模塊包就完成了,接下來我們要向之前使用第三方模塊一樣,將它編譯進 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
          

          接下來,我們只要在 nginx.conf 中加入我們的指令,并給一個參數,就能看到我們自定義的輸出了。

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

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

          3. 小結

          在 Nginx 基礎架構介紹的最后,主要是介紹了 Nginx 的模塊設計以及相應的模塊用法。最后,我們簡單給出了一個簡單編寫自己模塊的案例作為本章的實戰案例。希望這一節之后,大家能對 Nginx 的模塊化設計有所了解,并有興趣在模塊的源碼方向深入學習。

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

          啟動、檢查、重啟及關閉命令

          #假設Nginx的安裝目錄為
          /home/nginx/nginx/
          
          #啟動命令
          /home/nginx/nginx/sbin/nginx -c /home/nginx/nginx/conf/nginx.conf
          #狀態檢查
          /home/nginx/nginx/sbin/nginx -t
          #重新加載配置
          /home/nginx/nginx/sbin/nginx -s reload
          
          #關閉
          #查詢nginx主進程號 
          ps -ef | grep nginx
          #從容停止   
          kill -QUIT 主進程號
          #快速停止   
          kill -TERM 主進程號
          #強制停止   
          kill -9 主進程號
          
          #若nginx.conf配置了pid文件路徑,如果沒有,則在logs目錄下
          kill -信號類型 '/usr/local/nginx/logs/nginx.pid'

          基礎配置

          events事件驅動配置

          • use指令
          • worker_connections指令
          • accept_mutex指令
          events {
          	use epoll;										#使用epoll類型的IO多路復用模型,性能比select高
            worker_connections 204800;		#Worker進程能夠打開的最大并發連接數
            accept_mutex on;							#各個Worker進程通過鎖來獲取新連接
          }

          server虛擬主機配置

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

          多個虛擬主機之間根絕server_name匹配的優先級從高到低:

          • 精確匹配
          • 左側通配符匹配
          • 右側通配符匹配
          • 正則表達式匹配
          • defalt_server:在listen指令后面如果帶有default指令參數,表示默認的、最后兜底的虛擬主機。

          錯誤頁面配置

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

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

          長鏈接配置

          keepalive_timeout	75;				#長鏈接有效時長,0表示禁用長鏈接,默認75秒
          keepalive_requests	100;		#一條長鏈接上允許被請求的資源的最大數量,默認100

          訪問日志配置

          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"';
            #日志文件、日志訪問格式
            access_log	logs/access_main.log format_main;
          }

          location路由規則配置

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

          rewrite模塊指令配置

          Nginx的rewrite模塊即ngx_http_rewrite_module標準模塊,默認安裝的模塊。主要功能是對URI進行重寫,然后再一次進行location匹配或者直接進行30X重定向返回給客戶端。

          • set指令:用于向變量賦值。當變量存在時就賦值,不存在時,先創建再賦值。創建后的可見范圍為Nginx整個配置
          set	$variable	value
          
          #實例
          set	$a "foo";
          set $b "$a, $a";
          • rewrite指令:主要功能是重寫URI。
          rewrite regrex replacement [flag];
          
          #實例
          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 ";
          }
          
          #訪問如下地址
          curl http://demo.cloudxue.com/download/1/video/10
          
          #rewrite模塊進行匹配后,占位變量$1的值為1, $2的值為10
          uri: /view/1/mp3/10.mp3

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

          • last:停止rewrite匹配,使用當前計算后的新URI進行location匹配和跳轉。
            • break:停止rewrite匹配,但是不進行location跳轉。
          • redirect:外部重定向,返回302響應碼
            • permanent:服務器將新URI地址返回給客戶端瀏覽器,并返回301響應碼給客戶端,客戶端使用新地址再發一次請求(地址欄會變)

          注意事項:

          • last和break的區別僅僅發生在location上下文中,如果發生在server上下文,那么last和break的作用是一樣的。
          • location上下文中的rewrite指令使用last指令參數會再次以新的URI重新發起內部重定向,再次進行location匹配,而新的URI若和舊的URI一樣,會發生死循環。當循環發生到第10次時,Nginx會終止這樣無意義的循環,并返回500錯誤。
          • if指令:相當于引入了一個新的上下文作用于,適用于server、location兩個上下文。
          if (condition) {...}
          #實例
          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手機
            	return 302;
            }
            if ($http_user_agent ~*"android") { 	#匹配安卓手機
            	return 404;
            }
            return 405;														#其他瀏覽器默認規則
          }
          • return指令:可用于server、location、if上下文中,執行階段是rewrite階段。
          #格式1:返回響應的狀態碼和提示文字,提示文字可選
          return code [text];
          
          #格式2:返回響應的重定向狀態碼和重定向URL
          return code URL;
          
          #格式3:返回響應的重定向URL,默認的返回狀態碼是臨時重定向302
          return URL;
          • add_header指令:設置返回客戶端的響應。

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

          add_header Cache-Control no-store;
          add_header Content-Encoding gzip;
          add_header Content-Type 'text/html; charset=utf-8';
          
          #實例
          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;
            
            #轉發到上游服務器,但是‘OPTIONS’請求直接返回空
            location / {
            	add_header	Access-Control-Max-Age 1728000;		#指定本次預檢請求的有效期,單位秒,允許緩存該條回應20天,此期間內客戶端不用發出另一條預檢請求
              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/;
          }
          • 指令的執行順序:與Nginx的請求處理的11各階段有密切關系。其中3個比較常見的按照執行時的先后順序依次是rewrite階段、access階段、content階段。Nginx的配置指令一般只會注冊并運行在其中的某一個處理階段,比如set指令就是在rewrite階段運行的,而echo指令只會在content階段運行,在一次請求處理流程中,rewrite階段總是在content階段之前執行。
          location /sequence_demo {
          	set $a foo;
            echo $a;
            
            set $a bar;
            echo $a;
          }
          
          #訪問測試:
          curl http://cloudxue.com/sequence_demo 
          #響應
          bar bar
          
          #若按照請求處理階段的先后次序排序
          location /sequence_demo {
          	#rewrite 階段的配置指令,執行在前面
            set $a foo;
            set $a bar;
            
            #content階段的配置指令,執行在后面
            echo $a;
            echo $a;
          }
          
          #所以以上輸出為 bar bar

          反向代理與負載均衡配置

          proxy_pass反向代理指令

          位于ngx_http_proxy_module模塊,注冊在HTTP請求11個階段的content階段。

          • 不帶location前綴的代理:proxy_pass指令后面的目標URL格式為:"協議" + "IP[:PORT]" + "/",最終的代理URL不帶location前綴。
          • 帶location前綴的代理:proxy_pass指令后面的目標URL格式未:"協議" + "IP[:PORT]" ,最終的代理URL帶有location前綴。
          • 帶部分URI路徑的代理:最終的代理URL為配置項中的目標URL前綴+請求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 "默認根路徑匹配:/";
            		}
            
            		#不帶location前綴的代理類型
          			location /foo_no_prefix {
          				proxy_pass http://127.0.0.1:8080/;
          			}
            
            		#帶location前綴的代理類型
            		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;
            		}
          		}
          	
          }
          

          測試結果如下

          ?  ~ 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請求頭設置指令

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

          proxy_set_header head_field field_value;

          該指令在發生反向代理之前,將保持在內置變量$remote_addr中的真實客戶端地址保持到請求頭中,通常請求頭參數名為X-real-ip。

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

          由于在整個請求處理鏈條上可能不僅一次反向代理,可能會經過N次反向代理,為了獲取整個轉發記錄,可以使用$proxy_add_x_forwarded_for內置變量,該值的第一個就是真實地址

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

          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; #修改從上游被代理服務器傳來的應答頭中的Location和Refresh字段
          }

          以上配置,設置了Host、X-real-ip、X-Forwarded-For,分別將當前的目標主機、客戶端IP、轉發記錄保存在請求頭中。

          當上游服務器返回的響應碼是重定向301或者刷新302請求時,proxy_redirect指令可以重設HTTP頭部的location或refresh字段值,off參數表示禁止所有的proxy_redirect指令,即反向代理時,禁止重定向。

          upstream上有服務器組

          作為Nginx的一大特色,若沒有負載均衡,只有反向代理,那么其使用價值會大打折扣。Nginx在配置反向代理時,可以通過負載均衡機制配置一個上有服務器組。當組內某臺機器宕機時,仍能維持系統可用,從而實現高可用。

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

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

          配置示例:

          upstream zuul {
            #名為upstream_zuul的共享內存區,大小為64k
          	zone upstream_zuul 64k;
            #組內該機器的權重為5,最大并發連接數為500
            server "192.168.223.121:7799" weight=5 max_conns=500;
            #組內該機器的默認權重為1,同時設置20秒內失敗2次,判定該服務器不可用
            server "192.168.233.122:7799" fail_timeout=20s max_fails=2;
            #后備服務
            server "192.168.233.123:7799" backup;
          }

          upstream的負載分配方式

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

          主站蜘蛛池模板: 大伊香蕉精品一区视频在线| 精品一区二区三区在线观看视频| 欧洲精品无码一区二区三区在线播放 | 亚洲熟女一区二区三区| 亚洲av无码成人影院一区| 日本不卡一区二区三区| 冲田杏梨高清无一区二区| 毛片一区二区三区无码| 无码视频一区二区三区在线观看 | 国产一区二区三区手机在线观看| 精品亚洲A∨无码一区二区三区| 亲子乱AV视频一区二区| 国产人妖视频一区二区| 国产成人无码AV一区二区| 精品aⅴ一区二区三区| 人妻少妇AV无码一区二区| 色噜噜AV亚洲色一区二区| 亚洲一区二区三区在线视频| 一区二区三区视频网站| 亚洲第一区在线观看| 久久国产精品免费一区二区三区| 八戒久久精品一区二区三区 | 无码aⅴ精品一区二区三区 | 人妻无码一区二区三区AV| 久久国产精品一区二区| 亚洲一区二区影院| 精品国产伦一区二区三区在线观看 | 精品亚洲综合在线第一区| 亚洲av无码一区二区乱子伦as| 亚洲色婷婷一区二区三区| 无码精品一区二区三区在线| 男女久久久国产一区二区三区| 精品无码一区二区三区爱欲| 在线精品视频一区二区| 亚洲av成人一区二区三区在线播放| 日韩三级一区二区三区| 国产aⅴ一区二区| 亲子乱av一区二区三区| AV鲁丝一区鲁丝二区鲁丝三区| 免费看AV毛片一区二区三区| 一区二区三区四区国产|