<目次>
(1) Javaのフォーム認証でログインを行うと数回で固まってしまう事象の対処記録
(1-1) 発生事象・エラーメッセージ
(1-2) 原因
(1-3) 対策
(1) Javaのフォーム認証でログインを行うと数回で固まってしまう事象の対処記録
(1-1) 発生事象・エラーメッセージ
フォーム認証(以下の「●前提の設定」)の設定を行い、DB接続を伴う操作を数回実施した所、リクエスト(HTTPリクエスト)の応答が無い状況がずっと続き、永久に応答が来ない事象が発生しました。
●前提の設定
⇒(参考)サーバサイドJavaのFORM認証を用いたログイン画面の開発
⇒(参考)Tomcatのコネクションプールの設定手順
⇒(参考)Tomcatを使ったフォーム認証でユーザ情報をデータベース管理する方法
●事象の動画
こちらが実際の事象の動画です。DB接続を伴う処理(例:ログイン処理、APIのカウントアップ処理)を数回行う中で、最初の数回は特に問題なく動作していたものの、ある回で永久に応答が返って来ない事象が発生しました。
(動画111)通常版
(動画112)ネットワークトラフィック表示あり版
(1-2) 原因
コネクションプールの接続を閉じる操作(close)をせずに連続で使用したため、コネクションプールが全て埋まってしまい、ずっとコネクションの解放待ちで固まってしまっていたため。
実際にDB接続オープン/クローズで、それぞれログを出力した所、オープンの回数よりもクローズの回数が少なく、未開放のコネクションがどんどん滞留している様子が確認できました。
(図121)
(1-3) 対策
DB接続を使用したら必ずclose()処理を忘れずに行う事で、この事象の発生を防止できます。
try{ //# DB接続&何かしらの処理 //#(具体的には、Connection生成⇒Statement生成⇒SQL実行しResultSetに格納など) } catch (SQLException e1) { e1.printStackTrace(); } catch (NamingException e2) { e2.printStackTrace(); } finally { //# DBクローズ処理 //#(具体的には、ResultSet/Statement/Connectionの順番にクローズ) }
(サンプル)
public void DbUpdateApiUseCount (String userid) { int current_count = DbUserUseCount(userid); try{ Context context = new InitialContext(); DataSource ds = (DataSource)context.lookup("java:comp/env/jdbc/LoginTemplate"); //# Connectionインスタンスの生成 conn = ds.getConnection(); //# Statementインスタンスの生成 stmt = conn.createStatement(); //# SQLの実行&ResultSetインスタンスに結果を格納 rs = stmt.executeQuery("[実行するSQL文]"); //# その他の付随処理(結果の取り出しなどもしあれば) } catch (SQLException e1) { e1.printStackTrace(); } catch (NamingException e2) { e2.printStackTrace(); } finally { DbClose(); } } //# クローズ処理 public void DbClose () { try { if(rs != null) {rs.close(); System.out.println("# @@ Connection Closed @@");} if(stmt != null) {stmt.close();} if(conn != null) {conn.close();} } catch (SQLException e) { e.printStackTrace(); } }
(図131)