乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      【Nginx26】Nginx學習:日志與鏡像流量復制

       硬核項目經(jīng)理 2023-09-14 發(fā)布于湖南

      Nginx學習:日志與鏡像流量復制

      總算到了日志模塊,其實這個模塊的指令之前我們就用過了,而且也是是非常常見的指令。相信這一塊的學習大家應(yīng)該不會有什么難度。另一個則是鏡像功能,這個估計用過的同學就比較少了,不過也并不是特別的復雜,一會講到的時候咱們再詳細說哦。

      今天的兩個模塊都是包含在 Nginx 源碼中的,不需要額外單獨編譯安裝。所有的配置指令大分部都可以在 http、server、location 中使用,僅有一個指令是只能配置在 http 中的,我會單獨說明。

      日志

      日志模塊是非常常用的模塊,這里指的是訪問日志哦,不是 error_log 。錯誤日志是屬于 HTTP 核心模塊的內(nèi)容,之前我們已經(jīng)學習過了。大多數(shù)情況下,我們只是去為每個 Server 指定一個單獨的日志文件,這樣便于管理,或者有特殊需要就為某些 Location 指定。另外還有一些情況就是會屏蔽掉一些比如說 favicon.ico 文件或者靜態(tài)圖片等資源文件的訪問日志記錄。

      它的全名是 ngx_http_log_module 模塊,用于以指定的格式寫入請求日志。請求記錄在處理結(jié)束位置的上下文中。如果在請求處理期間發(fā)生內(nèi)部重定向,它可能與原始位置不同。

      還是先來學習它的配置指令,最后再進行簡單地測試。

      access_log

      設(shè)置緩沖日志寫入的路徑、格式和配置。

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

      默認值是 logs/access.log combined ??梢栽谕慌渲眉墑e上指定多個日志。可以通過在第一個參數(shù)中指定“syslog:”前綴來配置日志記錄到 syslog。特殊值 off 取消當前級別的所有 access_log 指令。如果未指定格式,則使用預定義的“組合”格式。

      必須要有的這個 path 參數(shù),是指定日志要記錄到哪個文件的,可以相對也可以是絕對路徑的文件。后面的 format 則是根據(jù)后面要講的 log_format 配置,確定使用哪個日志格式。這個參數(shù)可以不填,不填走默認的 combined 格式,下面會看到。

      如果使用了 buffer 或 gzip (1.3.10, 1.2.7) 參數(shù),寫入日志將被緩沖。緩沖區(qū)大小不得超過對磁盤文件的原子寫入大小。對于 FreeBSD,這個大小是無限的。這個一會我們會測試。

      啟用緩沖后,這些數(shù)據(jù)將馬上寫入文件:

      • 如果下一個日志行不適合緩沖區(qū)
      • 如果緩沖的數(shù)據(jù)比刷新參數(shù)(1.3.10、1.2.7)指定的時間早
      • 當工作進程重新打開日志文件或正在關(guān)閉時

      如果使用 gzip 參數(shù),則緩沖的數(shù)據(jù)將在寫入文件之前進行壓縮。壓縮級別可以設(shè)置在 1(最快,較少壓縮)和 9(最慢,最佳壓縮)之間。默認情況下,緩沖區(qū)大小等于 64K 字節(jié),壓縮級別設(shè)置為 1。由于數(shù)據(jù)是按原子塊壓縮的,因此日志文件可以隨時被“zcat”解壓縮或讀取。

      文件路徑可以包含變量(0.7.6+),但是這樣的日志有一些限制:

      • 工作進程使用其憑據(jù)的用戶應(yīng)有權(quán)在具有此類日志的目錄中創(chuàng)建文件
      • 緩沖寫入不起作用
      • 每次寫入日志時都會打開和關(guān)閉文件。但是,由于常用文件的描述符可以存儲在緩存中,因此可以在 open_log_file_cache 指令的有效參數(shù)指定的時間內(nèi)繼續(xù)寫入舊文件
      • 在每次日志寫入期間,都會檢查請求的根目錄是否存在,如果不存在,則不會創(chuàng)建日志。因此,在同一配置級別上同時指定 root 和 access_log 是一個好主意

      if 參數(shù) (1.7.0) 啟用條件日志記錄。如果條件評估為“0”或空字符串,則不會記錄請求。就是可以有條件的記錄到日志,后面我們也會測試這個參數(shù)。

      另外,如果是新安裝好的 Nginx ,沒有別的訪問日志配置,并且在編譯時有 --http-log-path=/var/log/nginx/access.log 那么就是默認找不到 access_log 和 log_format 配置的其它所有日志全被記錄到這個編譯時參數(shù)所指定的日志文件中。如果你找不到日志在哪了,可以 nginx -V 看一下是不是記錄到這里了哦。

      log_format

      指定日志的格式。

      log_format name [escape=default|json|none] string ...;

      默認值 combined "..." ,它只能配置在 http 模塊下。轉(zhuǎn)義參數(shù) (1.11.8) 允許在變量中設(shè)置 json 或默認字符轉(zhuǎn)義,默認情況下使用默認轉(zhuǎn)義。none 值 (1.13.10) 禁用轉(zhuǎn)義。對于默認轉(zhuǎn)義,字符“"”、“\”和其他值小于 32 (0.7.0) 或大于 126 (1.1.6) 的字符將轉(zhuǎn)義為“\xXX”。如果找不到變量值,將記錄一個連字符(“-”)。對于json轉(zhuǎn)義,JSON字符串中不允許的所有字符都將被轉(zhuǎn)義:字符“”和“\”被轉(zhuǎn)義為“\”和“\\”,值小于32的字符被轉(zhuǎn)義為“\n”, “\r”、“\t”、“\b”、“\f”或“\u00XX”。

      必須的 name 參數(shù)就是上面 access_log 所需要的那個 format 參數(shù)。這樣兩邊配合起來就是一套完整的日志記錄功能了。

      日志格式可以包含公共變量,以及僅在寫入日志時存在的變量:

      • $bytes_sent 發(fā)送到客戶端的字節(jié)數(shù)
      • $connection 連接序列號
      • $connection_requests 當前通過連接發(fā)出的請求數(shù) (1.1.18)
      • $msec 以秒為單位的時間,在日志寫入時以毫秒為單位
      • $pipe “p”如果請求是流水線的,“.”否則
      • $request_length 請求長度(包括請求行、請求頭和請求體)
      • $request_time 以毫秒為單位的請求處理時間;從客戶端讀取第一個字節(jié)到最后一個字節(jié)發(fā)送到客戶端后寫入日志之間經(jīng)過的時間
      • $status 響應(yīng)狀態(tài)
      • $time_iso8601 ISO 8601 標準格式的當?shù)貢r間
      • $time_local 通用日志格式的本地時間

      在現(xiàn)代 nginx 版本中,變量 $status (1.3.2, 1.2.2), $bytes_sent (1.3.8, 1.2.5), $connection (1.3.8, 1.2.5), $connection_requests (1.3.8, 1.2 .5), $msec (1.3.9, 1.2.6), $request_time (1.3.9, 1.2.6), $pipe (1.3.12, 1.2.7), $request_length (1.3.12, 1.2.7 )、$time_iso8601 (1.3.12, 1.2.7) 和 $time_local (1.3.12, 1.2.7) 也可用作公共變量。

      發(fā)送到客戶端的標題行具有前綴“sent_http_”,例如,$sent_http_content_range。

      配置始終包含預定義的“組合”格式:

      log_format combined '$remote_addr - $remote_user [$time_local] '
                          '"$request" $status $body_bytes_sent '
                          '"$http_referer" "$http_user_agent"';

      默認安裝完成后提供的 nginx.conf 或 nginx.conf.default 中,有兩段注釋掉的日志配置,其實就是最基本的日志配置信息。你可以打開試試哦。

       #log_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.log  main;

      open_log_file_cache

      定義一個緩存,用于存儲名稱包含變量的常用日志的文件描述符。

      open_log_file_cache max=N [inactive=time] [min_uses=N] [valid=time];
      open_log_file_cache off;

      該指令具有以下參數(shù):

      • max 設(shè)置緩存中描述符的最大數(shù)量;如果緩存已滿,則關(guān)閉最近最少使用 (LRU) 描述符
      • inactive 如果在此期間沒有訪問,則設(shè)置緩存描述符關(guān)閉的時間;默認情況下,10 秒
      • min_uses 設(shè)置在由 inactive 參數(shù)定義的時間內(nèi)文件使用的最小數(shù)量,以讓描述符在緩存中保持打開狀態(tài);默認情況下,1
      • valid 設(shè)置應(yīng)檢查文件是否仍以相同名稱存在的時間;默認情況下,60 秒
      • off 禁用緩存

      這個確實沒用過,不過看樣子是緩存打開的日志文件的句柄的。也不知道怎么測出效果,所以咱們就不演示了哈。有興趣的小伙伴可以自己看一下,有相關(guān)的經(jīng)驗的大佬也歡迎留言評論哈。

      日志測試

      好了,日志模塊的配置指令就是上面那三個,不是特別復雜吧,接下來我們就簡單測試一下。先配置兩個 log_format ,名字就叫 log1 和 log2 吧,為了測試方便。真實業(yè)務(wù)場景下還是要根據(jù)自己的需求好好起名字哈。

      log_format  log1  'This is Log1 Format: $remote_addr - $remote_user [$time_local] "$request" '
                        '$status $body_bytes_sent "$http_referer" '
                        '"$http_user_agent" "$http_x_forwarded_for" "$arg_a"' ;

      log_format log2 escape=json '{"remote_addr":"$remote_addr"}';

      然后找一個 Server ,建個 lcoation 。

      location /log1/ {
        alias html/;
        access_log logs/log1_access_con.log.gz log1 buffer=1000 gzip=1 if=$arg_a;
        access_log logs/log1_access.log log1;
      }

      這個配置是啥意思呢?第一條 access_log ,加了一些參數(shù),分別是緩沖區(qū)配置、gzip壓縮一下,然后還有條件。也就是說,當我們的 GET 參數(shù)中有 a 這個參數(shù)時,訪問日志會記錄到 logs/log1_access_con.log.gz 這個文件中。

      第二條 access_log ,沒有別的參數(shù),就是最簡單的使用 log1 的配置?,F(xiàn)在直接訪問一下吧,先看下不帶任何參數(shù)。

      # /usr/local/nginx/logs/log1_access.log
      This is Log1 Format: 192.168.56.1 -  [05/Sep/2022:09:18:47 +0800] "GET /log1/ HTTP/1.1" 200 621 "" "PostmanRuntime/7.29.2" "" ""

      普通的日志記錄文件中,清楚地看到了訪問請求的情況。注意最后有兩個空的雙引號,并且 logs/log1_access_con.log.gz 創(chuàng)建了,但還是空的。然后我們再帶一個 ?a=111 這樣的 GET 參數(shù)試一下。

      # /usr/local/nginx/logs/log1_access.log
      This is Log1 Format: 192.168.56.1 -  [05/Sep/2022:09:19:22 +0800] "GET /log1/?a=111 HTTP/1.1" 200 621 "" "PostmanRuntime/7.29.2" "" "111"

      看出來不同了吧,最后的一個空引號有值了,因為我們在上面的 log1 的 log_format 中最后加入了 $arg_a 這個變量?,F(xiàn)在 if 參數(shù)的條件滿足了,我們再看一下 log1_access_con.log.gz 文件,我這里還是 0 ,還是沒有內(nèi)容,這是為啥?因為 buffer 參數(shù)的問題啦,日志內(nèi)容還沒有刷到文件中。這時可以多刷幾下,或者重載配置 nginx -s reload ,重載日志 nginx -s reopen 都可以。然后就會看到 log1_access_con.log.gz 有內(nèi)容了。直接使用 gzip 命令解壓。

      gzip -d log1_access_con.log.gz

      查看解壓出來文件內(nèi)容,應(yīng)該和上面記錄的日志是一樣的。不過這邊記錄的日志都是有最后那個 GET 參數(shù)的。

      好了,上面還有一個 log2 的格式配置,使用了 escape=json ,就是要記錄一個 JSON 格式的日志。那么咱們也單獨再來一個 location 測試吧,為了看得清楚一點。

      location /log2/ {
        alias html/;
        access_log logs/log2_access.log log2;
      }

      訪問之后查看日志文件,記錄的內(nèi)容是這樣的。

      # /usr/local/nginx/logs/log2_access.log
      {"remote_addr":"192.168.56.1"}

      記錄 POST 日志

      在之前學習內(nèi)嵌變量時,我們就說過,所有的變量都可以用在日志記錄中,而且之前還學習過一些變量是只能在日志中體現(xiàn)的。比如說 $gzip_ratio 這種。另外,還有一種非常常見的需求就是要記錄 POST 參數(shù),為啥呢?因為現(xiàn)在很多大數(shù)據(jù)分析系統(tǒng),會直接通過日志分析來提取數(shù)據(jù)。就像我們在講 emptygif 時說過的數(shù)據(jù)采集。不過空圖片一般都是以 GET 參數(shù)的提取分析為主,實際業(yè)務(wù)中還是可能會有 POST 數(shù)據(jù)提取的需求。

      為了利用 Nginx 的強大性能,并同步收集到 POST 數(shù)據(jù)埋點信息,我們也可以直接簡單地將 POST 數(shù)據(jù)變量放到日志格式配置中就可以實現(xiàn)這種功能了。

      log_format postinfo '$remote_addr - $remote_user [$time_local] '
                          '"$request" $status $body_bytes_sent '
                          '"$http_referer" "$http_user_agent" '
                          '"$request_body"';
      server {
        listen 8026;
        location ~ \.php$ {
          root           html;
          fastcgi_pass   unix:/var/sock/php-fpm/www.sock;
          fastcgi_index  index.php;
          fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
          include        fastcgi_params;
       }

       access_log logs/26.post.log postinfo;
      }

      上面的配置中,只是在默認日志最后多加了一個 $request_body 變量。它的意思就是獲取 Body 中的內(nèi)容,也就是 POST 的數(shù)據(jù)信息。這個變量之前我們已經(jīng)學習過哦,不記得的小伙伴可以回到 Nginx學習:HTTP核心模塊(十二)內(nèi)嵌變量 https://mp.weixin.qq.com/s/0ks7GgfcvJpQp7mA1IgQcA 再看一下哦。

      curl  --request POST 'http://192.168.56.88:8026/1.php?a=123' --data-urlencode 'bbb=4444'
      192.168.56.1 - - [05/Sep/2022:10:55:34 +0800] "POST /1.php?a=123 HTTP/1.1" 200 1366 "-" "PostmanRuntime/7.29.2" "bbb=4444"

      看到日志記錄的結(jié)果了吧。不過需要注意的是,POST 還有一種提交格式是 FORM-DATA ,就是需要上傳文件時要用的那種格式,這種格式獲得的結(jié)果是不一樣的哦。

      curl  --request POST 'http://192.168.56.88:8026/1.php?a=123' --form 'aaa=555'
      192.168.56.1 - - [05/Sep/2022:10:59:00 +0800] "POST /1.php?a=123 HTTP/1.1" 200 1102 "-" "curl/7.79.1" "--------------------------02b9bcad6dd94cb3\x0D\x0AContent-Disposition: form-data; name=\x22aaa\x22\x0D\x0A\x0D\x0A555\x0D\x0A--------------------------02b9bcad6dd94cb3--\x0D\x0A"

      大數(shù)據(jù)提取日志時需要注意這兩塊的不同哦。

      鏡像 Mirror

      這個鏡像是啥?在沒系統(tǒng)學習文檔之前我都不知道還有這么個東西。它的全稱是 ngx_http_mirror_module 模塊(1.13.4)通過創(chuàng)建后臺鏡像子請求來實現(xiàn)原始請求的鏡像,并且會忽略對鏡像子請求的響應(yīng)。

      還是看不懂吧?其實呀,它就是可以將我們的請求再發(fā)給另一個鏡像地址,它只管發(fā)送,不管那邊會有什么響應(yīng)。就相當于是將流量復制了一份。我們先來看它的配置。

      mirror

      設(shè)置原始請求將被鏡像到的 URI。

      mirror uri | off;

      默認值是 off ,打開的話就是設(shè)置一個 URI 就可以了,這個 URI 就是要發(fā)送到的地址??梢栽谕慌渲眉墑e上指定多個鏡像。

      mirror_request_body

      指示客戶端請求正文是否被鏡像。啟用后,將在創(chuàng)建鏡像子請求之前讀取客戶端請求正文。

      mirror_request_body on | off;

      在這種情況下,由 proxy_request_buffering、fastcgi_request_buffering、scgi_request_buffering 和 uwsgi_request_buffering 指令設(shè)置的無緩沖客戶端請求正文代理將被禁用。

      這個配置默認是 on ,如果改成 off 的話,POST 請求中的 Body 部分就不會被發(fā)送到鏡像地址上了。

      鏡像流量復制測試

      好了,直接來測試吧,這個東西要是上面沒看懂,那就手動測試一下,不動手,光看概念,不懂的始終還是不懂。我們先準備一個鏡像 location 。

      location /mirror1/ {
        alias html/;
        mirror /26.php;

        #
       mirror_request_body off;
      }

      設(shè)置一個 mirror 指定地址為當前目錄的 26.php 這個文件,當然我們也可以設(shè)置成靜態(tài)文件,不過為了記錄請求是否真的發(fā)過去了,使用動態(tài)文件還是方便些。

      這個 26.php 里面就是記錄一下請求的內(nèi)容到一個日志文件中。不需要返回什么響應(yīng),因為鏡像是會忽略響應(yīng)的嘛,它只是將請求發(fā)走,響應(yīng)還是按正常的響應(yīng),不會走鏡像中的響應(yīng)。

      <?php
      $req = json_encode($_REQUEST);
      file_put_contents('./26.REQ.log', $req, FILE_APPEND);

      上面兩個準備好了之后,我們就可以測試了。

      // curl 請求
      curl  --request POST 'http://192.168.56.88/mirror1/?a=123' --data-urlencode 'bbb=4444'


      // 26.REQ.log
      {"a":"123","bbb":"ssss"}{"a":"123","bbb":"ssss"}

      可以看到,請求內(nèi)容被完整記錄了下來,但是訪問路徑返回的響應(yīng)還是我們的靜態(tài)首頁的內(nèi)容。不過你會發(fā)現(xiàn)一個問題,這個日志被記錄了兩條,也就是說,這個 26.php 被訪問了兩次。如果我們直接訪問這個 php 頁面,是只會正常記錄一次的。

      curl  --request POST 'http://192.168.56.88/26.php?a=123' --data-urlencode 'bbb=4444'

      這個原因我也沒找到,網(wǎng)上也沒有相關(guān)的資料。

      那么這個鏡像功能可以有什么實際的應(yīng)用嗎?一是可以做流量放大,比如多次請求;二是灰度發(fā)布驗證,通過鏡像到新版來驗證新版本是否會報錯;三是忽略響應(yīng)很重要,可以發(fā)送一些回調(diào)驗證之類的請求。

      不過需要注意的是,雖然會忽略響應(yīng),但如果鏡像的地址無響應(yīng)或者響應(yīng)慢的時候,也會拖累主請求的響應(yīng)速度。另外如果是 POST/PUT/DELETE 這些請求,一定要清楚地知道自己發(fā)送的請求會對數(shù)據(jù)產(chǎn)生的影響,并且鏡像端要做好日志記錄。

      總結(jié)

      日志功能很重要,雖然錯誤日志可能更有利于我們進行調(diào)試,發(fā)現(xiàn)問題。但是訪問日志同樣也很關(guān)鍵,網(wǎng)站的很多統(tǒng)計,流量、熱點鏈接、爬蟲分析、黑客防護等也都需要通過分析訪問日志來實現(xiàn)。因此,大部分情況下,咱們還是要打開并且配置好相應(yīng)的訪問日志信息的。但是訪問日志一般會比較大,因此會有日志需要分割保存的問題,關(guān)于這個問題,我們后面再說,但其實非常簡單,大家自己先去找找相關(guān)的資料也沒問題。

      另一個鏡像模塊,真的之前從來不知道,現(xiàn)在雖然了解了,但是要想靈活運用還是需要更多的實踐的。所以咱們也不瞎吹牛了,功能用法了解之后就是實踐運用嘗試一下咯。

      參考文檔:

      http:///en/docs/http/ngx_http_log_module.html

      http:///en/docs/http/ngx_http_mirror_module.html

        轉(zhuǎn)藏 分享 獻花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多