頭條資訊 - 為您提供最新最全的新聞資訊,每日實時更新

可惡的爬蟲直接把生產 6 臺機器爬掛了!

科技數碼 CSDN

作者 | 碼農二胖  責編 | 張文

頭圖 | CSDN 下載自視覺中國

可惡的爬蟲直接把生產 6 臺機器爬掛了!

前言

正在午睡,突然收到線上瘋狂報警的郵件,查看這個郵件發現這個報警的應用最近半個月都沒有發佈,應該不至於會有報警,但是還是打開郵件通過監控發現是由於某個接口流量暴增,CPU暴漲。

為了先解決問題只能先暫時擴容機器了,把機器擴容了一倍,問題得到暫時的解決。

最後覆盤為什麼流量暴增?由於最近新上線了一個商品列表查詢接口,主要用來查詢商品信息,展示給到用戶。業務邏輯也比較簡單,直接調用底層一個 soa 接口,然後把數據進行整合過濾,排序推薦啥的,然後吐給前端。

這個接口平時流量都很平穩。線上只部署了 6 臺機器,面對這驟增的流量,只能進行瘋狂的擴容來解決這個問題。擴容機器後問題得到暫時的解決。後來經過請求分析,原來大批的請求都是無效的,都是爬蟲過來爬取信息的。

這個接口當時上線的時候是裸著上的也沒有考慮到會有爬蟲過來。

解決辦法

既然是爬蟲那就只能通過反爬來解決了。自己寫一套反爬蟲系統,根據用戶的習慣,請求特徵啥的,瀏覽器 cookie、同一個請求頻率、用戶 ID、以及用戶註冊時間等來實現一個反爬系統。

直接接入公司現有的反爬系統,需要按照它提供的文檔來提供指定的格式請求日誌讓它來分析。既然能夠直接用現成的,又何必自己重新造輪子呢。

最後決定還是採用接入反爬系統的爬蟲組件。爬蟲系統提供了兩種方案如下:

方案 1:

爬蟲系統提供批量獲取黑名單 IP 的接口(getBlackIpList)和移除黑名單 IP 接口(removeBlackIp)。業務項目啟動的時候,調用 getBlackIpList 接口把所有 IP 黑名單全部存入到本地的一個容器裡面(Map、List),中間會有一個定時任務去調用 getBlackIpList 接口全量拉取黑名單(黑名單會實時更新,可能新增,也可能減少)來更新這個容器。

每次來一個請求先經過這個本地的黑名單 IP 池子,檢驗 IP 是否在這個池子裡面。如果在這個池子直接返回爬蟲錯誤碼,然後讓前端彈出一個複雜的圖形驗證碼,如果用戶輸入驗證碼成功(爬蟲基本不會去輸入驗證碼),然後把 IP 從本地容器移除,同時發起一個異步請求調用移除黑名單 IP 接口(removeBlackIp),以防下次批量拉取黑單的時候又拉入進來了。然後在發送一個 activemq 消息告訴其他機器這個 IP 是被誤殺的黑名單,其他機器接受到了這個消息也就會把自己容器裡面這個 IP 移除掉。

其實同步通知其他機器也可以通過把這個 IP 存入 redis 裡面,如果在命中容器裡面是黑名單的時候,再去 redis 裡面判斷這個 ip 是否存在 redis 裡面,如果存在則說明這個 ip 是被誤殺的,應該是正常請求,下次通過定時任務批量拉取黑名單的時候,拉取完之後把這個 redis 裡面的數據全部刪除,或者讓它自然過期。

這種方案:性能較好,基本都是操作本地內存。但是實現有點麻煩,要維護一份 IP 黑名單放在業務系統中。

可惡的爬蟲直接把生產 6 臺機器爬掛了!

方案 2:

爬蟲系統提供單個判斷 IP 是否黑名單接口 checkIpIsBlack(但是接口耗時有點長 5s)和移除黑名單 IP 接口(removeBlackIp)。每一個請求過來都去調用爬蟲系統提供的接口(判斷 IP 是否在黑名單裡面)這裡有一個網絡請求會有點耗時。

如果爬蟲系統返回是黑名單,就返回一個特殊的錯誤碼給到前端,然後前端彈出一個圖形驗證碼,如果輸入的驗證碼正確,則調用爬蟲系統提供的移除 IP 黑名單接口,把 IP 移除。

這種方案:對於業務系統使用起來比較簡單,直接調用接口就好,沒有業務邏輯,但是這個接口耗時是沒法忍受的,嚴重影響用戶的體驗。

最終綜合考慮下來,最後決定採用方案 1。畢竟系統對響應時間是有要求的儘量不要增加不必要的耗時。

方案 1 實現

方案 1 偽代碼實現,對於讀多寫少的線程安全的容器我們可以選擇 CopyOnWrite 容器。

上線後經過一段時間讓爬蟲系統消費我們的請求日誌,經過一定模型特徵的訓練,效果還是很明顯的。

由於大部分都是爬蟲很多請求直接就被攔截了,所以線上的機器可以直接縮容掉一部分了又回到了 6 臺。

但是好景不長,突然發現 GC 次數頻繁告警不斷。為了暫時解決問題,趕緊把生產機器進行重啟(生產出問題之後,除了重啟和回退還有什麼解決辦法嗎),並且保留了一臺機器把它拉出集群,重啟之後發現過又是一樣的還是沒啥效果。

