Javaに関する様々な情報をご紹介します。

Javaに関する様々な情報をご紹介します。
評価

40

springアプリへの151回目のアクセスで必ず500エラーになる

自作のspringアプリへ連続アクセスする負荷テストを行っているのですが、必ず151回目で500エラー(Whitelabel Error Page)になってしまいます。
151回目以降もアクセスできるよう下記を試みたのですが、やはり500エラーになってしまい困っております。
皆様の力をお借りできれば幸いです。
不足の情報等ありましたら、ご指摘をお願いいたします。

使用IDE: eclipse 4.23.0
WARファイル作成方法: プロジェクトを右クリック→実行→Maven Install

1)組み込みTOMCATを無効にする
-----application.properties-----
spring.main.web-application-type=none
----------------------------------

2)server.xmlを編集
-----server.xml(一部抜粋)-----
<Connector port="8080" protocol="HTTP/1.1"
                  connectionTimeout="20000"
                  redirectPort="8443"
                  maxThreads="100000"
                  acceptCount="100000"/>
--------------------------------

5

回答

258

閲覧

5件の回答

評価

30

Whitelabel Error Pageは、発生したエラーに対応するエラーページが用意されていないというだけで、エラー自体はアプリで発生しているものだと考えられる。
spring周りの設定の問題ではないので、それを見直したところで何にもならない。

自作アプリのどこかに、151回目でエラーが発生する要因がある。
それはアプリそのものが分からなければまったく想像すらできない。

評価

0

ご回答くださり誠にありがとうございます。
ご回答がヒントとなり自己解決出来ました。

負荷テストを行ったページには、どれもデータベース(MySQL)からデータを参照する処理が入っており、MySQLの最大接続数の設定が問題でした。
151回目(正確には152回目でしたが)でエラーが返ってきたのは、デフォルトの最大接続数が151だったためでした。
Javaやspringとは、ずれた問題点となってしまっていたのはすみません。

そこでまずは、「my.cnf」に「max_connections=100000」という行を付け足しました。
次にMySQLにログインして、
show global variables like 'max_connections';
とコマンドを打った結果なぜか、「9190」という値が返ってきたので、
set global max_connections = 100000;
とコマンドを打ったら今度は「100000」に設定されていました。
これだと、mysqldを再起動するたびにコマンドを打ち、設定する必要がありますがとりあえずは解決です。

ただ、「my.cnf」に設定を書き足した場合に、最大接続数が「9190」という値になったのはなんでなんだろう?と疑問には思っています。

評価

30

解決していない。

そもそもコネクションの使い方がおかしい。
コネクションは使い終わったら返却(クローズ)するものだが、そのように作っていないからリクエストのたびにコネクションが増え、最大接続数に達してしまう。

通常は、何度リクエストしてもコネクション数は1であり、最大接続数には達しない。
同時にそれだけのリクエストを処理しない限りは。
(場合によっては1リクエスト中で複数のコネクションを使うこともあるが)

評価

0

おかげさまで今度こそ根本解決しました。

セッションの開始と同時にセッションがJDBCのConnectionクラスを保持し、セッション切れと同時にConnectionクラスをCloseする。
インターセプタークラス内でセッション切れを感知したら上記の処理でセッションを開始する。

ここまでの実装は問題ないと思うのですが、コントローラークラス内でセッションからConnectionクラスを取り出せない場合に一連のセッションを開始処理しなおす処理が完全に蛇足でした。
WebMvcConfigurerクラスを実装したクラスで、Autowiredしていたインターセプターインスタンスの変数名にスペルミスがありました。
そのため、インターセプタークラス内の処理がされず、ページアクセス毎に上記のセッション開始処理がされていたので、セッションもデータベース接続数も増え続ける形になってしまっていました。

スペルミスを修正し、ページアクセス毎の無駄な処理を消した結果、セッション数もデータベース接続数も変に増えないようになりました。

ご指摘いただき誠にありがとうございました。

評価

0

>セッションの開始と同時にセッションがJDBCのConnectionクラスを保持し、
セッションが保持している理由はあるのだろうか。

通常、Webアプリのセッションはそれなりに長いが、その中でリクエストを処理している時間は短く、しばしば非常に短い。
クライアント側の処理時間と行き帰りの時間の方が長く、その間DBコネクションは使われもしないのに保持しておかれることになる。

DBコネクションの基本的な考え方は、リクエストの開始とともに取得し、最後に解放する。
Javaの変数も同じだが、スコープは極力小さくする。

それなりの数のリクエストを受け付ける、かつコネクションの取得解放コストが大きいと判断される場合は、コネクションプールというものを使うことが多い。
これはDBコネクションをアプリケーション単位で一元管理する手法。
Tomcatも持っているので、それを使えば新たなライブラリを必要とせず導入できる。
ただしこの場合も、実装部分ではリクエストのたびに取得し、その終了ともに解放するという考え方は変わらない。

自分で長期間保持して使い回す構成には、他にも懸念がある。
何らかのネットワークの問題でコネクションが維持できなくなると、一連のリクエストの途中でDBアクセスがエラーになってしまう。
そのケアはできているだろうか。

回答する

ログインしていません。

ログインしなくても回答はできますが、ログインすると、質問・回答の管理、更新があった場合のメールでの通知を受けることができます。 アカウントをお持ちでない方は会員登録を行ってください。

ユーザ名匿名