Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/363.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何在SpringMVC中使用多线程提高性能_Java_Multithreading_Spring_Spring Mvc - Fatal编程技术网

Java 如何在SpringMVC中使用多线程提高性能

Java 如何在SpringMVC中使用多线程提高性能,java,multithreading,spring,spring-mvc,Java,Multithreading,Spring,Spring Mvc,我在我的项目中使用SpringMVC模型。其中控制器从某个第三方应用程序获取请求。 控制器每秒收到20个请求。代码是这样的 @Controller @RequestMapping("/action") public class FrontController{ @AutoWired private CommonService commonService; (First Code) @RequestMappint("/save") public String saveData(@PathPar

我在我的项目中使用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";
}
我开始使用类似这样的代码。因此,呼叫方可以立即得到响应,从而缩短响应时间,稍后我的应用程序将继续工作。但在第一个代码中,我使用JMeter20 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的六核处理器。 谁能告诉我该怎么做。

您的ThreadPoolTaskExecutor线程太多。CPU花费大量时间在THRED之间切换上下文。在测试中,您只运行您的控制器,所以生产环境中不存在其他线程调用。核心问题是等待DB,因为它阻塞了线程

解决方案

将池大小设置为较小的值进行一些实验 移除executor并使用actor系统(如Akka)进行保存操作。 最重要的是使用批处理在数据库中保存对象。每1000个对象只有一个调用,而不是1k对象的1k调用> ThreadPoolTaskExecutor的线程太多。CPU花费大量时间在THRED之间切换上下文。在测试中,您只运行您的控制器,所以生产环境中不存在其他线程调用。核心问题是等待DB,因为它阻塞了线程

解决方案

将池大小设置为较小的值进行一些实验 移除executor并使用actor系统(如Akka)进行保存操作。 最重要的是使用批处理在数据库中保存对象。每1000个对象只有一个调用,而不是1k对象的1k调用>
看起来你拧错旋钮了

在第一个版本中,最多有N个线程冲击数据库。在servlet容器中的某个地方配置了N。还有做servlet之类的事情,接受连接等等

现在您又创建了200个额外的线程,这些线程基本上什么也不做,只是访问数据库。在前面的线程进行连接处理时,请求解析是最重要的。因此,您增加了数据库的负载,并将负载添加到上下文切换中,除非您有数百个内核。 出于某种奇怪的原因,你的数据库没有变得更快

为了提高性能,减少线程池中访问数据库的线程数。在性能下降之前,测量数据库可以处理多少线程

使队列容量足够大,以覆盖需要处理的请求峰值

当这还不够的时候,实现一些能给用户一个有意义的完整答案的东西。比如说抱歉

然后考虑真正的问题:如何使数据库足够快地处理请求

可能是某些数据库调优已经到位,或者您需要切换到其他数据库系统,或者save方法的实现需要一些调优


但这一切都是为了一个不同的问题。

看起来你拧错了旋钮

在第一个版本中,最多有N个线程冲击数据库。在servlet容器中的某个地方配置了N。还有做servlet之类的事情,接受连接等等

现在您又创建了200个额外的线程,这些线程基本上什么也不做,只是访问数据库。在前面的线程进行连接处理时,请求解析是最重要的。因此,您增加了数据库的负载,并将负载添加到上下文切换中,除非您有数百个内核。 出于某种奇怪的原因,你的数据库没有变得更快

为了提高性能,减少线程池中访问数据库的线程数。在性能下降之前,测量数据库可以处理多少线程

使队列容量足够大,以覆盖需要处理的请求峰值

当这还不够的时候,实现一些能给用户一个有意义的完整答案的东西。比如说抱歉

然后考虑真正的问题:如何使数据库足够快地处理请求

可能是某些数据库调优已经到位,或者您需要切换到其他数据库系统,或者save方法的实现需要一些调优

但这一切都是为了
另一个问题。

你的瓶颈是交易数据库

以下是一些建议:

如果不需要立即保存数据,只需使用异步作业(JMS、内存队列等)即可

可以考虑将DB加载到RAM


你的瓶颈是交易

以下是一些建议:

如果不需要立即保存数据,只需使用异步作业(JMS、内存队列等)即可

可以考虑将DB加载到RAM


好吧,为什么cpu负载在我没有使用线程池的第二个代码中增加。第二,我不能在这种情况下使用批次。原因系统经常收到请求,然后用户将在MIS部分查看这些条目。另一个原因是某些时间系统处于空闲阶段。所以我必须一对一打db,同样的原因。你创建了很多线程。超过内核数。请阅读Amdahl定律这是一个很好的解释,为什么创建大量线程会降低性能。好吧,为什么cpu负载在第二个代码中增加,而我没有使用线程池。第二,我不能在这种情况下使用批次。原因系统经常收到请求,然后用户将在MIS部分查看这些条目。另一个原因是某些时间系统处于空闲阶段。所以我必须一对一打db,同样的原因。你创建了很多线程。超过内核数。请阅读Amdahl定律,这是一个很好的解释,为什么创建大量线程会降低性能。如果db事务是一个问题,那么为什么cpu负载在第一种情况下没有增加意味着没有线程代码可以正常工作。cpu负载是由于线程正在等待获取资源,正如我认为的那样connectionPool my be be Minor 200 connections线程被迫等待,直到有可用的连接才能运行TX。例如,您可以打电话了解是否有可用的连接,如果没有,那么睡眠线程直到连接准备好,但这是一件奇怪的事情,我绝对不会使用如果db事务有问题,那么为什么cpu负载没有增加在第一种情况下意味着没有线程代码工作正常。cpu负载是由于线程正在等待获取资源,正如我所认为的那样connectionPool my be be Minor 200 connections线程被迫等待,直到有可用的连接才能运行TX。例如,您可以打电话了解是否有可用的连接,如果没有,那么睡眠线程直到连接准备好,但这是一件奇怪的事情,我绝对不会使用你能告诉我什么是执行器配置的最佳值,每秒有15个请求。就像核心尺寸、最大尺寸和最大容量一样,我在回答中告诉你们:测量它。任何其他答案都是谎言。你能告诉我每秒15个请求的Executor配置的最佳值是什么吗。就像核心尺寸、最大尺寸和最大容量一样,我在回答中告诉你们:测量它。任何其他答案都是谎言。