1. 程式人生 > 其它 >聊聊最近工作中解決的幾個小問題

聊聊最近工作中解決的幾個小問題

最近專案組搞衝刺,忙到爆,五月一篇文章也沒寫,眼看六月又將結束,抓住一個週末抽點時間寫寫最近工作中遇到的幾個小問題,希望能給遇到相同問題的同學些許幫助。

衝刺階段的裝備-紅頭巾)

問題1:使用者進入微信公眾號選單時偶現oAuth2.0授權失敗

問題背景:

我們有些功能以微信公眾號的形式提供出去,為了避免使用者使用時頻繁輸入使用者名稱密碼,所以藉助微信的oAuth2.0鑑權流程實現了免登入的效果,但是有個前提是需要使用者提前做一步繫結操作,將我們體系的userid和微信體系中的openid做一個繫結,只要有了openid就可以關聯到使用者。

下面看下微信oAuth2.0的接入流程。

就在上圖中4.1呼叫開放api獲取access_token時會偶現

{"errcode":40163,"errmsg":"code been used”}

排查過程:

什麼情況下會對同一個auth _code發起重複呼叫呢?

  • 是httpclient(4.1由httpclient發起,所以先懷疑它)的重試嗎?不是,我看了上一次呼叫的日誌,沒有異常而且響應很快,完全不具備httpclient重試的條件。
  • 是業務程式碼的重試嗎?看了程式碼並沒有任何重試的痕跡。
  • 有沒有可能是第4步“帶著auth_code,訪問第三方應用指定的地址”重複請求了呢?帶著這種疑問開始找證據,果不其然,從nginx的access log中很快發現了蛛絲馬跡。
grep auth_code access.log

  

第一次請求

第二次請求

可以看到兩次使用的code是同一個,還有個細節是第一次請求的http狀態碼是499,看下網路上對nginx 499狀態碼的解釋:

499,客戶端關閉連線,這個狀態碼並不是http協議中定義的status code,而是nginx自己定義的一個狀態碼。由於伺服器處理請求較多,客戶端在有效時間內沒有得到答覆,主動關閉了連線。

到這兒我大膽的猜測這是微信客戶端加的一種優化策略,如果某個請求超時,那就斷開重試一次,從上面兩次請求的access log可以得出微信認定的超時時間為20s,正是這種優化才造成了這個問題,怎麼優化呢?

解決方式:

也許有人說這屬於微信的bug啊,作為一個第三方應用提供方我們怎麼優化呢,其實不然,某種角度來說是我們沒有做好“冪等“才導致這種問題發生,微信客戶端在此時只是一個普通的瀏覽器而已,即使它沒有這種“重試”,誰又能保證後面的環節沒有重試發生呢,比如nginx,所以廢話不多說還是把“冪等”做起來,解決方式很簡單,引入redis對auth_code的查詢結果暫存幾分鐘,如果報“code been used

”那就從redis獲取一次。

問題2:站點升級https以後導致附件預覽功能失敗

問題背景:

筆者所在的團隊目前負責B端的業務,涉及到附件預覽,其中附件預覽是獨立的服務,當業務中有附件預覽需求時會重定向到預覽服務進行線上預覽。

大體流程如下:

1.使用者在業務方站點發起預覽請求;

2.業務方拼接相關引數重定向到預覽服務;

3.預覽服務通過業務方傳遞的附件連結呼叫業務方介面下載附件到本地;

4.預覽服務將下載的附件轉換成html、圖片、pdf等供使用者線上預覽。

之前一直執行的好好的,但是業務站點由http升級到https以後有部分使用者反映,附件預覽失敗,報錯截圖如下:

第一反應我是有點懵的,預覽服務本身就是個http地址,怎麼還牽扯到證書了,緊接著我讓客戶把瀏覽器位址列內容複製給我,果然是個https地址,趕快找運營借來測試賬號嘗試復現,結果在我瀏覽器上沒復現出來,在其他同事瀏覽器上覆現了,都是chrome只是版本不一樣,到這裡還是雲裡霧裡的,不知道發生了什麼,猜測可能是瀏覽器做了某些處理導致。

解決方式:

緊急將預覽服務也增加了https支援,問題隨之解決,至於原因我一直沒有找到特別確切的答案,所以在此也就不多說了,猜測是一個叫做HSTS的東西作祟,當你發現http被強制重定向為https的時候希望你可以聯想到它,有興趣的可以看下知乎上ThoughtWorks團隊寫的一篇文章https://zhuanlan.zhihu.com/p/25537440。

問題3:git分支亂合併

最近團隊出現過好幾次git分支合併錯的問題,比較致命的是把開發分支合併到某個release分支上,更誇張的是居然運行了一個晚上,還好第二天一大早就有測試發現了問題,緊急回退才避免了事故擴大。

下圖是我們團隊的git flow流程,和標準的git flow差別不小,目前我們有固定的迭代週期和發版計劃,所以整體流程和TrunkBased很相似,直接在master開發,到達發版節點以後釋出master程式碼,釋出完成以後拉取release分支,用來做歷史版本bug的修復。

某天晚上有個小哥修改bug,本意可能是改完了把release合回master,但是手抖居然合反了,導致線上執行著未經測試的程式碼,想想我都一頭汗,事後他過來找我。

“哥,幫我回退下程式碼,昨天把程式碼合錯了”

“嗯”(我咬著後槽牙回答到)

問題雖然解決了,同時也映射出我們的程式碼合併流程其實是存在問題的,試圖通過一種口口相傳的方式顯然是不行的,得想辦法藉助工具來解決,通過調研我大概發現有以下兩種辦法:

1.在git服務端設定保護分支,只允許某幾個人的合併,甚至只能通過MR的方式來合併分支,將風險性行為交給團隊內“德高望重“的人來實施;

2.在git客戶端通過git hook的方式來實施,檢測到某些風險合併時拒絕merge。

最終我使用客戶端hook的方式規避這種風險,主要原因是想讓開發者提前意識到這種問題,不要把風險往後傳遞。

實踐方式如下:

1. 在.git\hooks目錄下實現commit-msg這個hook,git已經內建了這個檔案只是增加了sample字尾,刪除sample就會啟用這個hook;

2. 編寫檢測指令碼,這段引用自網際網路,侵刪。

https://www.cnblogs.com/SteelArm/p/12773485.html

#!/bin/sh

BLACKLIST=("master" "origin/master")
forbid_list=()

if [[ -e .git/MERGE_HEAD ]]; then
  heads=`ls .git/refs/heads`

  for bl in "${BLACKLIST[@]}"; do
    if [[ -n `echo ${heads} | grep -oP "(^| )${bl} "` ]]; then
      forbid_list+=(`cat .git/refs/heads/${bl}`)
    fi
  done

  merge_head=`cat .git/MERGE_HEAD`
  for br in "${forbid_list[@]}"; do
    if [[ ${merge_head} == ${br} ]]; then
      echo -e "\033[41;37m 合併了黑名單中的分支 \033[0m\n\r"
      echo -e "\033[41;37m 請使用 git merge --abort 命令終止合併 \033[0m"
      exit 1
    fi
  done
fi

3. 最終效果,如果錯誤合併了會報錯提示;

寫在最後

以上是我近期工作中遇到的幾個比較有意思的問題,在這裡分享出來,希望下一次你遇到同樣問題的時候能帶來些許幫助。