零零好車代碼層面優化系統開發性能應該怎麽做?
我們以前看到的很多架構變遷或者演進方面的文章大多都是針對架構方面的介紹,很少有針對代碼級別的性能優化介紹。本文將針對一些代碼細節方面的東西進行介紹,歡迎大家吐槽以及提建議。服務器環境
-
服務器配置:4 核 CPU,8G 內存,共 4 臺
-
MQ:RabbitMQ
-
數據庫:DB2
-
SOA 框架:公司內部封裝的 Dubbo
-
緩存框架:Redis、Memcached
-
統一配置管理系統:公司內部開發的系統
- 系統開發謝天華 135-0148-8501
問題描述
-
單臺 40TPS,加到 4 臺服務器能到 60TPS,擴展性幾乎沒有。
-
在實際生產環境中,經常出現數據庫死鎖導致整個服務中斷不可用。
-
數據庫事務亂用,導致事務占用時間太長。
-
在實際生產環境中,服務器經常出現內存溢出和 CPU 時間被占滿。
-
程序開發的過程中,考慮不全面,容錯很差,經常因為一個小 bug 而導致服務不可用。
-
程序中沒有打印關鍵日誌,或者打印了日誌,信息卻是無用信息沒有任何參考價值。
-
配置信息和變動不大的信息依然會從數據庫中頻繁讀取,導致數據庫 IO 很大。
-
項目拆分不徹底,一個 Tomcat 中會布署多個項目 WAR 包。
-
因為基礎平臺的 bug,或者功能缺陷導致程序可用性降低。
-
程序接口中沒有限流策略,導致很多 VIP 商戶直接拿我們的生產環境進行壓測,直接影響真正的服務可用性。
-
沒有故障降級策略,項目出了問題後解決的時間較長,或者直接粗暴的回滾項目,但是不一定能解決問題。
-
我們針對線上的環境進行模擬,盡量真實的在測試環境中再現,采用數據庫連接池為咱們默認的 C3P0。
那麽當壓測到二萬批,100 個用戶同時訪問的時候,並發量突然降為零!報錯如下:
com.yeepay.g3.utils.common.exception.YeepayRuntimeException: Could not get JDBC Connection; nested exception is java.sql.SQLException: An attempt by a client to checkout a Connection has timed out.
那麽針對以上錯誤跟蹤 C3P0 源碼,以及在網上搜索資料發現 C3P0 在大並發下表現的性能不佳。
線程池使用不當引起
以上代碼的場景是每一次並發請求過來,都會創建一個線程,將 DUMP 日誌導出進行分析發現,項目中啟動了一萬多個線程,而且每個線程都極為忙碌,徹底將資源耗盡。
那麽問題到底在哪裏呢???就在這一行!
private static final ExecutorService executorService = Executors.newCachedThreadPool();
在並發的情況下,無限制的申請線程資源造成性能嚴重下降,在圖表中顯拋物線形狀的元兇就是它!!!那麽采用這種方式最大可以產生多少個線程呢??答案是:Integer 的最大值!看如下源碼:
那麽嘗試修改成如下代碼:
private static final ExecutorService executorService = Executors.newFixedThreadPool(50);
零零好車代碼層面優化系統開發性能應該怎麽做?