用 scrapy 寫爬蟲時 ,過程中碰到有一些網(wǎng)頁元素需要通過 JS 加載,而且獲取數(shù)據(jù)的 API 限制重重,這種情況下選擇 splash 來進行渲染往往是最好的選擇了。然而使用下來的體驗,包括網(wǎng)絡(luò)上也有相同的抱怨,那就是 splash 雖好,但太不穩(wěn)定了。在高強度負載下,掛掉幾乎是必然的。接下來記錄我遇到的其中一種死法:
問題
操作系統(tǒng):macOS 10.13.4
Docker 版本:18.03.0-ce
splash 版本:3.2
描述:
對頁面進行持續(xù)渲染時,scrapy 會突然拋出 splashrequest 返回 timeout 的異常,這時 splah 服務(wù)其實已經(jīng)掛掉了。在 docker 中查看容器,發(fā)現(xiàn)狀態(tài)為Exited (1),接著在日志中發(fā)現(xiàn)掛之前留下的最后記錄為:
The X11 connection broke (error 1). Did the X11 server die?
在 splash 運行一段時間后,這個問題總是會隨機出現(xiàn)。
解決
問題出現(xiàn)以后上網(wǎng)查了下相似的情況,發(fā)現(xiàn)不是很多,而且并不是 splash 的特有問題,在嘗試了調(diào)整延時、修改 Docker 使用的內(nèi)存大小無效后,最后在 splash 的 github 中的一個 iusses 里,找到了一個方法:
This may just be coincidence and may not apply to everyone else's crashing but I noticed that Docker started crashing when I added the following and stopped crashing when I removed it.
splash.images_enabled = false
恰好我的設(shè)置里也包含了這一項,不加載圖片可大大提高爬蟲效率,一開始看到時不認為這個設(shè)置會導致問題的發(fā)生,最后將這一項設(shè)為true后,問題竟然解決了...
如果你的情況和我一樣,可以嘗試使用這個方案,但不能保證一定能解決你的問題。
曲線救國
因為每次修改后需要長時間運行來檢測問題是否被解決,所以解決這個問題用了較長的時間,最后問題雖然解決了,但仍舊不知道具體原因,可謂是一次失敗的 debug 了。
是否有更好的解決方案?答案是肯定的,既然 splash 老掛又找不到原因,那么我們可以讓其掛了以后 restart 嘛,后來在官方 FAQ 中發(fā)現(xiàn)了如下方法:
A command for starting a long-running Splash server which uses up to 4GB RAM and daemonizes & restarts itself could look like this:
$ docker run -d -p 8050:8050 --memory=4.5G --restart=always scrapinghub/splash:3.1 --maxrss 4000
上述語法可以限制容器所用內(nèi)存,并在占用內(nèi)存超過設(shè)定值/容器掛掉時重啟容器,一種曲線救國的方法。
寫到這里不禁反思,在產(chǎn)品設(shè)計中許多場景也是這樣,雖然好的產(chǎn)品設(shè)計和用戶體驗通常是正相關(guān)的,但在現(xiàn)實中,由于種種原因(技術(shù)限制、終端差異、用戶素質(zhì)),我們必須在好設(shè)計和好體驗中找到平衡。
后記
其實心里一直有個疑問,這個錯誤日志究竟是什么意思?在這里稍作記錄:
X11 是什么?
X11 是 unix 和 linux 控制和顯示圖形界面的協(xié)議,和 http 協(xié)議類似,X 程序端通過 X 協(xié)議向 X server 傳輸需要在顯示器上顯示的信息,并由 X server 負責執(zhí)行,X server 同時負責將用戶輸入的信息返回 X 程序端。和 http 協(xié)議不同的一點是,這里的 X server 通常是面向用戶的。
splash 為什么會用到 X ?
splash 的運行依賴 Docker ,而 Docker 的守護進程是基于 linux 的。由于 splash 支持WebKit 中的 Web Inspector ,所以會用到 X 。(待考證)
說了這么多,到底為什么會 crash ?
很遺憾,目前仍舊未知。留個坑,希望以后可以為自己解答吧....