簡體   English   中英

如何在Spring Mvc中使用多線程來提高性能

[英]How to improve performance using multithreading in spring Mvc

我在項目中使用spring MVC模型。 哪個控制器從某個第三方應用程序獲取請求。 控制器每秒獲得20個請求。 代碼看起來像這樣

@Controller
@RequestMapping("/action")
public class FrontController{

@AutoWired
private CommonService commonService;

(First Code)
@RequestMappint("/save")
public String saveData(@PathParam("id")String did){

    List<String, Object> map = commonService.getVmn(did);
    CallReporting callReporting = new CallReporting();
    callReporting.setName(map.get("name"));
    so---on (have 15 field)
    commonService.save(callReporting);
    }

    return "1";
}

這段代碼可以正常工作,但是如果mysql很忙,則需要一段時間才能將值返回給調用應用程序。 因此,我放棄了主意,開始進行異步通信。

(Second Code)
@RequestMappint("/save")
public String saveData(@PathParam("id")String did){

    Thread thread = new Thread(new Runnable(){
        List<String, Object> map = commonService.getVmn(did);
        CallReporting callReporting = new CallReporting();
        callReporting.setName(map.get("name"));
        so---on (have 15 field)
        commonService.save(callReporting);
    });
    }

    return "1";
}

我開始使用類似這樣的代碼。 這樣主叫方可以立即獲得響應(減少響應時間),然后在我的應用程序上繼續工作。 但是在第一個代碼中,我用JMeter(20 req / sec)測試了負載,發現它在cpu load(3%)下工作正常。 但是在具有相同負載的第二個代碼中,CPU負載將超過100%。然后我開始使用具有以下配置的ThreadPoolTask​​Executor。

@AutoWired
private ThreadPoolTaskExecutor executor;

@RequestMappint("/save")
public String saveData(@PathParam("id")String did){

//Assume this code is in MyRunnableWorker Class
        List<String, Object> map = commonService.getVmn(did);
        CallReporting callReporting = new CallReporting();
        callReporting.setName(map.get("name"));
        so---on (have 15 field)
        commonService.save(callReporting);

    MyRunnableWorker worker = new MyRunnableWorker();
    executor.execute(worker)

    return "1";
}

<bean id="taskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
    <property name="corePoolSize" value="50" />
    <property name="maxPoolSize" value="100" />
    <property name="keep-alive" value="10" />
    <property name="queueCapacity" value="200" />
</bean>

但發現相同的結果。 代碼有什么問題可以有人建議我。 當我在階段測試中使用Jmeter進行測試時,一件重要的事情是負載在30%到70%之間移動。但是在生產服務器中,負載總是在100%左右。 它消耗了100%其他進程的Java相當低。 生產機器具有linux OS。 具有128 GB RAM的六核處理器。 有人可以告訴我該怎么做。

您的ThreadPoolTaskExecutor過多。 CPU花大量時間在thred之間切換上下文。 在測試中,您僅運行控制器,因此生產環境中不存在其他線程(調用)。 核心問題是等待數據庫,因為它阻塞了線程

解決方案

  • 設置較小的池(進行一些實驗)
  • 刪除執行程序,並使用Akka之類的actor系統進行save操作。
  • 最重要的是使用批處理將對象保存在DB中 每1000個對象只有一個調用,而不是1k對象的1k調用> JPA / Hibernate提高了批處理插入性能

看來您在轉動錯誤的旋鈕。

在第一個版本中,最多有N個線程在破壞數據庫。 使用N在您的servlet容器中的某個位置配置。 還要做一些servlet,接受連接和填充。

現在,您創建了200個其他線程,這些線程除了訪問數據庫外基本上不執行任何操作。 當先前的線程進行連接處理時,請求進行解析。 因此,您增加了數據庫的負載,並且將負載do添加到上下文切換中(除非您有數百個內核)。 出於某些奇怪的原因,您的數據庫並沒有獲得更快的速度。

為了提高性能,請減少影響數據庫的線程池中的線程數。 測量性能降低之前數據庫可以處理多少個線程。

使queueCapacity足夠大以覆蓋您需要處理的請求峰值。

當這還不夠時,實施一些能夠給用戶有意義的答案的事情。 諸如“對不起...”之類的東西

然后處理一個真正的問題:如何使數據庫足夠快地處理請求。

可能是某些數據庫調整已經到位,或者您需要切換到其他數據庫系統,或者也許save方法的實現需要一些調整...

但這一切是一個不同的問題。

您遇到的瓶頸是交易(DB)

這是一些建議:

  1. 如果不需要立即保存數據,則只需使用異步作業即可完成(JMS,內存隊列等)

  2. 您可以考慮將DB加載到RAM中

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM