一次接口的性能優化之旅

一、引言

在項目開發過程中,我們經常會遇到接口響應慢的問題。這不僅影響了用戶體驗,還可能降低了系統的吞吐量。爲了提高接口性能,我們需要對整個系統進行全面的優化,包括代碼層面、數據庫、緩存、異步處理等方面。本文將分享一個接口性能優化之旅,希望能幫助大家掌握Pfinder使用、JSF異步調用等優化技巧,提升接口性能和定位問題的能力。

二、現狀診斷

UMP診斷:
Max:10s
T99:1000ms
經常可用率下降





 





 

Pfinder診斷:
問題1:循環調用RPC 120次=1441ms
問題2:查詢DB 286ms
問題3:未知操作 2000ms+





 

三、問題定位以及性能優化

如何解決Pfinder顯示耗時不全問題:-> 手動完善全程跟蹤上報

1. 集成Pfinder SDK:
<!-- 引用 PFinder SDK 庫 -->
<dependency>
    <groupId>com.jd.pfinder</groupId>
    <artifactId>pfinder-profiler-sdk</artifactId>
    <version>1.2.2-FINAL</version>
</dependency>

1. 使用註解:@PFTracing





 

1. 上報效果





 

1. 定位問題和進行代碼分析





 

這段代碼的目的是從一個名爲waveInfos的字符串列表中,篩選出已經包含在另一個名爲sendDPackageCodes的字符串列表中的元素,並將這些重複的元素放入一個新的列表repeatResult中。然後,它從waveInfos中排除這些重複的元素,將剩餘的元素放入另一個新的列表showPackages中。這兩個列表最終被用於前端顯示或進一步處理。簡而言之,這段代碼的作用是去重並篩選出尚未處理的數據。



通過現象查看此處代碼耗時佔總耗時進一半左右,因此判斷集合數據非常多,導致數據計算耗時較長。通過日誌打印發現:waveInfos=3000+,sendDPackageCodes=7000+,因此可以看出兩個集合因爲數據過大導致耗時較長。





 

代碼優化:使用Set進行處理





 





 

優化效果:2000ms -> 6ms

如何解決RPC批量調用問題 -> 使用JSF異步調用

同步異步方案比較

優劣勢 異步調用 同步調用
優勢 提高系統的併發性能 簡單直觀
 提高系統的響應速度 錯誤處理方便
 節約資源 
劣勢 複雜性 阻塞線程
 可讀性差 響應速度慢

JSF異步調用使用

第一步:如果存在同步bean,爲了不影響同步bean可以注入新的異步bean。需要

注意:jsf 這邊相同接口 別名 最多支持3個

// 同步bean
@Autowired
private XxxxxApi xxxxApi;
// 異步實現bean,(jsf 這邊相同接口 別名 最多支持3個)
@Autowired
private XxxxxApi xxxxAsyncApi;

<!-- 【異步】路由查詢班次單號明細 -->
<jsf:consumer id="xxx" interface="xxx"
              protocol="jsf" alias="xx" timeout="xxx" retries="0" check="false">
    <jsf:method name="方法名稱" async="true"/>
</jsf:consumer>

第二步:使用RpcContext調用,返回CompletableFuture對象

// Rpc代理類 需要返回CompletableFuture 對象
public CompletableFuture<CommonDto<PageDto>> queryWaybillDetailByBusinessIdByAsync() {
    // 發起方法請求
    return RpcContext.getContext().asyncCall(() -> xxxxAsyncApi.method());;
}

第三步:調用處任意地方,獲取future返回結果,需要指定超時時間

public <T> T getResultDefaultTimeOut(CompletableFuture<T> future) {
    try {
        return future.get(10, TimeUnit.SECONDS);
    } catch (InterruptedException | ExecutionException | TimeoutException e) {
        throw new RuntimeException(e);
    }
}

優化效果:1400ms -> 200ms

五、最終效果和未解決問題

優化前優化後

問題 優化前 優化後 方案
總耗時 3800ms 500ms 
rpc循環調用 1400ms 200ms JSF異步調用(N次耗時變一次最大耗時)
數據笛卡爾積處理 2000ms 6ms list包含操作變set包含操作
數據庫操作 100ms 100ms 數據庫批量查詢,此期不處理
未知操作 150ms 150ms 非業務代碼,懷疑是sql查詢後結果處理,目前無法跟蹤和處理,此期不處理

六、總結

接口性能優化是一個涉及多個方面的過程,需要從代碼層面、數據庫、緩存、異步處理等多個維度進行優化。在這個過程中,我們需要不斷診斷瓶頸、嘗試優化手段,並結合實際情況進行調整。希望通過本文的分享,大家能掌握接口性能優化的方法和技巧,提高接口性能,提升用戶體驗。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章