4

私は、POST 要求に応答して CGI を介して Apache Web サーバー (Tomcat ではない) で起動される小さなプログラムを作成しています。

プログラムは次のことを行います。

  1. リクエストで http 経由で送信された xml を読み取ります
  2. xml から抽出されたデータを使用してデータベースでストアド プロシージャを実行する
  3. POST リクエストへの応答としてストアド プロシージャの結果を返す

データベースはオラクルです。jdbc OCI を使用してアクセスします。

Class.forName("oracle.jdbc.OracleDriver");

String dbCS = "jdbc:oracle:oci:@//ip:port/service"

Connection conn = DriverManager.getConnection(dbCS, dbUserId, dbPwd);
CallableStatement cs = conn.prepareCall("{ call ? := my_pkg.my_sp(?,?,?,?)}");
cs.registerOutParameter(pReturnValue, OracleTypes.NUMBER);
cs.setInt("p1", p1);
cs.setString("p2", p2);
cs.setString("p3", p3);
cs.registerOutParameter("p_out", Types.VARCHAR);
try {
    cs.executeQuery();
    return cs.getString(pReqResponse);
} finally {
    try {
        cs.close();
   } catch (SQLException ex) {
        //....        
   }
}

単一のリクエストを実行している間、それはうまくいきました(プログラム全体が2秒で終了しました)。ただし、一度に複数の POST リクエストを送信しようとすると、リクエストの量に応じて、すべてのリクエストが一定時間スタックしてしまいました (およそ、10 件のリクエストで 10 秒、15 件のリクエストで 15 秒です)。 )。

コードのどの部分が遅延したかを推定しようとしました。次の 2 行のように見えました。

Connection conn = DriverManager.getConnection(dbConnectionString, dbUserId, dbPwd);
CallableStatement cs = conn.prepareCall("{ call ? := my_pkg.my_sp(?,?,?,?)}");

実行自体はほぼ即座に終了しました。

これはなぜですか?

PS: Windows7 でも同じことを試しました。もちろん、これは Web サーバーから起動されたのではなく、単純なコンソール プロセスとして起動されました。また、ハード ドライブ上のファイルから xml を読み取る必要があります。プログラムの同時に起動されたすべてのインスタンスは、すべて一緒に 1 秒で終了しました。

Apache を介して Linux で高速に動作するのを妨げているのは何ですか?


コメントに基づく

接続のプーリング プロパティを設定しようとしましたが、すべて無駄でした。私は次のことを試しました:

  1. URLにUserIdとPasswordを指定している間

    jdbc:oracle:oci:login/password@//ip:port/service
    

    接続プロパティを設定しようとしました:

     Properties p = new Properties();
     p.setProperty("Pooling", "true");
     p.setProperty("Min Pool Size", "1");
     p.setProperty("Max Pool Size", "10");
     p.setProperty("Incr Pool Size", "4");
    
     Connection conn = DriverManager.getConnection(dbConnectionString, p);
    
  2. OCI Connection Poolingを使用しようとしました:

     OracleOCIConnectionPool cpool = new OracleOCIConnectionPool();
     cpool.setUser("user");
     cpool.setPassword("pwd");
     cpool.setURL(dbConnectionString);
    
     Properties p = new Properties();
     p.put(OracleOCIConnectionPool.CONNPOOL_MIN_LIMIT, "1");
     p.put(OracleOCIConnectionPool.CONNPOOL_MAX_LIMIT, "5");
     p.put(OracleOCIConnectionPool.CONNPOOL_INCREMENT, "2");
     p.put(OracleOCIConnectionPool.CONNPOOL_TIMEOUT, "10");
     p.put(OracleOCIConnectionPool.CONNPOOL_NOWAIT, "true");
     cpool.setPoolConfig(p);
    
     Connection conn = (OracleOCIConnection) cpool.getConnection();
    
  3. Apache DBCP コンポーネントを使用しようとしました:

    basicDataSource = new BasicDataSource();
    basicDataSource.setUsername("user");
    basicDataSource.setPassword("pwd");
    basicDataSource.setDriverClassName("oracle.jdbc.OracleDriver");
    basicDataSource.setUrl(dbConnectionString);
    
    Connection conn = basicDataSource.getConnection();
    

getConnection動作は同じままでした。つまり、すべての同時リクエストで大きな遅延が発生しました。

私の場合、すべての接続が別々のプロセスから確立されており、異なるプロセス間で 1 つのプールから接続を管理することは自明ではないように見えます (ここで間違っていますか??)。

どのようなオプションがありますか? または、おそらく私は何か悪いことをしましたか?また、私は一般的にJavaにまったく慣れていないので、いくつかの基本的なことが欠けている可能性があります..


これは OS または Web サーバーの問題でしょうか? おそらく、コードではなく、そこに何かを設定する必要があります...?


またthin、代わりに clientを使用しようとしましたoci。ただし、それはさらに奇妙に機能しました。最初のリクエストは 1 秒で完了し、2 番目のリクエストは 1分間遅延しました。


Oracle JDBC ドライバーとの並行性が低いと、私と同様の問題が発生します。


最終的に、CGI を介して Apache によって起動されたプロセスが CPU の 100% (およびメモリの大部分のシェア) をすべて占有していたため、十分なリソースがないことがわかりました。残念ながら、非常に単純で基本的なプログラム (xml を読み取り、DB への 1 つの接続を確立してストアド プロシージャを実行する) が同時に 20 回しか起動されず、すべてのリソースを消費する理由はわかりません。

しかし、解決策は確かに非常に明白であるように見えました。サーブレットを使用して Java Web アプリケーションにリファクタリングし、Apache Tomcat と MAGIC にデプロイしました。リソースに目に見える影響を与えることなく、期待どおりに動作し始めました。

4

1 に答える 1