一次現網翻車經歷與總結

lhyt發表於2018-12-29

0. 前言

還是和平時一樣,做完需求,測試通過,愉快地上線。運營側在大推,推了好幾天。突然有一天,都來反饋說頁面自己彈出dialog而且關不掉:

image

這就奇怪了,都跑了幾天的專案沒問題,怎麼突然翻車了?

背景:一個專門做活動的git專案,僅在微信和手Q環境執行。用的是preact,專案結構是該有的都有,pages下每一個資料夾都是一個頁面,也能支援第2級資料夾一個頁面。每一個活動頁面就是一個資料夾,互不影響,mpa。我們的ci系統很慢,部署大專案需要幾分鐘,然後加上各種環節最快要半小時走完流程,接下來很快將會用另一個方案替代。我活動已經上線幾天,是一個運營活動,推廣那些學習課程的。同事他們另一個活動後來上線,是一個年度總結活動。突發現網問題,時間非常非常緊張而且是2018最後一工作日前一天晚上,而且我們兩個活動必須在元旦前發出去(運營壓時間的活動準時上線的重要性大家應該都懂)

專案資料夾

pages
-- act1資料夾
---- conponents
---- index.jsx
---- index.html
-- act2資料夾
---- act4資料夾(都同上)
---- act5資料夾
-- act3資料夾
複製程式碼

最後act1.html,act4.html,act5.html,act3.html都是不同頁面

1. 開始第一次排查

都上線幾天,突然出事,可以肯定的是,不是業務的bug。剩下的原因:現網資源被更改、npm包被更新。跑了一下主分支master程式碼,沒問題。npm run dist模擬生產環境也沒問題。

經過詢問,原來同事剛剛釋出,發完還沒合併主分支。一看他的分支,果然是更新了。查了一下ci系統,也找到了記錄。於是,切換他的分支跑起來專案程式碼,然後打斷點,彈出方法的函式根本都沒有進去,而且控制彈框彈出的state都不是true

image

這種情況,首先讓我懷疑人生一陣,程式碼明明沒問題而且state也沒有讓他彈出來。於是再對比現網的和我之前釋出的正常版本,來到同一個頁面,發現新程式碼的主邏輯js多了10行程式碼!!一瞬間我馬上想到的是babel外掛的問題。因為我正在用同事寫的一個Babel外掛,功能就是在react的jsx中寫類似像vue那種命令。

現網彈框無解彈出關不掉 =》 所對應的state並沒有為true =》 程式碼多了10行 =》 babel外掛有問題

2. 升級基礎庫版本之坑

問了一下,原來他為了fix那個外掛在preact中的一些坑和更新了preact-compact。為什麼呢?因為他們的活動需要引入antd不然時間上有風險,引入antd在目前preact的版本並不能跑起來需要升級。升級完成後,antd大部分元件可以正常使用,但select元件是undefined無法使用,效果就是一個叫undefined的什麼都沒有的標籤渲染在頁面上,所以他在能跑大部分antd元件的基礎上,再手寫一個很完美的select。

但是,就是因為升級,導致這個外掛有bug。時間緊急,也沒有時間去管。定位到問題,馬上叫測試回滾,現網我的活動正常執行。接下來的計劃是,我把所有的用了指令的地方改回常規方法,然後跟著他們一起發出去。對於版本,測試穩定後,把package.json的^號去掉,把版本穩定下來。剛剛好,他們那邊被leader們盯得緊,一些體驗問題也要改,所以我也可以坐個順風車。我改完了,自測沒問題,先撤了。他們改完了也自測通過,已是差不多10點,部署上了預釋出。

晚上的時候,看見企業微信上的他們順利上預釋出的訊息,我也放心了,心裡想著第二天過去驗證一波就上線。

必須要用antd =》不能用只能升級基礎庫 =》 導致babel外掛問題出現(作者也投入需求沒時間理)=》 我的活動和年度總結活動一起放同一個分支上線

3. 預釋出資源丟失

當我在公司,代理配置上了預釋出,發現資源404和502,一些主js丟失頁面崩潰。而且有的手機有快取復現不了,連電腦修改ua跑微信環境也發現大部分圖片資源失敗。一開始想到的就是我們的ci系統有點坑,重新部署一次就可以。浪費半小時,結果還是一樣。這時候,去檢查資源,經過老司機們的同心協力,確定了原因以及解決方案:

我們的部署是增量部署,也就是類似於電腦複製貼上,有衝突的覆蓋無衝突的不變。我前幾天上線,今天也改了新程式碼但是一些靜態資源和一些頁面完全沒有變化,cdn對映也不變,資源名字還是資源+原雜湊。問題的根源:這週週一的時候,機器上的檔案被清了一次,現在才知情。於是手動把資源拷貝到伺服器上,順利跑起來預釋出環境。此時,炸出了這邊資源匹配規則不合理的問題,應該改進一下。

預釋出資源404和502 =》 機器被清理過 =》 手動補回資源

4. 突然發現遺漏點