通過 dump 線上的一臺機器,通過 MemoryAnalyzer 分析發現一個大對象就是我們存放 IP 的大對象,存放了大量的的 IP 數量。這個 IP 存放的黑名單是放在一個全局的靜態 CopyOnWriteArraySet,所以每次 gc 它都不會被回收掉。只能臨時把線上的機器配置都進行升級,由原來的 8 核 16g 直接變為 16 核 32g,新機器上線後效果很顯著。

為啥測試環境沒有復現?測試環境本來就沒有什麼其他請求,都是內網 IP,幾個黑名單 IP 還是開發手動構造的。

解決方案

業務系統不再維護 IP 黑名單池子了,由於黑名單來自反爬系統,爬蟲黑名單的數量不確定。所以最後決定採取方案 2 和方案 1 結合優化。

項目啟動的時候把所有的 IP 黑名單全部初始化到一個全局的布隆過濾器

一個請求過來,先經過布隆過濾器,判斷是否在布隆過濾器裡面,如果在的話我們再去看看是否在 redis 白名單裡面(誤殺用戶需要進行洗白)我們再去請求反爬系統判斷 IP 是否是黑名單接口,如果接口返回是 IP 黑名單直接返回錯誤碼給到前端;如果不是直接放行(布隆過濾器有一定的誤判,但是誤判率是非常小的,所以即使被誤判了,最後再去實際請求接口,這樣的話就不會存在真正的誤判真實用戶)。如果不存在布隆器直接放行。

如果是被誤殺的用戶,用戶進行了 IP 洗白,布隆過濾器的數據是不支持刪除(布穀鳥布隆器可以刪除(可能誤刪)),把用戶進行正確洗白後的 IP 存入 redis 裡面。(或者一個本地全局容器,mq 消息同步其他機器)下面我們先來了解下什麼是布隆過濾器吧。

什麼是布隆過濾器

布隆過濾器(英語:Bloom Filter)是 1970 年由布隆提出的。它實際上是一個很長的二進制向量和一系列隨機映射函數。布隆過濾器可以用於檢索一個元素是否在一個集合中。它的優點是空間效率和查詢時間都遠遠超過一般的算法,缺點是有一定的誤識別率和刪除困難。

上述出自百度百科。說白了布隆過濾器主要用來判斷一個元素是否在一個集合中,它可以使用一個位數組簡潔的表示一個數組。它的空間效率和查詢時間遠遠超過一般的算法,不過它存在一定的誤判的概率,適用於容忍誤判的場景。如果布隆過濾器判斷元素存在於一個集合中,那麼大概率是存在在集合中,如果它判斷元素不存在一個集合中,那麼一定不存在於集合中。

實現原理

布隆過濾器的原理是,當一個元素被加入集合時,通過 K 個散列函數將這個元素映射成一個位數組(Bit array)中的 K 個點,把它們置為 1 。檢索時,只要看看這些點是不是都是 1 就知道元素是否在集合中;如果這些點有任何一個  0,則被檢元素一定不在;如果都是 1,則被檢元素很可能在(之所以說“可能”是誤差的存在)。

底層是採用一個 bit 數組和幾個哈希函數來實現。

可惡的爬蟲直接把生產 6 臺機器爬掛了!

下面我們以一個 bloom filter 插入"java" 和"PHP"為例,每次插入一個元素都進行了三次 hash 函數。

java 第一次 hash 函數得到下標是 2,所以把數組下標是 2 給置為 1;java 第二次 Hash 函數得到下標是 3,所以把數組下標是 3 給置為 1;java第三次 Hash 函數得到下標是 5,所以把數組下標是 5 給置為1;PHP 第一次 Hash 函數得到下標是 5,所以把數組下標是 5 給置為 1...

查找的時候,當我們去查找 C++ 的時候發現第三次 hash 位置為 0,所以 C++ 一定是不在不隆過濾器裡面。但是我們去查找“java”這個元素三次 hash 出來對應的點都是 1。只能說這個元素是可能存在集合裡面。

布隆過濾器添加元素

將要添加的元素給 k 個哈希函數

得到對應於位數組上的 k 個位置

將這 k 個位置設為 1

布隆過濾器查詢元素

將要查詢的元素給 k 個哈希函數

得到對應於位數組上的 k 個位置

如果 k 個位置有一個為 0,則肯定不在集合中

如果 k 個位置全部為 1,則可能在集合中

使用 BloomFilter

引入 pom

解決問題

布隆過濾器介紹完了,我們再回到上述的問題,我們把上述問題通過偽代碼來實現下;

總結

上述只是列舉了通過 IP 來反爬蟲,這種反爬的話只能應對比較低級的爬蟲,如果稍微高級一點的爬蟲也可以通過代理 IP 來繼續爬你的網站,這樣的話成本可能就會加大了一點。

爬蟲雖然好,但是還是不要亂爬。“爬蟲爬的好,牢飯吃到飽”。

程序員如何避免陷入“內卷”、選擇什麼技術最有前景,中國開發者現狀與技術趨勢究竟是什麼樣?快來參與「2020 中國開發者大調查」,更有豐富獎品送不停!

轉載請超鏈接註明:頭條資訊 » 可惡的爬蟲直接把生產 6 臺機器爬掛了!
免責聲明
    :非本網註明原創的信息,皆為程序自動獲取互聯網,目的在於傳遞更多信息,並不代表本網贊同其觀點和對其真實性負責;如此頁面有侵犯到您的權益,請給站長發送郵件,並提供相關證明(版權證明、身份證正反面、侵權鏈接),站長將在收到郵件24小時內刪除。
加載中...