いくつかの背景
私は、Java EE 1.4 で書かれた 1999 年からの時代遅れの非常に単純な書店 Web アプリケーションを使用するプロジェクトに取り組んでいます。ただし、Amazon AWS のようなクラウド環境で実行するためにモダナイズすることが目的です。Spring フレームワーク、Hibernate、および接続プール用の c3p0 を使用して最初から書き直すことにしました。
Web アプリケーションのほかに、RBE (Remote Browser Emulator) と呼ばれる Web アプリケーション用のストレス ツールも入手しました。必要なユーザー数を RBE に伝えるだけで、RBE はユーザーごとに 1 つのスレッドを作成します。各スレッドはランダムに URL を生成しており、ユーザーがページを閲覧している限り (ユーザーがサイトを閲覧する時間を 180 秒間と定義しています)、URL はランダムに生成されます。その後、スレッドをシャットダウンします。リクエストごとに HTML ページ ソースを取得し、jsessionid を解析してから次の URL に進みます。
問題
400 ユーザー (つまり、1 秒あたり 400 要求) に対して RBE を実行すると、すぐに次の例外が発生します。
java.net.SocketException: Connection reset by peer
at java.net.PlainSocketImpl.socketConnect(Native Method)
at java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:382)
at java.net.PlainSocketImpl.connectToAddress(PlainSocketImpl.java:241)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:228)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:431)
at java.net.Socket.connect(Socket.java:527)
at sun.net.NetworkClient.doConnect(NetworkClient.java:158)
at sun.net.www.http.HttpClient.openServer(HttpClient.java:388)
at sun.net.www.http.HttpClient.openServer(HttpClient.java:523)
at sun.net.www.http.HttpClient.<init>(HttpClient.java:227)
at sun.net.www.http.HttpClient.New(HttpClient.java:300)
at sun.net.www.http.HttpClient.New(HttpClient.java:317)
at sun.net.www.protocol.http.HttpURLConnection.getNewHttpClient(HttpURLConnection.java:970)
at sun.net.www.protocol.http.HttpURLConnection.plainConnect(HttpURLConnection.java:911)
at sun.net.www.protocol.http.HttpURLConnection.connect(HttpURLConnection.java:836)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1172)
at rbe.EB.getHTML(EB.java:423)
at rbe.EB.run(EB.java:324)
しばらくして、RBE が他のサブページをブラウズしようとすると、次のように表示されます。
java.net.ConnectException: Operation timed out
at java.net.PlainSocketImpl.socketConnect(Native Method)
at java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:382)
at java.net.PlainSocketImpl.connectToAddress(PlainSocketImpl.java:241)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:228)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:431)
at java.net.Socket.connect(Socket.java:527)
at sun.net.NetworkClient.doConnect(NetworkClient.java:158)
at sun.net.www.http.HttpClient.openServer(HttpClient.java:388)
at sun.net.www.http.HttpClient.openServer(HttpClient.java:523)
at sun.net.www.http.HttpClient.<init>(HttpClient.java:227)
at sun.net.www.http.HttpClient.New(HttpClient.java:300)
at sun.net.www.http.HttpClient.New(HttpClient.java:317)
at sun.net.www.protocol.http.HttpURLConnection.getNewHttpClient(HttpURLConnection.java:970)
at sun.net.www.protocol.http.HttpURLConnection.plainConnect(HttpURLConnection.java:911)
at sun.net.www.protocol.http.HttpURLConnection.connect(HttpURLConnection.java:836)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1172)
at rbe.EB.getHTML(EB.java:423)
at rbe.EB.run(EB.java:324)
EB.java:423)
(例外が発生した場所)のコードは次のとおりです。
BufferedReader in = new BufferedReader( new InputStreamReader(connection.getInputStream() ) );
私のmy.cnf
構成:
[mysqld]
log=/var/log/mysqld.log
max_connections = 200
log-slow-queries = /var/log/mysqld_slow_queries.log
log-error = /usr/local/mysql/data/mysql-error.log
back-log = 200
key_buffer_size=16M
max_allowed_packet=100M
interactive_timeout=30
wait_timeout=30
の Tomcat 関連の設定server.xml
:
<Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443" acceptCount="500" />
また、テストを行い、静的 html ファイルを 2 秒の遅延で提供し、データベースとの反復は行いませんでした。このテストを行って、Tomcat が 400 の同時要求を処理できないかどうかを確認しました。Tomcat はこのテストに合格しました。
mysql への 400 の同時アクセスのボトルネックは何ですか? これはMySQLには多すぎますか?