[英]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%。然后我開始使用具有以下配置的ThreadPoolTaskExecutor。
@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之間切換上下文。 在測試中,您僅運行控制器,因此生產環境中不存在其他線程(調用)。 核心問題是等待數據庫,因為它阻塞了線程
解決方案
save
操作。 看來您在轉動錯誤的旋鈕。
在第一個版本中,最多有N個線程在破壞數據庫。 使用N在您的servlet容器中的某個位置配置。 還要做一些servlet,接受連接和填充。
現在,您創建了200個其他線程,這些線程除了訪問數據庫外基本上不執行任何操作。 當先前的線程進行連接處理時,請求進行解析。 因此,您增加了數據庫的負載,並且將負載do添加到上下文切換中(除非您有數百個內核)。 出於某些奇怪的原因,您的數據庫並沒有獲得更快的速度。
為了提高性能,請減少影響數據庫的線程池中的線程數。 測量性能降低之前數據庫可以處理多少個線程。
使queueCapacity足夠大以覆蓋您需要處理的請求峰值。
當這還不夠時,實施一些能夠給用戶有意義的答案的事情。 諸如“對不起...”之類的東西
然后處理一個真正的問題:如何使數據庫足夠快地處理請求。
可能是某些數據庫調整已經到位,或者您需要切換到其他數據庫系統,或者也許save方法的實現需要一些調整...
但這一切是一個不同的問題。
您遇到的瓶頸是交易(DB)
這是一些建議:
如果不需要立即保存數據,則只需使用異步作業即可完成(JMS,內存隊列等)
您可以考慮將DB加載到RAM中
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.