3

システムの同時ユーザー数のスケーリングに問題があります。私のテストでは、同時ユーザー数をスケーリングすると、線形関係でリクエストの期間が直接増加するようです。

16Gb RAM を搭載した (仮想) Ubuntu Quad Core マシンにデプロイされた Java Web アプリケーションを実行しています。Apache Tomcat 7 と MySQl 5.5 データベースを使用しています。Tomcat と MySQL はデフォルト設定を使用しています。私はそれらをまったく構成していません。

私は Apache Benchmark を使用して多数のテストを実行しており、最終的に SQL クエリを作成して 1 行のデータを返しますが、応答サイズは非常に小さくなっています。

Spring の JDBCTemplate と Apache Commons BasicDataSource を使用します。Spring Bean の構成を以下に示します。

<!-- 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 の注釈が付けられています。

これらは私のテストの結果です:

  • 1 リクエストにかかる時間は 0.2 秒です。
  • 10 リクエスト (並行して実行) には 0.9 秒かかります。

したがって、私のアプリケーションがスケーリングしていないことがわかります。問題の原因が何であるかはわかりません。誰かが私が間違っていることを見たり、これをさらに調査できる方法を提案したりできますか?

前もって感謝します、

フィル

アップデート

その他の指標:

  1 リクエスト、同時実行 1 = 0.22 秒
 10 リクエスト、同時実行数 10 = 0.6 秒 (平均)、0.5 (分)
100 リクエスト、同時実行数 100 = 7 (平均)、3.7 (分)
300 リクエスト、同時実行性 300 = 12 秒 (平均)、4.3 (分)
300 リクエスト、同時実行数 300 = 18 秒 (平均)、6.4 (分)

応答サイズは 1kb です。

同じリクエストの試行と同時実行の変更:

300 リクエスト、同時実行数 8 = 合計時間: 14.9 秒
300 リクエスト、同時実行数 20 = 合計時間: 15.3 秒
300 リクエスト、同時実行性 300 = 合計時間: 24 秒

したがって、同時実行数を 8 に減らすと、300 の同時実行数よりも 10 秒速く完了します。8 から増やすと、トランザクションが遅くなります。8 が最も最適な同時実行数のようです。

4

1 に答える 1

3

アプリケーションを並行処理しようとする場合、考慮すべき点がいくつかあります。

まず、サーバーに 4 つのコアがあるからといって、それらすべてが JVM で使用できるわけではありません。ランタイムに問い合わせて、使用可能なコアの数を確認する必要があります。JVM の存続期間中にこれが変更されることも技術的に可能です。まれですが。

次に、環境の物理トポロジを考慮する必要があります。DB はアプリケーションと同じサーバーで実行されていますか? もしそうなら、アプリケーションが何をしているかだけでなく、処理と IO の観点からリソースの追加の競合があります。

これらの点を理解したら、アプリケーションの IO と処理のプロファイルを検討する必要があります。たとえば、素数を見つけてシステム ログに出力するアプリケーションは、事実上 100% の処理と 0% の IO です。このタイプのアプリケーションでは、使用可能なコアよりも多くのスレッドをアプリケーションに配置しても意味がありません。コアは実行中の処理で継続的にビジー状態になり、タスク切り替えのオーバーヘッドが実際にアプリケーションの速度を低下させるからです。

DB に大きく結び付けられたアプリケーションは、通常、処理プロファイルに対して比較的高い IO を持ちますが、読み取りのみを行っており、クエリ対象のデータが論理的に配置されている明確に定義されたデータベースでそれらの読み取りが比較的小さい場合、そのプロファイルは IO バウンドが少なくなります。 . DB セット全体をメモリ内に保持できるかどうか、またはディスク ページングが発生しているかどうかに基づいて、DB のサイズも IO に影響します。

並行処理を初めて使用する場合は、Brian Goetz による Java Concurrency in Practice を読むことを強くお勧めします。そうは言っても、アプリケーションをそのままプロファイリングするという賢明なアプローチをとっています。

于 2012-11-27T11:27:58.620 に答える