java如何在spring Mvc中使用多线程提高性能
我在我的项目中使用SpringMVC模型。其中控制器从某个第三方应用程序获取请求。 控制器每秒收到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负载(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%左右。这是因为java消耗了100%的资源,而其他进程的消耗非常低。 具有linux操作系统的生产机器。具有128 GB RAM的六核处理器。 谁能告诉我该怎么办
# 1 楼答案
看起来你拧错旋钮了
在你的第一个版本中,你有多达N个线程冲击你的数据库。在servlet容器中的某个地方配置了N。还有做servlet之类的事情,接受连接等等
现在,您又创建了200个线程,这些线程基本上什么都不做,只是访问数据库。在前面的线程进行连接处理时,请求解析是最重要的。因此,您增加了数据库的负载,并将负载添加到上下文切换中(除非您有几百个内核)。 出于某种奇怪的原因,你的数据库没有变得更快
为了提高性能,减少线程池中访问数据库的线程数。在性能下降之前,测量数据库可以处理多少线程
使队列容量足够大,以覆盖需要处理的请求峰值
当这还不够的时候,实现一些能给用户一个有意义的完整答案的东西。比如“对不起……”
然后考虑真正的问题:如何让数据库足够快地处理请求
可能是某些数据库调整已经到位,或者您需要切换到另一个数据库系统,或者save方法的实现需要一些调整
但这一切都是为了一个不同的问题
# 2 楼答案
你的
ThreadPoolTaskExecutor
线程太多。CPU花费大量时间在THRED之间切换上下文。在测试中,您只运行控制器,这样生产环境中就没有其他线程(调用)。核心问题是等待DB,因为它阻塞了线程解决方案
save
操作李># 3 楼答案
在您的案例中,瓶颈是交易(DB)
以下是一些建议:
如果不需要立即保存数据,只需使用异步作业(JMS、内存队列等)