1

サーブレット (Tomcat 7.0.X および Ubuntu Linux 内で実行) によって提供される RESTful サービスを提供しています。私はすでに 1 時間あたり約 20,000 件のクエリを取得しており、さらに増えるでしょう。サーブレットはリクエストを受け取り、レスポンスを準備し、MySQL データベース テーブルにレコードを挿入し、レスポンスを配信します。データベースのログは絶対に必須です。最近まで、これらすべてが同時に起こっていました。つまり、Tomcat スレッドが応答を配信する前に、データベース テーブルにレコードを作成する必要がありました。問題は、このログが合計時間の 90% 以上を占めていたことです。さらに悪いことに、データベースが遅くなると、サービスはわずか 20 ミリ秒ではなく、約 10 ~ 15 秒かかりました。

私は最近改善を行いました:各Tomcatスレッドは、「(新しいスレッド(新しい特定のオブジェクト)).start();」を実行する追加のスレッドを作成します これにより、SQL 挿入が非同期的に処理されるため、クライアントへの応答が速くなります。しかし、これらのスレッドは、MySQL の実行が遅くなり、スレッドが増加すると、大量の RAM を消費し、スレッドが数千になると、JVM Tomcat がメモリを使い果たします。

私が必要としているのは、可能な限り多くの HTTP リクエストを受け入れ、それらのすべてを可能な限り高速に (同期ではなく) ログに記録し、MySQL が遅くなって挿入されたときにすべてを高速化し、RAM の使用量を非常に少なくすることです。キューに入れる必要があります。http リクエストの速度がデータベース ログへの挿入速度よりも速い場合、エントリをバッファリングするためのある種のキューが必要だと思います。

私はこれらのアイデアについて考えています:

1- ある種の FIFO キューを自分で作成します。おそらく、これらの Apache コモンズ コレクションのいくつかと、コレクションをポーリングしてデータベース レコードを作成するある種のスレッドを使用します。しかし、どのコレクションを使用すればよいでしょうか? また、CPU を独占しないように、スレッドをポーリングするスレッドをどのようにプログラムすればよいでしょうか? 「Do while (true)....」は CPU サイクルを食い尽くすと思います。そして、それをスレッドセーフにすることについてですか?どうやってするの?自分でやるのは大変な労力だと思います。

2-log4J? 直接使用したことはありませんが、このフレームワークは、データベースと通信する「アペンダー」を作成するように設計されているようです。それはそれを行う方法でしょうか?

3-これを専門とする他のフレームワークを使用していますか?

何を提案しますか?

前もって感謝します!

4

3 に答える 3

0

まず第一に: 貴重な提案をありがとうございました!

これまでのところ、私は自分のニーズに対する部分的な解決策を見つけており、すでにそれをうまく実装しています:

http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/LinkedBlockingQueue.html

現在、キュープロバイダーがいっぱいになった場合は、フェイルオーバーソリューションとしてキュープロバイダーも使用することを考えています. ここまでAmazonのキューサービスについて考えてきましたが、お金がかかります。また、Ryan が提案したキュー ソリューションも確認します。

于 2013-01-27T03:42:23.503 に答える
0

すぐに思いつくのは、あなたが言ったようなキューです。ActiveMQ http://activemq.apache.org/や RabbitMQ http://www.rabbitmq.com/などを使用できます。

アイデアは、ただ発砲して忘れることです。メッセージを送信するためのオーバーヘッドはほとんどありません。

次に、いくつかの「オフライン」に接続して、キューからメッセージを取得し、必要な速度でデータベースに書き込むことができます。

一日中 Stack Overflow にプラグインしているように感じますが、これを行うために職場で Mule (http://www.mulesoft.org/) を使用しています。Mule の優れた点の 1 つは、キューから読み取るスレッドの数と、データベースに書き込むスレッドの数を明示的に設定できることです。これにより、メッセージのスロットリングをきめ細かく制御できます。

于 2013-01-26T05:10:59.563 に答える
0

ThreadPoolExecutor の使用をぜひ検討してください。スレッド プールのサイズを指定すると、すべての同時実行とキューイングが処理されます。考えられる唯一の問題は、何らかの理由で JVM がクラッシュした場合、プール内のキューに入れられたアイテムが失われることです。

http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/ThreadPoolExecutor.html

また、MySQL データベースを可能な限り最適化することも検討します。1 時間あたり 20,000 件のエントリがあると、すぐに大変なことになります。ハードウェア、OS、およびインデックスが最適化されているほど、挿入が速くなり、キューが小さくなります。

于 2013-01-26T05:22:28.320 に答える