預釋出如期而至跑起來,預釋出驗證流程愉快走起,沒問題後全量釋出現網,釋出留守時,拉了一堆人體驗都沒有問題。忽然,一個產品反映,有一個課程不能購買,提示:“請先測試”。測試?什麼鬼?測試的東西跑到現網去了?但是又不是必現的問題,某些課程存在這個問題。於是抓包拿到錯誤碼,後臺說不知道這是什麼原因,我也突然很絕望,leader看見我這樣,說:“來,跟我走,我們一起去找他們,不要在這裡發企業微信,這樣你要搞到什麼時候。” 我們找到後臺leader,說這個是很久很久之前的邏輯,需要考試才能買這種課(才知道原來課程還有普通的和難的,難的需要考試!這裡的“請先測試”文案太抽象,實在容易讓人疑惑,我們開發和測試一看上去就覺得是我們業務流程中的功能測試)。但是,運營說釋出的時候特地驗證過,她可以買。綜合兩點,只有一個可能,運營很久之前就考過試了。

後來和產品對,最後結論是,產品測試開發都沒有知道這個事情,很久之前的邏輯,而且剛剛好運營自己考過試,一直以來都覺得這一切理所當然。此時,前後端產品測試都在,都帶著各自的leader,反推一系列的問題找出原因達成一致。方案: 下架尖子課程、修改文案、增加跳轉、強行讓購買,考慮到時間緊急,而且運營側必須推尖子課程,最後採取了修改文案的方法,讓使用者下載app去考試,功能等下期需求完善。不得不佩服老員工解決問題能力和團隊溝通能力,如果我自己估計搞到晚上了。

購買難的那種課程彈出“請先測試” =》 這種課程需要考試 =》 除了運營大家都不知道這種邏輯而且運營自測沒問題 =》 確認運營曾經考過試,現在能買課 =》 造成一切理所當然的假象 =》 修改文案、下期完善

5. 相容性

我這邊驗證沒問題,因為之前遭遇過測試低端機比較晚,釋出前很趕而且風險大。剛剛好,他們就遇到了,而且是,部門大老闆用安卓機體驗到一些不好的地方,他們那邊繼續修改。除了一些體驗問題,然後最後定位到一個fastick的庫的問題,是為了解決點透問題的,只是相容性上出了一些問題。後來有一個操作,有一個同事發現來到一個頁面的彈框怎麼都關不掉。問題來了,幾個同事跑的是不同結果。這很明顯是node_modules的問題,根本上還是package.json的版本。經過對比,我們package.json就取掉了^符號而已。

此時,我們的package.json經過幾個過程:我釋出時是舊的react和preact =》 他們有一個環節需要antd升級了compact並刪除了lock.json =》 我的活動發現babel外掛問題,修改程式碼自測通過,一個正則把 package.json的所有^ 去掉保證版本穩定 =》 他們幾個人不同的node_modules

為什麼還有版本坑?於是我們開始了rm -rf掉node_modules重新安裝,後來大家都是一樣的效果了。在我們尋找解決方案的時候,突然才想到,去掉package.json的所有^ 並不能解決問題,這不能阻止依賴中的依賴的版本,說鎖版本最靠譜的還是lock.json。又一番修改,確定最終package-lock.json,終於上線了!

package.json多次被修改 =》 自測穩定並鎖住最終版本

6. 最後

事情並沒有結束,有一個同事把工具庫裡面的一個函式名字寫錯,現網再出bug,很快解決。後來工具庫的作者說這個是廢棄的方法,於是又一波討論下次版本怎麼廢棄沒用的函式。

這次事情引起了很多leader重視,大家都反思並總結,針對問題提出解決方案。

  • 線上資源和預釋出資源不一致 =》 指令碼上的增強(當機器上的檔案被清除,原本的增量部署就會有問題)
  • 部署環境坑 =》 接下來會用新的構建和ci,git push或者打tag會自動部署
  • 版本升級 =》 升級的時候需要全面測試、照顧歷史程式碼、知會
  • 老邏輯 =》 新需求需要問清楚、主動推進整個流程、特殊照顧新人

為什麼用preact?因為小,而且我也喜歡上一些寬鬆語法:style可以寫字串、不用在map元素中寫key屬性、無需擔心對被解除安裝的元件setstate的坑(另一篇文章有講到這個問題)。但是用了preact意味著不能用react新特性,反正目前是這樣,以後應該可以支援。活動頁面效能要求高,而且相容性要做到極致,但preact在我們專案暫時跑不了antd。用不用antd不是問題,但是用不了antd就是一個問題,早晚會踩坑的。

對於我們這個專案,結構就是多頁面,每一個頁面獨立。但是每一次釋出也意味著所有的活動頁面也會被重新發一次。如果修改基礎庫,所有的活動都被影響。我們的方案是:刪掉之前的頁面,釋出的時候利用增量釋出的特性直接發某個需求,但是舊頁面需要找到舊分支才能修改,有點麻煩;或者是穩定版本庫,長期不用動它;或者是先用著,等到要改的時候順便改,舊頁面先在分支中刪掉。路過的大蝦們,對於後續維護上如果有更好的方法可以提一下。

“我只是想安安靜靜寫程式碼”,這是多美好的期望啊,可是事實上並不能,你要照顧整個團隊。大家都是一個team,無論遇到什麼都要一起面對,大家都要聚在一起,誰慢了誰快了都要照顧一下。導師也多次和我說:永遠別以為你自己跑起來專案就完事了。這次說背鍋,貌似誰也沒有特別明顯的背鍋嫌疑。說大家都沒錯,也是有道理,誰都是做好了自己本分而且正常上線,面對任何難題都解決。說大家都錯了,也是說得通,大家都是隻看自己的一畝三分地,沒照顧整個團隊,沒照顧整個專案。

最後一個工作日,雖然跌跌撞撞,但是獲得了成長,給2018職業生涯畫上句號

相關文章