grep 零寬斷言

2021-09-08 16:18:32 字數 2316 閱讀 9833

參考參考二

算是正則環視的乙個簡單應用吧。

前兩天因為第三方遊戲伺服器掉線,導致大量使用者同時登入我的伺服器,將伺服器負載瞬間提高到200+,如此恐怖的數字讓我不得不考慮增加伺服器來抵抗問題重現,然而我的伺服器平時負載都很低,0.1都不到,增加伺服器來應付這樣短暫的風暴未免太過於浪費,於是我決定從日誌下手,找到我的**的瓶頸,希望能通過改善程式來解決這個問題。

第一步,定位時間

我的日誌檔案裡包含了最近乙個禮拜的資料,然而我需要的只是風暴發生時產生的資料,總共不超過20分鐘,怎麼取呢?因為我的web伺服器採用的是標準的combined格式

而且全部是php動態請求,所以我決定從time_local下手,找到併發訪問量最高的時間段,這很容易辦到:

grep -op '12\/may\/2011(:\d)' access.log | uniq -c | sort -n > time.sort

得到如下結果(部分)

從18點43分開始,我的伺服器每秒需要響應120多次動態請求,而18:46:49秒更加**,211次!看來把我伺服器拖垮的,就是18點43分到18點50分這一段。

第二步, 過濾指令碼

定位好了時間,現在要做的,就是取出這一時間段的日誌再做分析,使用以下指令碼將18:43分到18:50分之間的日誌取出來

grep -p '12\/may\/2011:18:4[3-9]:\d' access.log > storm.log第三步, 找出元凶

得到了storm.log,下面我便要找出拖垮我伺服器的元凶,及訪問數量最高的$request。因為$request都是 「get /***** http/1.1″ 或 「post /****」 這樣的格式, 所以可以通過簡單的正則取出$request,如下

grep -op '((?<=get\s)|(?<=post\s))[^?\s]+' storm.log | sort \ | uniq -c | sort -n > request.sort

(?<=get\s)這個正則叫作零寬斷言,是將要被匹配文字前面的條件,即除非前面有』get 『出現,後面的才匹配。

上面的指令碼得到以下結果:

從這張圖我們便可以找出程式方面的瓶頸了,因為上面這些請求大部分都是ajax請求,所以明顯的,像』users/getuser』、』games/getservers/sxd』這樣的資料請求完全可以被瀏覽器快取起來,而』users/logoutservice』根據我們的業務邏輯也顯得毫無必要,將這三項請求砍掉能節省將近60%的資源!

以下便是通過優化程式**後13號應對的又一次風暴結果。

看到沒,』/users/getuser』請求減少了將近一半,而』/games/getserver/sxd』則減少了近75%,總量減少了近40%!然而』/users/logoutservice』卻不盡如人意,只少了三成,我們待會再尋找其原因。

通過以上程式的優化和一些系統配置的調整,這次風暴只將我的伺服器負載公升高到了10+,並在十幾秒後就很快地平穩了下來,和前一天的200+相比,可以說成功地解決了短暫風暴的問題。

第四步,找出**

上一步遺留了乙個問題,即我明明優化了程式,去掉了不必要的』users/logoutservice』,為何在風暴中,它依然出現了那麼多次,所以我決定分析$http_referer,找出這些請求都是從哪來的。

根據日誌的格式,$http_referer前面都有乙個$body_bytes_sent、乙個空格和乙個雙引號,例如

因為$body_bytes_sent始終是個數字,這樣就可以通過以下正則來找出**

grep -p '\/users\/logoutservice?' storm.log \ | grep -op '(?<=\d\s")[^?"]+' | sort | uniq -c | sort -n > logout.referer.sort

先過濾出logout的日誌,再通過零寬斷言找出**。得到的結果出乎我意料,來自於乙個我在上一步中已經調整過的頁面,明明去掉了不必要的』users/logoutservice』請求,為何還會重複出現?仔細觀察**後並沒發現可疑的地方,於是推測是cdn快取的問題,這些使用者用的js版本可能還是前一天的,清理快取,加上版本號,期待下次風暴來驗證這一推論!

負向零寬斷言

如果我們只是想要確保某個字元沒有出現,但並不想去匹配它時怎麼辦?例如,如果我們想查詢這樣的單詞 它裡面出現了字母q,但是q後面跟的不是字母u,我們可以嘗試這樣 b w q u w b 匹配包含後面不是字母u的字母q的單詞 但是如果多做測試 或者你思維足夠敏銳,直接就觀察出來了 你會發現,如果q出現在...

vim 零寬斷言

vim 中使用零寬度斷言,包括 符號vim符號 描述示例 vim示例 正先行斷言 存在 foo bar foo bar 負先行斷言 排除 foo bar foo bar 正後發斷言 存在 foo bar foo bar?負後發斷言 排除 foo 先行斷言和後發斷言都屬於非捕獲簇 不捕獲文字 也不針對...

負向零寬斷言

前面我們提到過怎麼查詢不是某個字元或不在某個字元類裡的字元的方法 反義 但是如果我們只是想要確保某個字元沒有出現,但並不想去匹配它時怎麼辦?例如,如果我們想查詢這樣的單詞 它裡面出現了字母q,但是q後面跟的不是字母u,我們可以嘗試這樣 b w q u w b匹配包含後面不是字母u的字母q的單詞。但是...