windymelt / p2p2ch

2ch like p2p bbs by Scala
BSD 3-Clause "New" or "Revised" License
11 stars 1 forks source link

しばらく運用するとスレッド一覧情報取得ができなくなる #5

Closed hangingman closed 9 years ago

hangingman commented 10 years ago

タイトルの通り、ログを貼り付けます https://gist.github.com/Hiroyuki-Nagata/7888399

Caused by: java.util.NoSuchElementException: None.get とあるので、すでになくなったノードを参照しているとかですかねえ…?

p2p2ch起動から問題発生まで約7時間ぐらいです。 エラーログは、スレッド一覧情報を取得した際に発生します。

hangingman commented 10 years ago

この現象が起こると、書き込み時にはタイムアウトとなります 以下にログを貼り付けます https://gist.github.com/Hiroyuki-Nagata/7888474

とりあえずログは採取できたのでp2p2chは再起動しときます

windymelt commented 10 years ago

ここでエラーが発生しています。

val nd = stateAgt().selfID.get.getClient(stateAgt().selfID.get)

この行ではノードの自己IDを取得し、さらに自己ノードと通信しようとしています。Option.getは中身がnullだったりNoneだったりすると例外を発生します。コードの前提として、ノードの自己IDは「設定済み」として処理を進めています。ノードの初期化時に必ずノードIDは設定されるからです。

原因はといいますと、おそらく内部でのなんらかのエラーによりChordCoreが再起動しています。(Akkaのアクターはエラーが発生すると例外を発生させずに自動的に再起動し、障害発生を回避しようとします)。再起動(インスタンスの再作成)の過程でノードは自己に関する情報(ノードIDや接続先など)を忘れてしまうので、再起動の後に、Stabilizerからのスレッドキャッシュの更新要求などを受けた際、自己のノードIDなどを取得しようとし、エラーとなります。おそらくほとんどの処理に自己のノードIDが必要になるため、そのままエラーのまま固まった状態になります。

init(nodeID)を呼び出すことでノード情報は再構築され、同時にノードIDも設定されますが、その際に保持していたデータを放棄してしまいます。

エラー時にデータなどを引き継がせる処理を実行させるべきですが、大抵エラーの原因はそのノードのデータなので、どう引き継がせるかが問題になります。 ノードの再起動にフックしデータを引き継がせる処理そのものは簡単に実装できます。

設定のデータベースにログを取るというのも考えられますが、データベースはDHTシステムからはアクセスできません。普通にログをconsoleに表示することになりそうです。

また、エラーをそもそも発生させないようにするのが先決です。なんらかのエラーが発生したら、その原因をログに留めて無視するべきでしょう。

再起動の原因となったエラー自体は不明です。

hangingman commented 9 years ago

最近これ起きてないです

hangingman commented 9 years ago

問題が起きていないのでクローズします