系统无法扩展以支持并发用户 [英] System not scaling to support concurrent users

查看:157
本文介绍了系统无法扩展以支持并发用户的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在扩展系统上的并发用户数时遇到问题.根据我的测试,扩展并发用户数似乎直接增加了线性关系中请求的持续时间.

I'm having a problem with scaling the number of concurrent users on my system. From my tests, scaling the number of concurrent users seems to directly increase the duration of a request in a linear relationship.

我正在运行Java Web应用程序,该Java Web应用程序部署在具有16Gb RAM的(虚拟)Ubuntu四核计算机上.我正在使用Apache Tomcat 7和MySQl 5.5数据库. Tomcat和MySQL使用默认设置-我没有进行任何配置.

I am running a Java Web Application deployed on a (virtual) Ubuntu Quad Core machine with 16Gb RAM. I am using Apache Tomcat 7 and a MySQl 5.5 Database. Tomcat and MySQL are using the default settings - I have not configured them in any way.

我正在使用Apache Benchmark运行许多测试,这些测试最终创建一个SQL查询以返回一行数据,其中响应大小非常小.

I am using Apache Benchmark to run a number of tests which ultimately create a SQL query to return one row of data, where the response size is very small.

我使用Spring的JDBCTemplate和Apache Commons BasicDataSource. Spring bean的配置如下所示.

I use Spring's JDBCTemplate, and a Apache Commons BasicDataSource. The spring bean's configuration is shown below.

<!-- READ ONLY CONNECTION TO DATABASE -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
  <property name="driverClassName">
    <value>com.mysql.jdbc.Driver</value>
  </property>
  <property name="username">
    <value>${database.username}</value>
  </property>
  <property name="password">
    <value>${database.password}</value>
  </property>
  <property name="url">
    <value>${database.url}/${database.schema}</value>
  </property>
  <property name="timeBetweenEvictionRunsMillis" value="7200000" />
  <property name="minEvictableIdleTimeMillis" value="3600000" />
  <property name="maxActive" value="100" />
  <property name="maxIdle" value="5" />
  <property name="defaultAutoCommit" value="false" />
  <property name="defaultReadOnly" value="true" />
</bean>

<bean id="myDao" class="...">
   <property name="jdbcTemplate" ref="jdbcTemplate"></property>
   <property name="dataSource" ref="dataSource"></property>
</bean>

<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
   <property name="dataSource" ref="dataSource" />
</bean>

我创建几个查询的Java方法使用@Transactional注释.

My Java method that creates a couple of queries is annotated with @Transactional.

这些是我测试的结果:

  • 1个请求需要0.2秒.
  • 10个请求(同时执行)需要0.9秒.

因此,您可以看到我的应用程序没有扩展.我不确定是什么原因造成的.谁能看到我在做错事情,或提出进一步调查此事的建议吗?

Thus you can see my application is not scaling. I'm not sure what the cause of the problem could be. Can anyone see what I am doing wrong or suggest ways in which I can investigate this further?

预先感谢

菲尔

更新

其他指标:


  1 Request,  Concurrency   1 = 0.22s
 10 Requests, Concurrency  10 = 0.6s (mean), 0.5(min)
100 Requests, Concurrency 100 = 7 (mean), 3.7(min)
300 Requests, Concurrency 300 = 12s (mean), 4.3(min)
300 Requests, Concurrency 300 = 18s (mean), 6.4(min)

响应大小为1kb.

尝试相同的请求&更改并发:

Trying same requests & changing the concurrency:


300 Requests, Concurrency   8 = total time: 14.9s
300 Requests, Concurrency  20 = total time: 15.3s
300 Requests, Concurrency 300 = total time: 24s

因此,将并发减少到8会比并发300快10秒钟完成.从8并发增加会减慢事务的速度. 8似乎是最优化的并发.

So reducing the concurrency to 8 completes 10s quicker then a concurrency of 300. Increasing from 8 slows down transactions. 8 seems to be the most optimum concurrency.

推荐答案

在尝试使应用程序并发时,需要考虑一些事项.

There are a few things to consider when trying to make an application concurrent.

首先,仅因为您的服务器具有四个内核,并不意味着它们对JVM都可用,因此您需要询问运行时以查看有多少个可用内核,并且从技术上讲,在以下情况下也可以更改该内核: JVM,尽管很少见.

Firstly, just because your server has four cores, does not mean they are all available to your JVM, you need to interrogate the runtime to see how many are available and it is also technically possible for this to change during the lifetime of the JVM, although rare.

接下来,您需要考虑环境的物理拓扑.数据库是否与应用程序在同一服务器上运行?如果是这样,那么您在处理和IO方面还有更多的资源争用,而不仅仅是您的应用程序在做什么.

Next, you need to consider the physical topology of your environment. Is the DB running on the same server as the application? If so you have additional contention for resources in terms of processing and IO, not just what your application is doing.

一旦您了解了这些要点,就需要考虑应用程序的IO与处理配置文件.例如,查找素数并将其输出到系统日志的应用程序实际上是100%处理,而IO是0%.在这种类型的应用程序中,没有比可用内核更多的线程,因为这些内核将持续忙于它们的工作,而任务切换的开销实际上会使您的应用程序变慢.

Once you have got an understanding of those points, you need to consider the IO vs. Processing profile of your application. An application which is finding prime numbers and outputting them to the system log for example is virtually 100% processing vs. 0% IO. In this type of application there is no point in having more threads in your application than there are available cores as the cores will be continuously busy with what they're doing and the overhead of task switching will actually slow down your application.

与数据库紧密相关的应用程序通常具有相对较高的IO到处理的配置文件,尽管如果仅读取并且使用定义良好的数据库(其中要查询数据的数据库)读取的数据相对较小,则该配置文件的IO绑定将减少逻辑布局.数据库的大小也会影响IO,具体取决于整个数据库集是否可以保留在内存中或是否发生磁盘分页.

An application heavily tied to a DB would generally have a relatively high IO to Processing profile, although that profile becomes less IO bound if you are only reading and those reads are relatively small with a well defined database where the data being queried is logically laid out. The size of the DB will also impact IO, based on whether the entire DB set can be kept in memory or whether disk paging is occurring.

如果您不熟悉并发性,我强烈建议您阅读Brian Goetz的实践中的Java并发性.话虽这么说,您正在按原样对应用程序进行性能分析是一种明智的方法.

I'd highly recommend reading Java Concurrency in Practice by Brian Goetz if you are new to concurrency. That being said, you are taking a sensible approach by profiling your application as you are.

这篇关于系统无法扩展以支持并发用户的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