4

永続的な接続 (Memcached クライアント) のプールがあります。データは memcached サーバーにキャッシュされています。memcached サーバーを再起動した後、プールからクライアントを使用してキャッシュされたデータを取得しようとすると、次の例外が発生します。

java.util.concurrent.ExecutionException: java.lang.RuntimeException: Cancelled
    at net.spy.memcached.MemcachedClient$OperationFuture.get(MemcachedClient.java:1662)
    at net.spy.memcached.MemcachedClient$GetFuture.get(MemcachedClient.java:1708)
    at com.eos.gds.cache.CacheClient.get(CacheClient.java:49)

キャッシュされたデータを取得しようとすると、再起動後に初めてこの例外が発生します。私はたくさんの検索をしました。しかし、これの正確な理由を見つけることができません。

4

5 に答える 5

4

Spymemcached には、操作が実際に memcached に送信される前に配置される一連の内部キューがあります。ここで起こっていることは、ユーザーが操作を実行し、その操作がネットワーク経由で送信される前、または memcached からの応答が受信される前に、Spymemcached が接続が失われたことを認識するということです。その結果、Spymemcached は実行中のすべての操作をキャンセルし、接続を再確立します。

Future で get() を呼び出すと、Spymemcached によって操作がキャンセルされたため、例外がスローされます。ここで私がお勧めするのは、Spymemcached で行うすべての個々の操作ですべての例外をキャッチし、エラーに応じて操作を再試行するか、それを無視することです。たとえば get で、memcached サーバーのクラスターがダウンした場合、キャッシュが空になるため、おそらく忘れることができますが、おそらく set を再試行する必要があります。

于 2011-11-09T17:47:16.760 に答える
0

解決策を何日も探していました。他の誰かに役立つ場合に備えて投稿します。

ServletContextListener の実装は、contextInitialized で新しい MemcachedClient(...) を取得し、contextDestroyed で MemcachedClient メソッドの shutdown() を呼び出します。最初に送信するリクエストでは、常に CancellationException または ExecutionException を取得します。(エラーメッセージは両方をほのめかしましたが、私がキャッチできたのは ExecutionException です。)

解決策: shutdown() から shutdown(1, TimeUnit.SECONDS) に切り替えました

get 呼び出しは、最初の実行時に成功するようになりました。

contextDestroyed 呼び出しがリクエストの通常の処理にどのように干渉していたのか、はっきりとは説明できません。私の推測では、spymemcached の単一のスレッドが何らかの方法でサーブレット間で共有されるため、ビルド プロセスの検証ステップによって送信されたリクエストを処理するためにサーブレットが作成されると、最初に送信するリクエストの前にサーブレットが破棄され、私のリクエストのサーブレットが使用していた MemcachedClient は、同じスレッドを使用しようとし、シャットダウンからの例外でヒットします。

(私たちのチームは、web アプリが memcached サーバーに対して開いている接続が多すぎることを知ったとき、shutdown を呼び出す必要性を確立しました。)

于 2019-06-24T16:32:09.477 に答える