關于搶購活動技術方案的一些思考
- 前言
- 搶購活動到底要不要限流?
- 超時問題的排查程序
- 關于壓測
- 總結
- 題外話
前言
去年的合作專案,隨著業務量的不斷增加,之前的技術方案最侄訓是被流量給打爛了,所以說技術方案是需要不斷地升級和改良的,不該在有點成績的時候就沾沾自喜,而失去了對業務量增大會造成后續問題的技術敏感性,
搶購活動到底要不要限流?
之前根據活動的數量,在nginx做了第一步的限流措施,當流量達到閾值時,請求只能等待,但合作方的做法是,請求時間超過5秒就當作失敗處理,導致了一些時間過長的請求,雙方的資料狀態是不一致的,造成這個問題的原因有兩點,一是溝通不到位,在問題出現前不知道對方有超過5秒就當作失敗處理的邏輯,二是根據業務的屬性,失敗是沒有辦法做補償的,必須要保證接受到的請求回傳都是成功的,所以這里不適合限流策略,只能去盡可能的提升系統的吞吐量,
超時問題的排查程序
高并發的介面,對于查詢操作都是基于快取,盡量減少對資料庫的操作,包括insert陳述句,當對方提出生產介面超時的情況后,我根據相關的日志輸出,發現介面的耗時基本都是毫秒級的,但從nginx的日志來看,確實有回應超過6秒的請求,并且不少,于是我根據例外的處理在日志中搜索,也沒有發現有任何的堆疊資訊,最后架構師提醒我,可能不是exception,而是error了,果然,活動期間有大量的error日志,

再跟進去看,問題就很明顯了,例外沒有捕獲到的原因也很簡單,SQLTransientConnectionException不屬于RuntimeException,所以在例外捕獲的地方沒有日志,

下單介面最后在保存訂單資料時,等待資料庫連接資源時超時了,百度一下相關的錯誤資訊,得出了以下結論,
springboot的HikariDataSource默認配置的執行緒池大小和核心執行緒數都是10,這在高并發場景下介面需要同步保存資料是遠遠不夠的,當然,這里的解決方案除了修改資料庫連接池配置外,還可以把訂單保存做成異步的,這個方案的代碼也已經完成,作為了春節的應急方案,但最開始沒這么做的原因也很簡單,介面同步回傳下單成功后,如果用戶馬上去兌換的話,可能會出現異步的保存還沒完成,導致訂單不存在的情況,所以目前生產的解決方案還是通過修改資料庫連接池的配置來解決這個問題,
關于壓測
壓測的重要性和必要性不必多說,但全鏈路的壓測在實際作業中確實存在很多的客觀的原因無法充分進行,之前進行的壓測更多的是對內的介面,對外的介面壓測缺失導致了資料庫連接池的問題沒有被及時發現,并且測驗環境的壓測報告只能作為生產環境的參考,org.testng包已經可以通過代碼去實作多執行緒的并發壓測了,所以測驗環境的壓測開發人員可以使用單元測驗的方式來進行了,
總結
業務級的專案往往會因為溝通造成不少后續的問題,包括結算時間點、對方的例外處理措施等等,以前的流程圖更多的是單邊的業務邏輯,之后在畫流程圖時,我會把對方的例外流程也加上,與對方的技術進行多次的確認,減少由于溝通產生的問題,最后在開發結束后,要開始計劃生產環境的壓測,如果對方不配合,我該怎么去寫偽代碼來完成生產環境的壓測,新的一年要更多的去關注性能上的解決方案,作為開發也要充分掌握壓測的能力,
題外話
在這次的問題排查中,引申出了一個新的問題探討,被@Transactional標注的方法,是在方法開始執行就開啟事務,還是在該方法第一次執行資料庫操作時才開始事務呢?我和同事兩個人意見不一,各有各的理由,最后在請教架構師后,寫了一個簡單的單元測驗,并且把日志級別調成trace,資料庫連接池設定成1,
@Transactional
public void transactionalWhenStartTest(){
log.info("start");
try {
Thread.sleep(3000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
industrialBankOrderService.save(new IndustrialBankOrder());
}
用postman進行簡單壓測發現,事務的開啟從trace級別的日志中可以看到,是方法執行就進行了標記,但與資料庫建立連接開啟事務,是在第一次操作資料庫時,
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/258703.html
標籤:其他
上一篇:MSGraphMailbag - Blazor web 程式集和 Microsoft Graph、Azure Functions 的三層架構
