3

ファイルをディスクに書き込み、その他のものをデータベースに書き込む Web サービスがあります。操作全体では、書き込みごとに 1 ~ 2 秒かかります。

このサービスは、ほとんどの場合、複数のクライアントから同時に呼び出される可能性があります。20 のクライアントが同時に Web サービスを呼び出すと仮定して、書き込み操作を同期する必要があります。その場合、何秒も待たなければならないため、一部のクライアントでタイムアウト例外が発生する可能性があります。

この種の状況を解決するための良い方法はありますか? 現在のように、メソッドは同期されています (これにより、飢餓/タイムアウトが発生する可能性があります)。

タイムアウトを回避するために、キーワードを削除してすべてのスレッドを書き込みメソッドにsynchronized入れ、それらのタスクをタスク キューに入れる必要がありますか? それはこれを回避する正しい方法ですか?

4

3 に答える 3

1

を削除しsynchronizedてそれ自体をタスクキューに入れることは役に立ちません(これは、同期が効果的に行っていることだからです)。ただし、Webリクエストをキューに入れたらすぐに応答すると、応答の時間は短くなります。ただし、ユーザーは作業が完了し、実際には作業が行われていないことを確認できるため、ある程度の信頼性が犠牲になります(作業が完了する前にシステムがクラッシュする可能性があります)。

于 2012-04-30T07:40:31.867 に答える
1

Francis Upton の実践は、実際に受け入れられている実践です。

もう 1 つは、よりきめ細かい同期を行うことです。クラスのすべての読み取り/書き込みメソッドを同期する代わりに、同期する必要がある正確な不変条件へのアクセスを同期できます。

さらに良いのは、同期を完全に取り除くことです。これは、java.util.concurrentパッケージを使用して可能です。このパッケージは、ノンブロッキング アルゴリズム( Compare-Ans-Swapアトミック命令を使用して Java で実装)を使用する新しいコレクションを導入します。ConcurrentHashMapなどのこれらのコレクションにより、スケーリング時のスループットが大幅に向上します。

詳細については、この記事を参照してください。

于 2012-04-30T08:14:18.637 に答える
1

このタイプの実装 (増加する負荷の下でサービスが遅くなる) では、タイムアウト処理 (サーバーベースの場合) や必要な I/O を含めて、できるだけ非同期にする必要があります。新しい要求に対するサーバーの応答性を維持するために、これらの時間のかかる操作のいずれかを待機するクライアント応答スレッドを保持しないでください。代わりに、必要な操作を (おそらく動的スレッド プールに対して) 開始し、コールバックに結果を処理させます。タイムアウト、完全な I/O、またはエラーのいずれか。

最初に何が起こったかに応じて適切な応答を送信しますが、エラー/タイムアウト メッセージを送信してから完了した I/O が到着した場合 (I/O とタイマーの間の競合状態が原因で)、I/O をロールバックする準備をしてください。これは、サーバーでトランザクションのセマンティクスが必要であることを意味します。

これは、負荷が大きくなるにつれてますます複雑になる領域ですが、早い段階で優れた設計を行うことで、負荷の増加に合わせて拡張できるようにする必要があります。理想的には、クライアント サービス スレッドがまったくブロックされないようにする必要があります。

于 2012-04-30T11:03:48.947 に答える